<?php


namespace Modules\Notification\Controllers;


use App\Controllers\BaseController;

use Modules\Notification\Models\NotificationModel;

use Modules\Notification\Models\UserNotificationModel;

use Modules\Notification\Models\NotificationScheduleModel;

use Modules\Trip\Models\TripModel;

use Modules\User\Models\UserDetailModel;

use Modules\Ticket\Models\TicketModel;

use App\Libraries\Rolepermission;

use Modules\Trip\Models\SubtripModel;

use App\Libraries\UserPushNotification;

use Modules\Passanger\Models\UserDeviceModel;



class Notification extends BaseController

{

    protected $Viewpath;

    protected $notificationModel;

    protected $userNotificationModel;

    protected $scheduleModel;

    protected $tripModel;

    protected $userDetailModel;

    protected $ticketModel;

    protected $db;

    protected $subtripModel;

    protected $userDeviceModel;



    public function __construct()

    {

        $this->Viewpath = "Modules\Notification\Views";

        $this->notificationModel = new NotificationModel();

        $this->userNotificationModel = new UserNotificationModel();

        $this->scheduleModel = new NotificationScheduleModel();

        $this->tripModel = new TripModel();

        $this->userDetailModel = new UserDetailModel();

        $this->ticketModel = new TicketModel();

        $this->db = \Config\Database::connect();

        $this->subtripModel = new SubtripModel();

        $this->userDeviceModel = new UserDeviceModel();

    }



    public function index()

    {

        $data['stats'] = $this->notificationModel->getStatistics();

        $data['module'] = "Notification Management";

        $data['title'] = "All Notifications";

        $data['pageheading'] = "Notification Management";



        $rolepermissionLibrary = new Rolepermission();

        $data['add_data'] = $rolepermissionLibrary->create("add_notification");

        $data['edit_data'] = $rolepermissionLibrary->edit("notification_list");

        $data['delete_data'] = $rolepermissionLibrary->delete("notification_list");



        echo view($this->Viewpath . '\notification/index', $data);

    }



    public function serverList()

