<?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['notifications'] = $this->notificationModel->getIndexList(500);

        $data['list_capped'] = $data['stats']['total'] > count($data['notifications']);



        $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 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;

        }

    }

}