    {

        $request = service('request');

        $draw   = $request->getPost('draw');

        $start  = (int) ($request->getPost('start') ?? 0);

        $length = (int) ($request->getPost('length') ?? 25);

        $searchValue = $request->getPost('search')['value'] ?? '';



        $statusFilter = strtolower(trim((string) ($request->getPost('status_filter') ?? 'all')));

        if (! in_array($statusFilter, ['all', 'sent', 'scheduled', 'cancelled', 'draft'], true)) {

            $statusFilter = 'all';

        }



        $scopeFilter = strtolower(trim((string) ($request->getPost('scope_filter') ?? 'admin')));

        if (! in_array($scopeFilter, ['admin', 'trip_reminders', 'all'], true)) {

            $scopeFilter = 'admin';

        }



        $columns = [

            0 => 'notifications.id',

            1 => 'notifications.subject',

            2 => 'notifications.target_group',

            3 => 'companies.name',

            4 => 'notifications.notification_date',

            5 => 'notifications.status',

            6 => 'notifications.notification_type',

            7 => null,

            8 => 'notifications.created_at',

            9 => null,

        ];



        $order = $request->getPost('order');

        $orderColumnIndex = ! empty($order) && isset($order[0]['column']) ? (int) $order[0]['column'] : 8;

        $orderDirection   = ! empty($order) && isset($order[0]['dir']) && strtolower($order[0]['dir']) === 'asc' ? 'asc' : 'desc';



        $countBuilder = $this->db->table('notifications');

        $countBuilder->select('notifications.id');

        NotificationModel::indexListSelect($countBuilder);

        NotificationModel::applyScopeFilter($countBuilder, $scopeFilter);

        $totalRecords = $countBuilder->countAllResults(false);



        $builder = $this->db->table('notifications');

        NotificationModel::indexListSelect($builder);

        NotificationModel::applyScopeFilter($builder, $scopeFilter);

        NotificationModel::applyStatusFilter($builder, $statusFilter);



        if ($searchValue !== '') {

            $builder->groupStart()

                ->like('notifications.subject', $searchValue)

                ->orLike('notifications.notification_type', $searchValue)

                ->orLike('notifications.target_group', $searchValue)

                ->orLike('notifications.status', $searchValue)

                ->orLike('companies.name', $searchValue)

                ->orLike('user_details.first_name', $searchValue)

                ->orLike('user_details.last_name', $searchValue)

                ->groupEnd();

        }



        $filteredCountBuilder = $this->db->table('notifications');

        NotificationModel::indexListSelect($filteredCountBuilder);

        NotificationModel::applyScopeFilter($filteredCountBuilder, $scopeFilter);

        NotificationModel::applyStatusFilter($filteredCountBuilder, $statusFilter);



        if ($searchValue !== '') {

            $filteredCountBuilder->groupStart()

                ->like('notifications.subject', $searchValue)

                ->orLike('notifications.notification_type', $searchValue)

                ->orLike('notifications.target_group', $searchValue)

                ->orLike('notifications.status', $searchValue)

                ->orLike('companies.name', $searchValue)

                ->orLike('user_details.first_name', $searchValue)

                ->orLike('user_details.last_name', $searchValue)

                ->groupEnd();

        }



        $totalRecordwithFilter = $filteredCountBuilder->countAllResults(false);



        if (isset($columns[$orderColumnIndex]) && $columns[$orderColumnIndex] !== null) {

            $builder->orderBy($columns[$orderColumnIndex], $orderDirection);

        } else {

            $builder->orderBy('notifications.created_at', 'desc');

        }



        if ($length > 0) {

            $builder->limit($length, $start);

        }



        $records = $builder->get()->getResult();



        $statusClass = [

            'draft'     => 'bg-secondary',

            'scheduled' => 'bg-warning',

            'sent'      => 'bg-success',

            'cancelled' => 'bg-danger',

        ];



        $data = [];

        $i = $start + 1;



        foreach ($records as $row) {

            $subjectHtml = '<strong>' . esc($row->subject ?? '') . '</strong>';

            if (! empty($row->is_push_notification)) {

                $subjectHtml .= ' <span class="badge bg-info ms-1">Push</span>';

            }



            if (($row->target_group ?? '') === 'all_users') {

                $targetBadge = '<span class="badge bg-primary">All Users</span>';

            } elseif (($row->target_group ?? '') === 'specific_trip') {

                $targetBadge = '<span class="badge bg-secondary">Specific Trip</span>';

            } elseif ((int) ($row->created_by ?? 0) === 0) {

                $targetBadge = '<span class="badge bg-light text-dark">Trip Reminder</span>';

            } else {

                $targetBadge = '<span class="badge bg-secondary">-</span>';

            }



            $status = (string) ($row->status ?? '');

            $statusHtml = '<span class="badge ' . ($statusClass[$status] ?? 'bg-secondary') . '">' . esc(ucfirst($status)) . '</span>';



            $actionHtml = '<div class="btn-group" role="group">';

            $actionHtml .= '<a href="' . base_url(route_to('show-notification', $row->id)) . '" class="btn btn-sm btn-info" title="View Details"><i class="fas fa-eye"></i></a>';



            if (in_array($status, ['draft', 'scheduled'], true)) {

                $actionHtml .= ' <button type="button" class="btn btn-sm btn-danger" onclick="cancelNotification(' . (int) $row->id . ')" title="Cancel"><i class="fas fa-times"></i></button>';

            }



            $actionHtml .= '</div>';



            $data[] = [

                'index'             => $i++,

                'subject'           => $subjectHtml,

                'target_group'      => $targetBadge,

                'trip_name'         => esc($row->trip_name ?: '-'),

                'notification_date' => esc(date('Y-m-d H:i', strtotime((string) $row->notification_date))),

                'status'            => $statusHtml,

                'notification_type' => esc($row->notification_type ?: '-'),

                'created_by_name'   => esc(trim($row->created_by_name ?? '') ?: '-'),

                'created_at'        => esc(date('Y-m-d H:i', strtotime((string) $row->created_at))),

                'action'            => $actionHtml,

            ];

        }



        return $this->response->setJSON([

            'draw'            => (int) $draw,

            'recordsTotal'    => $totalRecords,

            'recordsFiltered' => $totalRecordwithFilter,

            'data'            => $data,

        ]);

    }



    public function new()

    {

        // $data['trips'] = $this->tripModel->select('trips.id, trips.startdate as departure_date, schedules.start_time as departure_time, companies.name as trip_name, trips.status')

        //     ->join('schedules', 'schedules.id = trips.schedule_id', 'left')

        //     ->join('companies', 'companies.id = trips.company_id', 'left')

        //     ->where('trips.status', 'active')

        //     ->where('trips.startdate >=', date('Y-m-d'))

        //     ->orderBy('trips.startdate', 'ASC')

        //     ->findAll();

        $data['trips'] = $this->subtripModel->getTripsByCompany("all");

        $data['pageheading'] = "Create New Notification";

        $data['module'] = "Notification Management";

        $data['title'] = "Create Notification";



        echo view($this->Viewpath . '\notification/new', $data);

    }



    public function create()

    {

        $userID = $this->session->get('user_id');



        $data = [

            "subject" => $this->request->getVar('subject'),

            "message" => $this->request->getVar('message'),

            "notification_type" => 'manual',

            "target_group" => $this->request->getVar('target_group'),

            "trip_id" => $this->request->getVar('trip_id') ?: null,
            
            "journey_date" => $this->request->getVar('journey_date') ?: null,


            "notification_date" => $this->request->getVar('notification_date') ?? date('Y-m-d H:i:s'),

            "repeat_option" => $this->request->getVar('repeat_option') ?: 'none',

            "status" => $this->request->getVar('send_immediately') ? 'scheduled' : 'scheduled',

            "is_push_notification" => $this->request->getVar('is_push_notification') ? 1 : 0,

            "created_by" => $userID,

        ];

        if ($notificationId = $this->notificationModel->insert($data)) {

            if ($this->request->getVar('send_immediately')) {
                if (! $this->sendNotificationNow($notificationId)) {
                    return redirect()->route('index-notification')->with(
                        'fail',
                        'Notification was saved but could not be sent (no eligible recipients or send failed).'
                    );
                }
            } else {

                // Schedule notification

                if ($data['repeat_option'] !== 'none') {

                    $nextRunDate = $this->scheduleModel->calculateNextRunDate($data['repeat_option'], $data['notification_date']);

                    if ($nextRunDate) {

                        $this->scheduleModel->insert([

                            'notification_id' => $notificationId,

                            'next_run_date' => $nextRunDate,

                            'is_active' => 1

                        ]);

                    }

                }

            }



            return redirect()->route('index-notification')->with("success", "Notification created successfully");

        }else{
            return redirect()->back()->withInput()->with('fail', $this->validation->listErrors());    
        }

        return redirect()->back()->withInput()->with('fail', $this->validation->listErrors());

    }



    public function show($id)

    {

        $data['notification'] = $this->notificationModel->select('notifications.*, CONCAT(user_details.first_name, " ", user_details.last_name) as created_by_name, companies.name as trip_name')

            ->join('users', 'users.id = notifications.created_by', 'left')

            ->join('user_details', 'user_details.user_id = users.id', 'left')

            ->join('trips', 'trips.id = notifications.trip_id', 'left')

            ->join('companies', 'companies.id = trips.company_id', 'left')

            ->find($id);



        if (!$data['notification']) {

            return redirect()->route('index-notification')->with('fail', 'Notification not found');

        }



        $data['delivery_stats'] = $this->userNotificationModel->getDeliveryStats($id);



        $data['module'] = "Notification Management";

        $data['title'] = "Notification Details";

        $data['pageheading'] = "Notification Details";



        echo view($this->Viewpath . '\notification/show', $data);

    }



    public function edit($id)

    {

        $data['notification'] = $this->notificationModel->find($id);

        if (!$data['notification'] || in_array($data['notification']['status'], ['sent', 'cancelled'])) {

            return redirect()->route('index-notification')->with('fail', 'Notification cannot be edited');

        }



        $data['trips'] = $this->tripModel->select('trips.id, trips.startdate as departure_date, schedules.start_time as departure_time, companies.name as trip_name, trips.status')

            ->join('schedules', 'schedules.id = trips.schedule_id', 'left')

            ->join('companies', 'companies.id = trips.company_id', 'left')

            ->where('trips.status', 'active')

            ->where('trips.startdate >=', egypt_today())

            ->orderBy('trips.startdate', 'ASC')

            ->findAll();



        $data['module'] = "Notification Management";

        $data['pageheading'] = "Edit Notification";



        echo view($this->Viewpath . '\notification/edit', $data);

    }



    public function update($id)

    {

        $notification = $this->notificationModel->find($id);

        
        if (!$notification || in_array($notification['status'], ['sent', 'cancelled'])) {

            return redirect()->route('index-notification')->with('fail', 'Notification cannot be updated');

        }



        $data = [

            "id" => $id,

            "subject" => $this->request->getVar('subject'),

            "message" => $this->request->getVar('message'),

            "target_group" => $this->request->getVar('target_group'),

            "trip_id" => $this->request->getVar('trip_id') ?: null,

            "notification_date" => $this->request->getVar('notification_date'),

            "repeat_option" => $this->request->getVar('repeat_option') ?: 'none',

            "is_push_notification" => $this->request->getVar('is_push_notification') ? 1 : 0,

        ];



        // if ($this->validation->run($data, 'notification')) {

            $this->notificationModel->save($data);

            return redirect()->route('index-notification')->with("success", "Notification updated successfully");

        // }



        // return redirect()->back()->withInput()->with('fail', $this->validation->listErrors());

    }



    public function delete($id)

    {

        $notification = $this->notificationModel->find($id);

        

        if ($notification && ($notification['status'] ?? '') !== 'sent') {

            $this->notificationModel->delete($id);

            return redirect()->route('index-notification')->with("success", "Notification deleted successfully");

        }



        return redirect()->route('index-notification')->with("fail", "Cannot delete sent notification");

    }



    public function cancel($id)

    {

        $notification = $this->notificationModel->find($id);

        

        if ($notification && in_array($notification['status'], ['scheduled', 'draft'])) {

            $this->notificationModel->update($id, ['status' => 'cancelled']);

            

            // Deactivate schedule if exists

            $schedule = $this->scheduleModel->where('notification_id', $id)->first();

            if ($schedule) {

                $this->scheduleModel->deactivate($schedule->id);

            }

            

            return redirect()->route('index-notification')->with("success", "Notification cancelled successfully");

        }



        return redirect()->route('index-notification')->with("fail", "Cannot cancel this notification");

    }



    public function sendNow($id)

    {

        $notification = $this->notificationModel->find($id);

        

        if ($notification && in_array($notification['status'], ['scheduled', 'draft'])) {

            if ($this->sendNotificationNow($id)) {
                return redirect()->route('index-notification')->with('success', 'Notification sent successfully');
            }

            return redirect()->route('index-notification')->with(
                'fail',
                'Could not send notification (no eligible recipients or send failed).'
            );

        }



        return redirect()->route('index-notification')->with("fail", "Cannot send this notification");

    }



    public function scheduled()

    {

        $data['notifications'] = $this->notificationModel->getByStatus('scheduled');

        $data['module'] = "Notification Management";

        $data['title'] = "Scheduled Notifications";

        $data['pageheading'] = "Scheduled Notifications";



        echo view($this->Viewpath . '\notification/scheduled', $data);

    }



    public function sent()

    {

        $data['notifications'] = $this->notificationModel->getByStatus('sent');

        $data['module'] = "Notification Management";

        $data['title'] = "Sent Notifications";

        $data['pageheading'] = "Sent Notifications";



        echo view($this->Viewpath . '\notification/sent', $data);

    }



    public function cancelled()

    {

        $data['notifications'] = $this->notificationModel->getByStatus('cancelled');

        $data['module'] = "Notification Management";

        $data['title'] = "Cancelled Notifications";

        $data['pageheading'] = "Cancelled Notifications";



        echo view($this->Viewpath . '\notification/cancelled', $data);

    }



    public function getTripPassengers($tripId)

    {

        $passengers = $this->ticketModel->select('tickets.*, user_details.first_name, user_details.last_name')

            ->join('user_details', 'user_details.user_id = tickets.passanger_id', 'left')

            ->where('tickets.trip_id', $tripId)

            ->where('tickets.cancel_status', 0)

            ->where('tickets.payment_status', 'paid')

            ->findAll();



        return $this->response->setJSON(['passengers' => $passengers]);

    }



    /**

     * Send notification immediately

     */

    private function sendNotificationNow($notificationId)

    {

        $notification = $this->notificationModel->find($notificationId);

        if (!$notification) {

            return false;

        }

        // Get target users

        $userIds = [];

        if ($notification['target_group'] === 'all_users') {

            // Match SendScheduledNotifications: users with at least one active device token

            $devices = $this->userDeviceModel->select('user_id')->where('status', 1)->findAll();

            foreach ($devices as $device) {

                $userIds[] = (int) $device->user_id;

            }

        } elseif ($notification['target_group'] === 'specific_trip' && $notification['trip_id']) {

            // Get distinct passenger app users for this trip (paid, not cancelled)

            $passengers = $this->ticketModel->select('passanger_id')

                ->where('trip_id', $notification['trip_id'])

                ->where('cancel_status', 0)

                ->where('payment_status', 'paid')

                ->where('passanger_id >', 0)

                ->groupBy('passanger_id')

                ->findAll();

            

            foreach ($passengers as $passenger) {

                $userIds[] = (int) $passenger->passanger_id;

            }

        }



        $userIds = array_values(array_unique(array_filter($userIds)));

        if ($userIds === []) {

            return false;

        }

        try {

            $this->userNotificationModel->sendToUsers($notificationId, $userIds);

            if (! empty($notification['is_push_notification'])) {

                try {

                    $push = new UserPushNotification();

                    $title = (string) ($notification['subject'] ?? '');

                    $body  = (string) ($notification['message'] ?? '');

                    foreach ($userIds as $uid) {

                        $push->sendToUser((int) $uid, $title, $body);

                    }

                } catch (\Throwable $e) {

                    log_message('error', 'sendNotificationNow push phase failed: ' . $e->getMessage());

                }

            }

            $this->notificationModel->update($notificationId, ['status' => 'sent']);

            return true;

        } catch (\Throwable $e) {

            log_message('error', 'sendNotificationNow failed: ' . $e->getMessage());

            return false;

        }

    }

}

