<?php



namespace Modules\Ticket\Controllers;



use App\Controllers\BaseController;

use CodeIgniter\API\ResponseTrait;

use Modules\Employee\Models\EmployeeModel;

use Modules\Fleet\Models\FleetModel;

use Modules\Fleet\Models\VehicleModel;

use Modules\Location\Models\LocationModel;

use Modules\Location\Models\StandModel;

use Modules\Paymethod\Models\PaymethodModel;

use Modules\Schedule\Models\ScheduleModel;

use Modules\Tax\Models\TaxModel;

use Modules\Ticket\Models\JourneylistModel;

use Modules\Ticket\Models\PartialpaidModel;

use Modules\Ticket\Models\TicketModel;

use Modules\Ticket\Models\PretripModel;

use Modules\Ticket\Models\MaxtimeModel;

use Modules\Trip\Models\FacilityModel;

use Modules\Trip\Models\PickdropModel;

use Modules\Trip\Models\StuffassignModel;

use Modules\Trip\Models\SubtripModel;

use Modules\Trip\Models\TripModel;

use Modules\User\Models\UserDetailModel;

use Modules\User\Models\UserModel;

use Modules\Role\Models\RoleModel;

use Modules\Agent\Models\AgentModel;

use Modules\Agent\Models\Agentcommission;

use Modules\Website\Models\WebsettingModel;

use Modules\Coupon\Models\CoupondiscountModel;

use Modules\Coupon\Models\CouponModel;

use Modules\Trip\Models\RoundtripdiscoundModel;

use Modules\Company\Models\CompanyModel;

use Modules\Ticket\Models\TemporaryBook;


use Modules\HoldSeat\Models\HoldSeatModel;

use Modules\Account\Models\PayagentModel;

use Modules\Ticket\Models\TemporaryBook as TemporaryBookModel;

use Modules\Notification\Models\NotificationModel;
use Modules\Notification\Models\UserNotificationModel;





use App\Libraries\Rolepermission;
use App\Libraries\BookingInventorySupport;
use App\Libraries\TemporaryBookHoldService;

use App\Libraries\Ticketmail;

use CodeIgniter\Database\RawSql;

use Exception;



class Ticket extends BaseController

{

    use ResponseTrait;



    protected $Viewpath;

    protected $ticketModel;

    protected $pretripModel;

    protected $tripModel;

    protected $subtripModel;

    protected $stuffassignModel;

    protected $locationModel;

    protected $employeeModel;

    protected $fleetTypeModel;

    protected $scheduleeModel;

    protected $vehicleModel;

    protected $standModel;

    protected $picdropModel;

    protected $facilitypModel;

    protected $taxModel;

    protected $db;

    protected $paymethodModel;

    protected $userModel;

    protected $userDetailModel;

    protected $journeylistModel;

    protected $partialpaidModel;

    protected $maxtimeModel;

    protected $roleModel;

    protected $agentModel;

    protected $agentCommissionModel;



    protected $websettingModel;

    protected $couponModel;

    protected $coupondiscountModel;



    protected $roundtripdiscoundModel;

    protected $CompanyModel;



    protected $TemporaryBook;

    protected $holdSeatModel;

    protected $agentPayment;

    protected $temporaryBookModel;
    
    protected $notificationModel;



    public function __construct()

    {



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

        $this->ticketModel = new TicketModel();

        $this->pretripModel = new PretripModel();

        $this->tripModel = new TripModel();

        $this->subtripModel = new SubtripModel();

        $this->stuffassignModel = new StuffassignModel();

        $this->locationModel = new LocationModel();

        $this->employeeModel = new EmployeeModel();

        $this->fleetTypeModel = new FleetModel();

        $this->vehicleModel = new VehicleModel();

        $this->scheduleeModel = new ScheduleModel();

        $this->standModel = new StandModel();

        $this->picdropModel = new PickdropModel();

        $this->facilitypModel = new FacilityModel();

        $this->taxModel = new TaxModel();

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

        $this->paymethodModel = new PaymethodModel();



        $this->userModel = new UserModel();

        $this->userDetailModel = new UserDetailModel();



        $this->journeylistModel = new JourneylistModel();

        $this->partialpaidModel = new PartialpaidModel();



        $this->maxtimeModel = new MaxtimeModel();

        $this->roleModel = new RoleModel();



        $this->agentModel = new AgentModel();

        $this->agentCommissionModel = new Agentcommission();



        $this->websettingModel = new WebsettingModel();



        $this->coupondiscountModel = new CoupondiscountModel();

        $this->couponModel = new CouponModel();



        $this->roundtripdiscoundModel = new RoundtripdiscoundModel();

        $this->CompanyModel = new CompanyModel();

        $this->TemporaryBook = new TemporaryBook();

        $this->holdSeatModel = new HoldSeatModel();

        $this->agentPayment = new PayagentModel();

        $this->temporaryBookModel = new TemporaryBookModel();
        
        $this->notificationModel = new NotificationModel();

        $this->userNotificationModel = new UserNotificationModel();

    }



    function new()

    {



        $this->session->remove('pick_location_id');

        $this->session->remove('drop_location_id');

        $this->session->remove('filterjourneydate');

        $this->session->remove('filterreturndate');

        $this->session->remove('fleet_id');



        $this->session->remove('subtripId');

        $this->session->remove('seatnumbers');

        $this->session->remove('totalseat');

        $this->session->remove('journeydate');

        $this->session->remove('aseat');

        $this->session->remove('spseat');

        $this->session->remove('vpseat');

        $this->session->remove('cseat');

        $this->session->remove('totalprice');

        $this->session->remove('tax');

        $this->session->remove('grandtotal');

        $this->session->remove('pickstand');

        $this->session->remove('dropstand');

        $this->session->remove('isrountrip');

        $this->session->remove('discountPercent');

        $this->session->remove('roundtrip_discount');



        $data['pick_location_id'] = null;

        $data['drop_location_id'] = null;

        $data['filterjourneydate'] = null;

        $data['filterreturndate'] = null;

        $data['fleet_id'] = null;



        $data['filterpath'] = $this->Viewpath;

        $data['location'] = $this->locationModel->findAll();

        $data['fleet_type'] = $this->fleetTypeModel->findAll();



        $data['module'] =    lang("Localize.ticket_booking");

        $data['title']  =    lang("Localize.book_ticket");



        $heading = lang("Localize.search") . ' ' . lang("Localize.ticket");

        $data['pageheading'] = $heading;



        $data['company_id'] = 0;

        $data['companies'] = $this->CompanyModel->findAll();



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

    }



    public function findtrip()

    {

        $t = $this->request->getVar();

        $websetting = $this->websettingModel->first();



        // Get request vars

        $pick_location_id  = $this->request->getVar('pick_location_id') ?: session('pick_location_id');

        $drop_location_id  = $this->request->getVar('drop_location_id') ?: session('drop_location_id');

        $filterjourneydate = $this->request->getVar('filterjourneydate') ?: session('filterjourneydate');

        $filterreturndate  = $this->request->getVar('filterreturndate') ?: session('filterreturndate');

        $fleet_id          = $this->request->getVar('fleet_id') ?: session('fleet_id');

        

        $company_id = session()->get('company_id') ?? 0;

        if(($this->request->getVar('company_id') || $this->request->getVar('company_id') == 0) && session()->get('role_id') == "1"){

            $company_id = $this->request->getVar('company_id') ?? 0;

        } else {

            if(session('search_company_id')){

                $company_id = session('search_company_id');

            }

        }

        // 

        $journeyDate = date('Y-m-d', strtotime($filterjourneydate));

        $journeyDayOfWeek = date('N', strtotime($filterjourneydate));



        $this->session->remove('pick_location_id');

        $this->session->remove('drop_location_id');

        $this->session->remove('filterjourneydate');

        $this->session->remove('filterreturndate');

        $this->session->remove('fleet_id');



        $this->session->remove('subtripId');

        $this->session->remove('seatnumbers');

        $this->session->remove('totalseat');

        $this->session->remove('journeydate');

        $this->session->remove('aseat');

        $this->session->remove('spseat');

        $this->session->remove('vpseat');

        $this->session->remove('cseat');

        $this->session->remove('totalprice');

        $this->session->remove('tax');

        $this->session->remove('grandtotal');

        $this->session->remove('pickstand');

        $this->session->remove('dropstand');

        $this->session->remove('isrountrip');

        $this->session->remove('discountPercent');

        $this->session->remove('roundtrip_discount');

        $this->session->remove('search_company_id');



        $tripData['pick_location_id'] =  $pick_location_id;

        $tripData['drop_location_id'] = $drop_location_id;

        $tripData['filterjourneydate'] =  $filterjourneydate;

        $tripData['filterreturndate'] = $filterreturndate;

        $tripData['fleet_id'] = $fleet_id;

        $tripData['search_company_id'] = $company_id;



        $this->session->set($tripData);



        $monthcomparedate =  date('Y-m-d', strtotime('+1 month'));



        // if ($filterjourneydate > $monthcomparedate) {

        //     return redirect()->route('new-ticket')->with("fail", "No advance booking for this day");

        // }



        $data = array('trips' => [], 'in_holiday' => [], 'to_open' => [], 'inactive' => [], 'you_may_like' => []);

        $data['pick_location_id'] = $pick_location_id;

        $data['drop_location_id'] = $drop_location_id;

        $data['filterjourneydate'] = $filterjourneydate;

        $data['filterreturndate'] = $filterreturndate;

        $data['fleet_id'] = $fleet_id;

        $data['company_id'] = $company_id;



        $data['filterpath'] = $this->Viewpath;

        // $data['location'] = $this->locationModel->findAll();
        
        // $data['location'] = $this->locationModel->orderBy('name', 'DESC')->findAll();
        
        $data['location'] = $this->locationModel
    ->orderBy("(name REGEXP '^[ء-ي]')", "DESC", false)
    ->orderBy("name COLLATE utf8mb4_unicode_520_ci", "ASC", false)
    ->findAll();



        $data['fleet_type'] = $this->fleetTypeModel->findAll();

        $data['companies'] = $this->CompanyModel->findAll();



        if (strpos($company_id, ',')) { 

            $company_ids = explode(',', $company_id);

        } else {

            $company_ids = [$company_id];

        }



        $allSubTrips = $this->getAllTrip($pick_location_id, $drop_location_id, $fleet_id, $company_ids);



        foreach ($allSubTrips as $subTrip) {

            if ($subTrip->status == 0) {

                // subtrip is inactive

                $data['inactive'][] = $subTrip;

                continue;

            }



            if (strtotime($journeyDate) < strtotime($subTrip->startdate)) {

                // subtrip yet not begin

                $data['to_open'][] = $subTrip;

                continue;

            }

            // if ($journeyDate ==  $subTrip->offdates) {

            $cleanedoffdates = preg_replace('/\s+/', '', $subTrip->offdates);

            if (in_array($journeyDate,explode(",", $cleanedoffdates))) {

                // subtrip is off today

                $data['in_holiday'][] = $subTrip;

                continue;

            }



            if ($this->isDateInRange($journeyDate, $subTrip->startdateinrange, $subTrip->enddateinrange)) {

                // subtrip is not in range

                $data['in_holiday'][] = $subTrip;

                continue;

            }



            $offdateranges = json_decode($subTrip->offdateranges, true);

            $isInAnyRange = false;

            if (is_array($offdateranges) && !empty($offdateranges)) {

                foreach ($offdateranges as $range) {

                    $start = $range['start'] ?? null;

                    $end = $range['end'] ?? null;



                    if ($start && $end && $this->isDateInRange($journeyDate, $start, $end)) {

                        $isInAnyRange = true;

                        break;

                    }

                }

            }



            if ($isInAnyRange) {

                $data['in_holiday'][] = $subTrip;

                continue;

            }





            if (!$this->isDateInRange($journeyDate, $subTrip->repetedstartdate, $subTrip->repetedenddate)) {

                if($journeyDate != date('Y-m-d',strtotime($subTrip->startdate))){

                    //start date and not between start and edn date

                    $data['in_holiday'][] = $subTrip;

                    continue;    

                }

                

            }



            $today = new \DateTime(date('Y-m-d'));



            $journeyDateObj = new \DateTime(date('Y-m-d', strtotime($journeyDate)));

            $interval = $today->diff($journeyDateObj);

            $bookingToday = new \DateTime(date('Y-m-d'));
            $bookingWindowInterval = $bookingToday->diff($journeyDateObj);

            if ($subTrip->maxdayforbooking > 0 && ($subTrip->maxdayforbooking < $bookingWindowInterval->days)) {

                //not allowed to book tickets

                $data['in_holiday'][] = $subTrip;

                continue;

            }



            if ($this->isDateInRange($journeyDate, $subTrip->repetedstartdate, $subTrip->repetedenddate)) {

                if($journeyDate != date('Y-m-d',strtotime($subTrip->startdate))){

                    if($subTrip->repeted_after > 0 && $interval->days > 0){

                        if($interval->days%$subTrip->repeted_after > 0){

                            //start date and not between start and edn date

                            $data['in_holiday'][] = $subTrip;

                            continue;

                        }

                    }

                    

                }

                

            }



            if (@in_array($journeyDayOfWeek, explode(',', $subTrip->weekend))) {

                // subtrip is on holiday

                $data['in_holiday'][] = $subTrip;

                continue;

            }



            if (($subTrip->pick_location_id != $pick_location_id) || ($subTrip->drop_location_id != $drop_location_id)) {

                // subtrip is related to selected locations

                $data['you_may_like'][] = $subTrip;

                continue;

            }





            $subtripInfo = $this->subtripModel->find($subTrip->id);

            $this->ticketModel

            ->where('journeydata', $filterjourneydate)

            ->where('cancel_status', 0)

            ->where('refund', 0);



            if ($subtripInfo->type == 'subtrip') {

                $mainTripId = $subtripInfo->trip_id;

                $subtripStoppagePointsArr = array_filter(explode(',', $subtripInfo->stoppage));

                $mainTripMainSubtripId = $this->subtripModel->where('trip_id', $mainTripId)->where('type', 'main')->first();



                $subtripStopage = $this->subtripModel->where('trip_id', $mainTripId)->where('pick_location_id', $subtripInfo->pick_location_id)->where('drop_location_id', $subtripInfo->drop_location_id)->first();

                $results = $this->getDynamicPickupDropCombinations($subtripInfo->pick_location_id, $subtripInfo->drop_location_id, $subtripStopage->stoppage, $filterjourneydate, $mainTripId);

                $bookseat = array_column($results, 'seatnumber');



            } else {

                $this->ticketModel->where('tickets.trip_id', $subtripInfo->trip_id);

                $bookseat = array_column($this->ticketModel->findAll(), 'seatnumber');

            }

            $separatedSeats = [];

            foreach ($bookseat as $seats) {

                // Use explode to separate the comma-separated seat numbers

                $separatedSeats = array_merge($separatedSeats, explode(',', $seats));

            }

            $subTrip->bookseatCount = is_array($separatedSeats)?count($separatedSeats):0;

            $pickdrop = $this->picdropModel->select('pickdrops.id as pickdropid,pickdrops.*,stands.*, stands.name as stand_name')

                ->join('stands', 'stands.id = pickdrops.stand_id')

                ->where('trip_id', $subtripInfo->id)
                
                ->orderBy('pickdrops.id','ASC')

                ->findAll();

            if(empty($pickdrop)){

                $pickdrop = $this->picdropModel->select('pickdrops.id as pickdropid,pickdrops.*,stands.*, stands.name as stand_name')

                    ->join('stands', 'stands.id = pickdrops.stand_id')

                    ->where('trip_id', $subtripInfo->trip_id)
                    
                    ->orderBy('pickdrops.id','ASC')

                    ->findAll();

            }

            // print_r($pickdrop);

            $pickup_time = null;

            $drop_time = null;



            // foreach ($pickdrop as $item) {

            //     if ($item->type == 1) {

            //         $pickup_time = $item->time;

            //     } elseif ($item->type == 0) {

            //         $drop_time = $item->time;

            //     }

            // }

            $pickup_time = null;

            $drop_time = null;



            foreach ($pickdrop as $item) {

                if ($item->type == 1) {

                    // Smallest pickup time

                    // if (is_null($pickup_time) || strtotime($item->time) < strtotime($pickup_time)) {
                    if (is_null($pickup_time)) {

                        $pickup_time = $item->time;

                    }

                } elseif ($item->type == 0) {

                    // Largest drop time

                    // if (is_null($drop_time) || strtotime($item->time) > strtotime($drop_time)) {
                    if (is_null($drop_time)) {

                        $drop_time = $item->time;

                    }

                }

            }





            $subTrip->pickup_time = $pickup_time;

            $subTrip->drop_time = $drop_time;

            // Agents/backend users: hide trip 1 hour after departure. Super admin + company admin may still book.
            if (! \App\Libraries\BookingInventorySupport::canBookBackdatedTrips() && ! empty($pickup_time)) {
                $egyptCurrentTime = get_egypt_time();
                
                $departureDateTimeStr = $filterjourneydate . ' ' . $pickup_time;
                try {
                    $departureDateTime = new \DateTime($departureDateTimeStr, new \DateTimeZone("Africa/Cairo"));
                    
                    // The trip is available until exactly 1 hour after the departure time
                    $oneHourAfterDeparture = (clone $departureDateTime)->modify('+1 hour');
                    
                    if ($egyptCurrentTime >= $oneHourAfterDeparture) {
                        continue; // Hide the trip
                    }
                } catch (\Exception $e) {
                    // Ignore parsing errors
                }
            }

            $data['trips'][] = $subTrip;

            // print_r($data);

            // exit;

        }



        $data['taxtype'] = $websetting->tax_type;

        $data['module'] = lang("Localize.ticket_booking");

        $data['title'] = lang("Localize.book_ticket");

        $data['pageheading'] = lang("Localize.book") . ' ' . lang("Localize.ticket");

        $data['triptype'] = lang("Localize.single") . ' ' . lang("Localize.trip");

        //echo "<pre>";print_r($data);exit;

        return view($this->Viewpath . '\ticket\index', $data);

    }



    public function getAllTrip($pickLocationId, $dropLocationId, $fleetId = null, $company_id)

    {

        // bind search query

        $this->subtripModel

            ->select('trips.id as tripid, trips.*, fleets.*, schedules.*, vehicles.*, subtrips.id as subtripId, subtrips.*,companies.name as company, trip_bus_types.name AS trip_bus_type, trip_category.name AS trip_category_name')



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

            ->join('fleets', 'fleets.id = trips.fleet_id')

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

            ->join('vehicles', 'vehicles.id = trips.vehicle_id',"left")

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

            ->join('trip_bus_types', 'trip_bus_types.id = trips.trip_bus_type_id',"left")

            ->join('trip_category', 'trip_category.id = trips.trip_category_id',"left")



            ->groupStart()

                ->groupStart()

                    ->where('subtrips.pick_location_id', $pickLocationId)

                    ->where('subtrips.drop_location_id', $dropLocationId)

                ->groupEnd()



                ->orGroupStart()

                    ->whereIn('subtrips.trip_id', function ($subQuery) use ($pickLocationId, $dropLocationId) {

                        $subQuery

                            ->select('sm.trip_id')

                            ->from('subtrips sm')

                            ->where('sm.pick_location_id', $pickLocationId)

                            ->where('sm.drop_location_id', $dropLocationId)

                            ->where('sm.type', 'subtrip');

                    })

                    ->where('subtrips.type', 'main')

                ->groupEnd()

            ->groupEnd()

            ->where('subtrips.status', 1)

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

            ->where('companies.status', 1);



            if(is_array($company_id) && session()->get('role_id') != "1"){

                $this->subtripModel->whereIn('trips.company_id', $company_id);

            } else {

                $nonEmptyCompanyId = array_filter($company_id);

                if(!empty($nonEmptyCompanyId)){

                    $this->subtripModel->whereIn('trips.company_id', $company_id);

                }

                

            }



            $this->subtripModel->orderBy('subtrips.id', 'DESC');



        $fleetId && $this->subtripModel->where('trips.fleet_id', $fleetId);

        // $query = $this->subtripModel->builder()->getCompiledSelect();dd($query);

        return $this->subtripModel->findAll();

    }



    public function getSingleTrip($subTripId, $journeydate)

    {

        $maxtime = $this->maxtimeModel->first();

        $maxtime =  60 * (int)$maxtime->maxtime;

        $subtripInfo = $this->subtripModel->find($subTripId);



        // Release non paid expired seats

        $getData = $this->ticketModel

            ->where('trip_id', $subtripInfo->trip_id)

            ->where('journeydata', $journeydate)

            ->where('payment_status', "unpaid")

            ->where('cancel_status', 0)

            ->where('refund', 0)

            ->findAll();



        foreach ($getData as $key => $delvalue) {

            $cratetime = strtotime($delvalue->created_at);

            $timenow = strtotime("now");



            if (($timenow - $cratetime) > $maxtime) {

                $this->ticketModel->where('id', $delvalue->id)->set(['cancel_status' => 1])->update();

                $bookingId = $this->ticketModel->find($delvalue->id);

                $this->journeylistModel->where('booking_id', $bookingId->booking_id)->delete();

            }

        }



        // Build total booked seats

        $this->ticketModel

            ->where('journeydata', $journeydate)

            ->where('cancel_status', 0)

            ->where('refund', 0);



        if ($subtripInfo->type == 'subtrip') {

            $mainTripId = $subtripInfo->trip_id;

            $subtripStoppagePointsArr = array_filter(explode(',', $subtripInfo->stoppage));

            $mainTripMainSubtripId = $this->subtripModel->where('trip_id', $mainTripId)->where('type', 'main')->first();

            $subtripStopage = $this->subtripModel->where('trip_id', $mainTripId)->where('pick_location_id', $subtripInfo->pick_location_id)->where('drop_location_id', $subtripInfo->drop_location_id)->first();

            

            $results = $this->getDynamicPickupDropCombinations($subtripInfo->pick_location_id, $subtripInfo->drop_location_id, $subtripStopage->stoppage, $journeydate, $mainTripId);

            

            $bookseat = array_column($results, 'seatnumber');

            $holdseat =[];

            $blockseat =[];



            // $builder = $this->TemporaryBook->builder();

            // $builder->where('subtrip_id', $subtripInfo->id)

            //         ->where('journey_date', $journeydate)

            //         ->where('expires_at >', date('Y-m-d H:i:s'));

            // $query = $builder->get();

            // $TempBookedSeat = $query->getResultArray();

            

            $TempBookedSeat = $this->getDynamicPickupDropCombinationsTemp($subtripInfo->pick_location_id, $subtripInfo->drop_location_id, $subtripStopage->stoppage, $journeydate, $subtripInfo->id);

            $currentTime = date("Y-m-d H:i:s");

            $egyptNow = new \DateTime("now", new \DateTimeZone("Africa/Cairo"));
            $egyptNow->modify('+1 hour');
            $currentTime = $egyptNow->format("Y-m-d H:i:s");



            $builder = $this->holdSeatModel->builder();

            $builder

            // ->where('subtrip_id', $subtripInfo->id)

                    ->where("FIND_IN_SET('{$subtripInfo->id}', subtrip_id)", null, false)

                    ->where('status', 1)

                    ->where("'$journeydate' BETWEEN journeydata AND journeydataend", null, false)

                    ->where("'$currentTime' BETWEEN startdate AND enddate", null, false);

            $query = $builder->get();

            $holdSeat = $query->getResultArray();

            // if($subtripInfo->id == 339){

            //     print_r($holdSeat);

            //     exit;

            // }



            if(!empty($TempBookedSeat)){

                foreach($TempBookedSeat as $TempBookedSeat){

                    $holdseat[] = $TempBookedSeat['seat_names'];

                }

                

            }

            if(!empty($holdSeat)){

                foreach ($holdSeat as $seatRow) {

                    $seats = explode(',', $seatRow['seat_number']); // split by comma

                    foreach ($seats as $seat) {

                        $blockseat[] = trim($seat); // trim to clean whitespace

                    }

                }

                

            }



        } else {

            $currentTime = date("Y-m-d H:i:s");

            $egyptNow = new \DateTime("now", new \DateTimeZone("Africa/Cairo"));
            $egyptNow->modify('+1 hour');
            $currentTime = $egyptNow->format("Y-m-d H:i:s");

            if($subtripInfo->trip_id == 71){
                // dd($currentTime);
            }

            $holdseat =[];

            $blockseat = [];

            $builder = $this->holdSeatModel->builder();

            $builder

            ->where('trip_id', $subtripInfo->trip_id)

                    ->where("FIND_IN_SET('{$subtripInfo->id}', subtrip_id)", null, false)

                    ->where("'$journeydate' BETWEEN journeydata AND journeydataend", null, false)

                    ->where('status', 1)

                    ->where("'$currentTime' BETWEEN startdate AND enddate", null, false);

                    // ->where("DATE('$journeydate') BETWEEN DATE(startdate) AND DATE(enddate)", null, false);





            $query = $builder->get();

            $holdSeat = $query->getResultArray();



            // if($subtripInfo->id == 339){

                // print_r($holdSeat);

                // exit;

                foreach ($holdSeat as $key => $row) {

                    // if current time NOT between start and end, remove it

                    if ($currentTime < $row['startdate'] || $currentTime > $row['enddate']) {

                        unset($holdSeat[$key]);

                    }

                }

            //     echo $currentTime;

            //     print_r($holdSeat);

            //     exit;

            // }

            $mainTripId = $subtripInfo->trip_id;

            $subtripStopage = $this->subtripModel->where('trip_id', $mainTripId)->where('pick_location_id', $subtripInfo->pick_location_id)->where('drop_location_id', $subtripInfo->drop_location_id)->first();



            $TempBookedSeat = $this->getDynamicPickupDropCombinationsTemp($subtripInfo->pick_location_id, $subtripInfo->drop_location_id, $subtripStopage->stoppage, $journeydate, $subtripInfo->id);





            if(!empty($holdSeat)){

                foreach ($holdSeat as $seatRow) {

                    $seats = explode(',', $seatRow['seat_number']); // split by comma

                    foreach ($seats as $seat) {

                        $blockseat[] = trim($seat); // trim to clean whitespace

                    }

                }

                

            }

            if(!empty($TempBookedSeat)){

                foreach ($TempBookedSeat as $seatRow) {

                    $seats = explode(',', $seatRow['seat_names']); // split by comma

                    foreach ($seats as $seat) {

                        $holdseat[] = trim($seat); // trim to clean whitespace

                    }

                }

                

            }

            $this->ticketModel->where('tickets.trip_id', $subtripInfo->trip_id);

            $bookseat = array_column($this->ticketModel->findAll(), 'seatnumber');

        }



        // Build locations and taxes

        $pickdrop = $this->picdropModel->select('pickdrops.id as pickdropid,pickdrops.*,stands.*, stands.name as stand_name')

            ->join('stands', 'stands.id = pickdrops.stand_id')

            ->where('trip_id', $subtripInfo->id)
            
            ->orderBy('pickdrops.id','ASC')

            ->findAll();

        if(empty($pickdrop)){

            $pickdrop = $this->picdropModel->select('pickdrops.id as pickdropid,pickdrops.*,stands.*, stands.name as stand_name')

                ->join('stands', 'stands.id = pickdrops.stand_id')

                ->where('trip_id', $subtripInfo->trip_id)
                
                ->orderBy('pickdrops.id','ASC')

                ->findAll();

        }



        $tax = $this->taxModel->where('status', 1)->findAll();



        // Build subtrip info

        $subtrips = $this->subtripModel->select('trips.id as tripid,trips.*,fleets.*,schedules.*,vehicles.*,subtrips.id as subtripId,subtrips.*, fleets.id as fleet_id')

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

            ->join('fleets', 'fleets.id = trips.fleet_id')

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

            ->join('vehicles', 'vehicles.id = trips.vehicle_id',"left")

            ->where('subtrips.status', 1)

            ->where('subtrips.id', $subTripId)

            ->findAll();

            if(isset($subtrips[0]->subtrip_seatclass) && !empty($subtrips[0]->subtrip_seatclass)){

                $seatClasses = $subtrips[0]->subtrip_seatclass ? json_decode($subtrips[0]->subtrip_seatclass, true) : "";        

            }else{

                $seatClasses = $subtrips[0]->seatclass ? json_decode($subtrips[0]->seatclass, true) : "";        

            }

        $adultFair = $subtrips[0]->adult_fair ?? "";





        return $this->response->setJSON([

            'status' => "success",

            'response' => 200,

            'subtrips' => json_encode($subtrips),

            'pickdrop' => json_encode($pickdrop),

            'tax' => json_encode($tax),

            'bookseat' => json_encode(implode(',', $bookseat)),

            'holdseat' => json_encode(implode(',', $holdseat)),

            'blockseat' => json_encode(implode(',', $blockseat)),

            'seatClass' => json_encode($seatClasses),

            'adultfare' => $adultFair,

        ]);

    }



    public function getSeatLayout()

    {

        $subTripId = $this->request->getVar('id');

        $fleetId = $this->request->getVar('fleet_id');

        $bookedSeats = $this->request->getVar('booked');

        $holdSeats = $this->request->getVar('hold');

        $blockSeats = $this->request->getVar('block');

        $normalizeSeatList = static function ($list): array {
            $out = [];
            foreach ((array) $list as $s) {
                if ($s === null || $s === '') {
                    continue;
                }
                $out[] = trim((string) $s);
            }

            return array_values(array_unique($out));
        };

        $bookedSeats = $normalizeSeatList($bookedSeats);

        $holdSeats = $normalizeSeatList($holdSeats);

        $blockSeats = $normalizeSeatList($blockSeats);

        $fleetInfo = $this->fleetTypeModel->find($fleetId);

        $fleetTotalSeat = $fleetInfo->total_seat;

        // print_r($fleetInfo);die;

        // build seat layout vars

        $seatLayout     = $fleetInfo->layout;

        $seatLayoutArr  = array_filter(explode('-', $seatLayout));

        $totalSeatInRow = array_sum($seatLayoutArr);

        $tSeatRowWithB  = $totalSeatInRow + count($seatLayoutArr) - 3;

        // print_r($tSeatRowWithB);die;

        $seatNumbers    = array_filter(explode(',', $fleetInfo->seat_number));

        // remove last seat

        // if fleet has last seat

        $lastSeat = '';

        // $fleetInfo->last_seat && $lastSeat = array_pop($seatNumbers);

        $seatinfo['forth_seat'] = $fleetInfo->forth_seat;

        $seatinfo['lastSheet'] = $fleetInfo->last_seat;

        $seatinfo['wc'] = $fleetInfo->wc;







        // build seat group/row

        $seatRowGroup = array_chunk($seatNumbers, $totalSeatInRow);

        $seatRows = array_map(function ($singleRow) use ($seatLayoutArr, $tSeatRowWithB, $bookedSeats, $holdSeats, $blockSeats) {

        // print_r($tSeatRowWithB);die;

            $newSingleRow = array();

            $currentTotalIndex = 0;



            foreach ($singleRow as $seatRowIndex => $singleSeat) {

                $seatRowIndex++;

                $seatKey = trim((string) $singleSeat);

                $newSingleRow[] = array(

                    'seatName' => $singleSeat,

                    'isBooked' => in_array($seatKey, $bookedSeats, true) ? 1 : 0,

                    'isHold' => in_array($seatKey, $holdSeats, true) ? 1 : 0,

                    'isBlock' => in_array($seatKey, $blockSeats, true) ? 1 : 0,

                );



                if (($seatRowIndex != count($singleRow)) && (current($seatLayoutArr) + $currentTotalIndex == $seatRowIndex)) {

                    $newSingleRow[] = '';

                    $currentTotalIndex += current($seatLayoutArr);

                    array_shift($seatLayoutArr);

                }

            }



            return array_pad($newSingleRow, $tSeatRowWithB, '');

        }, $seatRowGroup);



// print_r(count($seatRows));

// exit;

if(count($seatRows[count($seatRows)-1]) != count($seatRows[1])){

    $seatRows[count($seatRows)-2] = array_merge($seatRows[count($seatRows)-2],$seatRows[count($seatRows)-1]);

    unset($seatRows[count($seatRows)-1]);

}

// print_r($seatRows[count($seatRows)-2]);

// exit;

        // $lastRow = end($seatRows);

        // if ($previousRowIndex >= 0) {

        //     $previousRow = &$seatRows[$previousRowIndex];

        //     $outstandingSeats = array_splice($previousRow, $totalSeatInRow);

        //     $lastRow = array_merge($lastRow, $outstandingSeats);

        //     $seatRows[count($seatRows) - 1] = $lastRow;

        // }



        // print_r($seatRows);die;

        if ($lastSeat !== '') {

            // last seat exists

            // build last seat info

            $lastKey = trim((string) $lastSeat);

            $lastSeatInfo =  array(

                'seatName' => $lastSeat,

                'isBooked' => in_array($lastKey, $bookedSeats, true) ? 1 : 0,

                'isHold' => in_array($lastKey, $holdSeats, true) ? 1 : 0,

                'isBlock' => in_array($lastKey, $blockSeats, true) ? 1 : 0,

            );

            

            if (($lastBlankSpace = array_search('', end($seatRows))) !== false) {

                // an blank space exists in last row

                // last seat place into the last blank space

                $seatRows[count($seatRows) - 1][$lastBlankSpace] = $lastSeatInfo;

            } else {

                // create new row and last seat place into it

                $seatRows[][] = $lastSeatInfo;

            }

        }

        

        // print_r($seatRows);die;



        try {

            //if()

            $filePath = sprintf("%s\\ticket\\seatlayouts\\%s", $this->Viewpath, $seatLayout);

            return view($filePath, compact('subTripId', 'seatRows', 'totalSeatInRow'));

        } catch (\Throwable $e) {

            // print_r($filePath);die;

            if($seatLayout =='4-1'){

                // print_r($seatRows);

                // exit;

                $filePath = sprintf("%s\\ticket\\seatlayouts\\layoutfinal2", $this->Viewpath);

                return view($filePath, compact('subTripId', 'seatRows', 'totalSeatInRow','fleetTotalSeat','seatinfo'));

            }else if($seatLayout =='1-1'){

                $filePath = sprintf("%s\\ticket\\seatlayouts\\layoutfinal1-1", $this->Viewpath);

                return view($filePath, compact('subTripId', 'seatRows', 'totalSeatInRow','fleetTotalSeat','seatinfo'));

            }else if($seatLayout =='1-2' || $seatLayout =='2-1'){

                $filePath = sprintf("%s\\ticket\\seatlayouts\\layoutfinal1-2", $this->Viewpath);

                return view($filePath, compact('subTripId', 'seatRows', 'totalSeatInRow','fleetTotalSeat','seatinfo'));

            }else{

                $filePath = sprintf("%s\\ticket\\seatlayouts\\default3", $this->Viewpath);

            }

            return view($filePath, compact('subTripId', 'seatRows', 'totalSeatInRow', 'fleetTotalSeat','seatinfo'));

        }

    }



    public function booking()

    {

        if (empty($this->request->getVar())) {

            $failMsg = session()->getFlashdata('fail') ?: 'Session expired!';

            return redirect()->route('new-ticket')->with("fail", $failMsg);

        }



        $data['returndate'] = $this->request->getVar('returndate');



        $data['seatnumbers'] = $this->request->getVar('seatnumbers');

        $array = explode(",", $data['seatnumbers']);

        $daynamic = count($array);

        

        if (!empty($data['returndate'])) {



            $grandtotal = $this->request->getVar('grandtotal');

            // if($this->request->getVar('subtripId') == 209){


            $CompanyId = $this->subtripModel->select('trips.company_id as companyId')

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

            ->where('subtrips.status', 1)

            ->where('subtrips.id', $this->request->getVar('subtripId'))

            ->first();

            $discount = $this->roundtripdiscoundModel->where('status', 1)->where('company_id',$CompanyId->companyId)->first();

            // }
            $discountMoney = 0;

            $discountPercent = 0;

            if (!empty($discount)) {

                $roleId = (int) ($this->session->get('role_id') ?? 0);
                $isAdminSideBooking = ($roleId !== 3);
                $discountPercent = $isAdminSideBooking
                    ? (float) ($discount->discountrate ?? 0)
                    : (float) ($discount->onlinediscountrate ?? $discount->discountrate ?? 0);

                $caltulateDiscont = (float) ($discountPercent / 100) * $grandtotal;

                $discountMoney = (float)  $grandtotal - (float)$caltulateDiscont;

            } else {

                $discountMoney = $grandtotal;

                $discountPercent = 0;

                $caltulateDiscont = 0;

            }



            $singleTripData['subtripId'] =  $this->request->getVar('subtripId');

            $singleTripData['seatnumbers'] = $this->request->getVar('seatnumbers');

            $singleTripData['totalseat'] =  $daynamic;

            $singleTripData['journeydate'] = $this->request->getVar('journeydate');

            $singleTripData['aseat'] = $this->request->getVar('aseat');

            $singleTripData['spseat'] = $this->request->getVar('spseat');

            $singleTripData['vpseat'] = $this->request->getVar('vpseat')??"";

            $singleTripData['cseat'] = $this->request->getVar('cseat');

            $singleTripData['totalprice'] = $this->request->getVar('totalprice');

            $singleTripData['tax'] = $this->request->getVar('tax');

            $singleTripData['grandtotal'] = $discountMoney;

            $singleTripData['pickstand'] = $this->request->getVar('pickstand');

            $singleTripData['dropstand'] = $this->request->getVar('dropstand');

            $singleTripData['discountPercent'] = $discountPercent;

            $singleTripData['roundtrip_discount'] = $caltulateDiscont;



            $this->session->set($singleTripData);



            return redirect()->route('roundfindtrip-ticket');

        } else {

            $data['filterpath'] = $this->Viewpath;

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

            $query = $builder->get();

            $data['country'] = $query->getResult();



            $data['subtripId'] = $this->request->getVar('subtripId');

            $data['seatnumbers'] = $this->request->getVar('seatnumbers');



            $array = explode(",", $data['seatnumbers']);



            $daynamic = count($array);

            $data['dynamicfield'] = $daynamic - 1;



            $data['totalseat'] = $daynamic;



            $data['journeydate'] = $this->request->getVar('journeydate');





            $data['aseat'] = $this->request->getVar('aseat');

            $data['spseat'] = $this->request->getVar('spseat');

            $data['vpseat'] = $this->request->getVar('vpseat')??"";

            $data['cseat'] = $this->request->getVar('cseat');



            $data['totalprice'] = $this->request->getVar('totalprice');

            $data['tax'] = $this->request->getVar('tax');







            if ($this->session->has('discountPercent')) {

                $percentDiscount = $this->session->get('discountPercent');

                $getGrandtotal = $this->request->getVar('grandtotal');

                $caltulateDiscont = (float) ($percentDiscount / 100) * $getGrandtotal;

                $discountMoney = (float)  $getGrandtotal - (float)$caltulateDiscont;

                $data['grandtotal'] = $discountMoney;

                $data['roundtrip_discount'] = $caltulateDiscont;

            } else {



                $data['grandtotal'] = $this->request->getVar('grandtotal');

                $data['roundtrip_discount'] = 0;

            }







            $data['pickstand'] = $this->request->getVar('pickstand');

            $data['dropstand'] = $this->request->getVar('dropstand');





            $data['paymethod'] = $this->paymethodModel->where('status', 1)->findAll();



            $data['module'] =    lang("Localize.ticket_booking");

            $data['title']  =    lang("Localize.ticket_list");



            $heading = lang("Localize.book") . ' ' . lang("Localize.ticket");

            $data['pageheading'] = $heading;



            $data['discount'] = $this->session->get('discount');

            $data['coupon'] = $this->session->get('coupon');

            $data['rountripStatus'] = 0;

            $data['isrountrip'] = 0;

            $maxtime = $this->maxtimeModel->where('book_from', "admin")->first();

            $expirytime = $maxtime->maxtime ?? 5;

            // $expirytime = 1;

            $expires_at = date('Y-m-d H:i:s', strtotime("+{$expirytime} minutes"));

            $data['expirytime_minutes'] = $expirytime;

            $data['expires_at'] = $expires_at;





            

            // $tempbooking = ['subtrip_id'   => $this->request->getVar('subtripId'),

            //                 'ticket_token' => 'backendd'.$this->request->getVar('subtripId'),

            //                 'seat_names'   => $this->request->getVar('seatnumbers'),

            //                 'journey_date' => $this->request->getVar('journeydate'),

            //                 'created_at'   => date('Y-m-d H:i:s'),

            //                 'expires_at'   => date('Y-m-d H:i:s', strtotime('+5 minutes'))];



            // $this->TemporaryBook->insert($tempbooking);



            echo view($this->Viewpath . '\ticket\booking', $data);

        }

    }



    public function create()

    {

        



        $rand = substr(str_shuffle('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 1, 8);

        $rand = "TB" . $rand;

        $maitripid = null;

        $subtripid = null;

        $piclocation = null;

        $droplocation = null;

        $vehicles_id = null;

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

        $subTripId = $this->request->getVar('subtripId');

        $payment_detail_rocord = $this->request->getVar('paydetail');



        $subtrips = $this->subtripModel->select('trips.id as tripid,trips.*,fleets.*,schedules.*,vehicles.*,subtrips.id as subtripId,subtrips.*,trips.company_id as companyId')

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

            ->join('fleets', 'fleets.id = trips.fleet_id')

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

            ->join('vehicles', 'vehicles.id = trips.vehicle_id',"left")

            ->where('subtrips.status', 1)

            ->where('subtrips.id', $subTripId)

            ->findAll();

        $companyId = $subtrips[0]->companyId??0;

        foreach ($subtrips as $key => $value) {

            $maitripid = $value->tripid;

            $subtripid = $value->id;

            $piclocation = $value->pick_location_id;

            $droplocation = $value->drop_location_id;

            $vehicles_id = $value->vehicle_id;

        }



        // get user info

        $login_email = $this->request->getVar('login_email');

        $login_mobile = $this->request->getVar('login_mobile');

        

        $first_name = $this->request->getVar('first_name');

                $fullName = $this->nameFilter($first_name);

                $first_name = $fullName['first_name'];

              //  print_r($fullName);die;

        if($login_mobile == ""){

            $demoemail = $first_name."123@gmail.com";

            $login_email = $demoemail;

        }

        

        $userid = $this->userCheck($login_email, $login_mobile);



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

        $bookUserId = $this->session->get('role_id');



        // Get role info

        $roelinfo = $this->roleModel->find($bookUserId);

        $bookUserType = $roelinfo->name;



        $ticketbooking = array(

            "booking_id" => $rand,

            "trip_id" => $maitripid,

            "subtrip_id" => $subtripid,

            "passanger_id" => $userid,

            "pick_location_id" => $piclocation,

            "drop_location_id" => $droplocation,

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

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

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

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

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

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

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

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

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

            "vip" => $this->request->getVar('vpseat')??"",

            "refund" => 0,

            "bookby_user_id" =>  $loginUserId,

            "bookby_user_type" => $bookUserType,

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

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

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

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

            "note" => $this->request->getVar('address')??"",

            "vehicle_id" => $vehicles_id,

            "cancel_status" => 0,

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

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

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

            "roundtrip_discount" => 0,

        );

        $checkbooking = $this->isAlreadybooked($maitripid, $subtripid, $userid, $piclocation, $droplocation, $this->request->getVar('totalseat'), $this->request->getVar('seatnumbers'),$this->request->getVar('journeydate'));

        if($checkbooking){

            return redirect()->route('allbookinglist-ticket')->with("fail", "Allready booked.");

        }



        $validTicketbooking = array(

            "booking_id" => $rand,

            "trip_id" => $maitripid,

            "subtrip_id" => $subtripid,

            "passanger_id" => $userid,



            "pick_location_id" => $piclocation,

            "drop_location_id" => $droplocation,

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

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



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

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

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

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

            "bookby_user_id" => 1,

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

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

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

            "vehicle_id" => $vehicles_id,

        );



        if ($this->validation->run($validTicketbooking, 'ticket')) {

            $this->db->transStart();

            $paymentStatus = $this->request->getVar('payment_status');



            if ($paymentStatus == "unpaid") {

                $paidamount = 0;

            }



            if ($paymentStatus == "paid") {

                $paidamount = $this->request->getVar('grandtotal');

            }



            if ($paymentStatus == "partial") {

                $paidamount = $this->request->getVar('partialpay');

            }

            $userRole = $this->session->get('role_id');



            if(($userRole == 2)){



                $agetnDetail =  $this->agentModel->where('user_id', $this->session->get('user_id'))->first();



                $walletAmount = $this->agentPayment->select('SUM(payagents.amount) as total_amount')

                ->join('agents', 'agents.id = payagents.agent_id', 'left')

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

                ->where('payagents.agent_id', $agetnDetail->id)

                ->where('companies.id ',$companyId)

                ->where('payagents.status',1)

                ->groupBy('companies.name')

                ->first();

                if (!is_object($walletAmount) || agent_wallet_insufficient_for_booking($walletAmount->total_amount ?? null, $paidamount)){

                    $errmsg = admin_bilingual_lang('Localize.insufficient_balance');

                    $seatNumbers = $this->request->getVar('seatnumbers');

                    $this->deleteHoldSeat($seatNumbers,$subtripid);

                    return redirect()->route('allbookinglist-ticket')->with("fail", $errmsg);

                }



            }

            



            $partialPaid = array(

                "booking_id" => $rand,

                "trip_id" => $maitripid,

                "subtrip_id" => $subtripid,

                "passanger_id" => $userid,

                "paidamount" => $paidamount,

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

            );

            $paidpartial = array(

                "booking_id" => $rand,

                "trip_id" => $maitripid,

                "subtrip_id" => $subtripid,

                "passanger_id" => $userid,

                "paidamount" => $paidamount,

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

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

            );



            $this->ticketModel->insert($ticketbooking);





            if ($this->validation->run($partialPaid, 'partialpay')) {



                $this->partialpaidModel->insert($paidpartial);



                $pick_stand_id = $this->request->getVar('pickstand');

                $drop_stand_id = $this->request->getVar('dropstand');



                $journeylist = $this->journeylist($rand, $userid, $maitripid, $subtripid, $piclocation, $droplocation, $pick_stand_id, $drop_stand_id, $ticketbooking['journeydata']);



                



                if (($userRole == 2) && ($paymentStatus != "unpaid")) {

                    $totalprice =  $paidamount;

                    $type = "income";

                    $message = "For Ticket Booking";



                    $agentIncome = agentIncomeCommission($backUserId, $totalprice, $rand, $subtripid, $userid, $message, $companyId);



                    $agentTotalIncome =   agentTotal($backUserId, $totalprice, $rand, $type, $payment_detail_rocord);



                    // if( $this->request->getVar('pay_method')== 1){

                        $agetnDetail =  $this->agentModel->where('user_id', $this->session->get('user_id'))->first();

                        $agentIncome = agentExpenseTicketCharge($agetnDetail->id, $totalprice, $rand, $subtripid, $userid, $message, $companyId);

                    // }

                }

            }



            if ($paymentStatus != "unpaid") {

                $paymethod_id = $this->request->getVar('pay_method');

                $payDetail = $this->request->getVar('paydetail');

                $type = "income";

                $detail = "Ticket Booking (" . $rand . ") ";

                accoutTranjection($type, $detail, $paidamount, $backUserId, $rand, "booking");

                paymethodTeanjection($rand, $paymethod_id, $paidamount, $payDetail, $maitripid, $subtripid, $backUserId);



                $couponcode = $this->request->getVar('offerer');



                if (!empty($couponcode)) {

                    $validDetail = $this->couponModel->where('code', $couponcode)->findAll();





                    $coupondetail = array(

                        "code" => $couponcode,

                        "coupon_id" => $validDetail[0]->id,

                        "booking_id" => $rand,

                        "subtrip_id" => $subtripid,

                        "amount" => $validDetail[0]->discount,



                    );



                    $this->coupondiscountModel->insert($coupondetail);

                }

            }



            $this->db->transComplete();
            
            $this->createTicketNotifications($rand, $userid, $maitripid, $subtripid, $this->request->getVar('journeydate'));

            $ticketmailLibrary = new Ticketmail();

            $emaildata = $ticketmailLibrary->getticketEmailData($rand);

            $status = sendTicket($login_email, $emaildata);



          //  if ($status == true) {

                return redirect()->route('allbookinglist-ticket')->with("success", "Ticket created successfully");

            //}

        }



        return redirect()->route('new-ticket')->with("fail", $this->validation->listErrors());

    }



    public function userCheck($login_email, $login_mobile)

    {

        

        $userid = null;

        if($login_email != ""){

            $evalue = $this->userModel->where('login_email', $login_email)->findAll();

        }else{

            $evalue = "";

        }

        if($login_mobile != ""){

            $mvalue = $this->userModel->where('login_mobile', $login_mobile)->findAll();

        }else{

            $mvalue = "";

        }

        // $evalue = $this->userModel->where('login_email', $login_email)->findAll();

        // $mvalue = $this->userModel->where('login_mobile', $login_mobile)->findAll();



        if (!empty($evalue) || !empty($mvalue)) {

            if ($evalue) {

                foreach ($evalue as $key => $mobilevalue) {

                    $userid = $mobilevalue->id;

                }

            }

            if ($mvalue) {

                foreach ($mvalue as $key => $emailvalue) {

                    $userid = $emailvalue->id;

                }

            }



            return $userid;

        } else {

            $status = 1;

            $role_id = 3;

            $slug = bin2hex(random_bytes(5));

            $password = $confirm = "123456";

            if($login_email == ""){

                $login_email = null;

            }else{

                $login_email = $login_email;

            }





            $userData = array(

                "login_email" => $login_email,

                "login_mobile" => $login_mobile,

                "password" => $password,

                "confirm" => $confirm,

                "slug" => $slug,

                "role_id" => $role_id,

                "status" => $status,

            );



            if ($this->validation->run($userData, 'user')) {

                $this->db->transStart();



                $userData['password'] = password_hash($password, PASSWORD_DEFAULT);

                $userid = $this->userModel->insert($userData);

                $first_name = $this->request->getVar('first_name');

                $fullName = $this->nameFilter($first_name);

                $first_name = $fullName['first_name'];

                $last_name = $fullName['last_name'];

                $validdata = array(

                    "user_id" => $userid,

                    "first_name" => $first_name,

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

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

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

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

                );



                if ($this->validation->run($validdata, 'userDetail')) {

                    $data = array(

                        "user_id" => $userid,

                        "first_name" => $first_name,

                        "last_name" => $last_name,

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

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

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

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

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

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

                    );



                    $this->userDetailModel->insert($data);



                    $this->db->transComplete();

                }

            }



            return $userid;

        }

    }

    

     function nameFilterold($full_name){

        // Split the full name by spaces

        $name_parts = explode(" ", $full_name);

        

        // Initialize variables for first name, middle name(s), and last name

        $first_name = ""; // Initialize first name as an empty string

        $middle_name = ""; // Initialize middle name as an empty string

        $last_name = ""; // Initialize last name as an empty string

        

        // Extract the last name (always the last part)

        $last_name = array_pop($name_parts);

    

        // If there are remaining parts, set the first name and middle name(s)

        if (!empty($name_parts)) {

            // First name is the first part

            $first_name = array_shift($name_parts);

            // If there are remaining parts, they are middle name(s)

            if (!empty($name_parts)) {

                // Concatenate the remaining parts as middle name(s)

                $middle_name = implode(" ", $name_parts);

            }

        }

        

        // Prepare the data array

        $data['first_name'] = $first_name;

        $data['last_name'] = $last_name;

        

        return $data;

    }

    function nameFilter($full_name) {

        // Trim and split the name at the first space

        $full_name = trim($full_name);

        $spacePos = strpos($full_name, ' ');



        if ($spacePos === false) {

            // No space found — whole name is the first name

            $first_name = $full_name;

            $last_name = '';

        } else {

            $first_name = substr($full_name, 0, $spacePos);

            $last_name = substr($full_name, $spacePos + 1);

        }



        return [

            'first_name' => $first_name,

            'last_name' => $last_name

        ];

    }





    public function journeylist($rand, $userid, $maitripid, $subtripid, $piclocation, $droplocation, $pick_stand_id, $drop_stand_id, $journeydate = "")

    {

        if($journeydate == ""){

            $journeydate = date("Y-m-d", strtotime($this->request->getVar('journeydate')));    

        }

        $joruneylistid = null;



        $mainpassanger = array(

            "booking_id" => $rand,

            "trip_id" => $maitripid,

            "subtrip_id" => $subtripid,

            "pick_location_id" => $piclocation,

            "drop_location_id" => $droplocation,

            "pick_stand_id" => $pick_stand_id,

            "drop_stand_id" => $drop_stand_id,

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

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

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

            "journeydate" => $journeydate,

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

        );



        if ($this->validation->run($mainpassanger, 'journeylist')) {

            $joruneylistid = $this->journeylistModel->insert($mainpassanger);

        }



        $newPassangerFName = $this->request->getVar('first_name_new');

        $newPassangerLName = $this->request->getVar('last_name_new');

        $newPassangerMobile = $this->request->getVar('login_mobile_new');

        $newPassangerNidNumber = $this->request->getVar('id_number_new');



        if (!empty($newPassangerFName)) {

            foreach ($newPassangerFName as $nkey => $newpassanger) {

                $newpassangerlist[$nkey] = array(



                    "booking_id" => $rand,

                    "trip_id" => $maitripid,

                    "subtrip_id" => $subtripid,

                    "pick_location_id" => $piclocation,

                    "drop_location_id" => $droplocation,

                    "pick_stand_id" => $pick_stand_id,

                    "drop_stand_id" => $drop_stand_id,

                    "first_name" => $newPassangerFName[$nkey],

                    "last_name" => $newPassangerLName[$nkey],

                    "phone" => $newPassangerMobile[$nkey],

                    "journeydate" => $journeydate,

                    "id_number" => $newPassangerNidNumber[$nkey],



                );

            }







            $this->journeylistModel->insertBatch($newpassangerlist);

        }





        return   $joruneylistid;

    }



    public function allbookinglist()

    {

        $rolepermissionLibrary = new Rolepermission();

        $refund_action = "refund_list";

        $cancel_action = "cancel_list";



        $data['refund_create'] = $rolepermissionLibrary->create($refund_action);

        $data['cancel_create'] = $rolepermissionLibrary->create($cancel_action);
        $ridDb = (int) session()->get('role_id');
        $data['cancel_create_online'] = ($ridDb === 1) || $rolepermissionLibrary->create('cancel_online_ticket');



        $pickdrops =  $this->picdropModel

            ->select('stands.id as standId,stands.*,pickdrops.*, stands.name as stand_name')

            ->join('stands', 'stands.id = pickdrops.stand_id')

            ->withDeleted()

            ->findAll();



        // print_r($pickdrops);

        // dd("asdasd");



        // use pagination to avoid loading all tickets at once
        $perPage = 50; // tickets per page
        $data['ticket'] = $this->filterBooking(true, $perPage);
        $data['pager'] = $this->ticketModel->pager;

        $data['location'] =  $this->locationModel->withDeleted()->findAll();

        $data['pickdropstand'] =  $pickdrops;

        $data['paymethod'] = $this->paymethodModel->where('status', 1)->findAll();



        // capture search term (server-side filter across all tickets)
        $search = $this->request->getGet('search');
        $data['search'] = $search;

        $data['module'] =    lang("Localize.ticket_booking");

        $data['title']  =    lang("Localize.ticket_list");

        $data['pageheading'] = lang("Localize.ticket_list");



        return view($this->Viewpath . '\ticket\bookinglist', $data);

    }



    public function filterBooking(bool $usePagination = false, int $perPage = 50)

    {

        $userRole = $this->session->get('role_id');

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

        // print_r($this->session->get());

        // exit;

        if (!in_array($userRole,[1,2,7])) {

            //not agent company and super admin

            // user role is agent or employee

            // list only user booking lists

            $rolepermissionLibrary = new Rolepermission();

            if (!$rolepermissionLibrary->create('all_tickets')) {

                $this->ticketModel->where('bookby_user_id', $userId);

            }else{

                $this->ticketModel->where('trips.company_id', session()->get('company_id'));

            }

        }else{

            if(in_array($userRole,[7])){

              $this->ticketModel->where('trips.company_id', session()->get('company_id'));

            }

            if(in_array($userRole,[2])){

              $this->ticketModel->whereIn('trips.company_id', explode(",", session()->get('company_id')))->where('bookby_user_id', $userId);

            }

        }



        $this->ticketModel->where('cancel_status', 0);

        $this->ticketModel->where('refund', 0);

        // $this->ticketModel->where('tickets.journeydata >=', '2025-08-21 00:00:00');

        // global search filter (if provided)
        $search = $this->request->getGet('search');
        if (!empty($search)) {
            $this->ticketModel
                ->groupStart()
                    ->like('tickets.booking_id', $search)
                    ->orLike('companies.name', $search)
                    ->orLike('user_details.first_name', $search)
                    ->orLike('user_details.last_name', $search)
                    ->orLike('tickets.payment_status', $search)
                ->groupEnd();
        }

        $this->ticketModel->select('tickets.*,CONCAT(user_details.first_name," ",user_details.last_name) as passengerName, CONCAT(COALESCE(booker.first_name, booker_agents.first_name,booker_agents_emp.first_name), " ", COALESCE(booker.last_name, booker_agents.last_name, booker_agents_emp.last_name)) AS booked_by, companies.name as company_name');

        $this->ticketModel->join("user_details","user_details.user_id = tickets.passanger_id");

        $this->ticketModel->join("user_details AS booker","booker.user_id = tickets.bookby_user_id","left");

        $this->ticketModel->join("agents AS booker_agents","booker_agents.user_id = tickets.bookby_user_id","left");

        $this->ticketModel->join("users","users.id = tickets.bookby_user_id","left");

        $this->ticketModel->join("employees AS booker_agents_emp","booker_agents_emp.email = users.login_email","left");

        $this->ticketModel->join("trips","trips.id = tickets.trip_id","left");

        $this->ticketModel->join("companies","trips.company_id = companies.id","left");

        $this->ticketModel->orderBy('id', 'DESC');

        if ($usePagination) {
            // Use pagination instead of loading all tickets into memory.
            // This keeps the ticket list fast even with a large number of records.
            return $this->ticketModel->withDeleted()->paginate($perPage);
        }

        return $this->ticketModel->withDeleted()->findAll();

    }

    /**
     * Export all tickets (optionally filtered by search term) as CSV.
     */
    public function exportAllTickets()
    {
        // reuse the same filters as the list, but without pagination
        $tickets = $this->filterBooking(false);

        $fp = fopen('php://temp', 'r+');
        fputcsv($fp, [
            '#',
            'Booking ID',
            'Company',
            'Pick Location',
            'Drop Location',
            'Seat Number',
            'Passenger Name',
            'Payment Status',
            'Journey Date',
            'Trip ID',
            'Booked By',
        ]);

        $i = 1;
        foreach ($tickets as $value) {
            $journeyDate = $value->journeydata ? date('Y-m-d', strtotime($value->journeydata)) : '';
            $bookedBy = isset($value->bookby_user_type)
                ? (($value->bookby_user_type == 'passanger') ? 'online' : $value->bookby_user_type) . '(' . ($value->booked_by ?? '') . ')'
                : '';

            fputcsv($fp, [
                $i++,
                $value->booking_id,
                $value->company_name,
                '', // pick location name (left blank here to avoid heavy joins again)
                '', // drop location name
                $value->seatnumber,
                $value->passengerName,
                $value->payment_status,
                $journeyDate,
                $value->trip_id,
                $bookedBy,
            ]);
        }

        rewind($fp);
        $csv = stream_get_contents($fp);
        fclose($fp);

        return $this->response
            ->setHeader('Content-Type', 'text/csv')
            ->setHeader('Content-Disposition', 'attachment; filename="tickets_' . date('Ymd_His') . '.csv"')
            ->setBody($csv);
    }



    public function agentCommission($totalprice)

    {

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

        $agetnDetail =  $this->agentModel->where('user_id', $userId)->first();

        (float)$commission = (float)(($totalprice) * ($agetnDetail->commission / 100));

        return $commission;

    }





    public function roundfindtrip()

    {

        $websetting = $this->websettingModel->first();



        $pick_location_id = $this->session->get('drop_location_id');

        $drop_location_id = $this->session->get('pick_location_id');

        $filterjourneydate = $this->session->get('filterreturndate');



        // build journey date

        $journeyDate = date('Y-m-d', strtotime($filterjourneydate));

        $journeyDayOfWeek = date('N', strtotime($filterjourneydate));



        $fleet_id = $this->session->get('fleet_id');



        $monthcomparedate =  date('Y-m-d', strtotime('+1 month'));



        if ($filterjourneydate > $monthcomparedate) {

            return redirect()->route('new-ticket')->with("fail", "No advance booking for this day");

        }

        $company_id = session()->get('company_id') ?? 0;

        if(($this->request->getVar('company_id') || $this->request->getVar('company_id') == 0) && session()->get('role_id') == "1"){

            $company_id = $this->request->getVar('company_id') ?? 0;

        } else {

            if(session('search_company_id')){

                $company_id = session('search_company_id');

            }

        }



        $data = array('trips' => [], 'in_holiday' => [], 'to_open' => [], 'inactive' => [], 'you_may_like' => []);

        $data['pick_location_id'] = $pick_location_id;

        $data['drop_location_id'] = $drop_location_id;

        $data['filterjourneydate'] = $filterjourneydate;

        $data['filterreturndate'] = "";

        $data['fleet_id'] = $fleet_id;

        $data['company_id'] = $company_id;



        $data['filterpath'] = $this->Viewpath;

        $data['location'] = $this->locationModel->findAll();

        $data['fleet_type'] = $this->fleetTypeModel->findAll();

        $data['companies'] = $this->CompanyModel->findAll();





        if (strpos($company_id, ',')) { 

            $company_ids = explode(',', $company_id);

        } else {

            $company_ids = [$company_id];

        }



        $allSubTrips = $this->getAllTrip($pick_location_id, $drop_location_id, $fleet_id, $company_ids);



        foreach ($allSubTrips as $subTrip) {

            if ($subTrip->status == 0) {

                // subtrip is inactive

                $data['inactive'][] = $subTrip;

                continue;

            }



            if (strtotime($journeyDate) < strtotime($subTrip->startdate)) {

                // subtrip yet not begin

                $data['to_open'][] = $subTrip;

                continue;

            }
            
            $cleanedoffdates = preg_replace('/\s+/', '', $subTrip->offdates);

            if (in_array($journeyDate,explode(",", $cleanedoffdates))) {

                // subtrip is off today

                $data['in_holiday'][] = $subTrip;

                continue;

            }
            
            if ($this->isDateInRange($journeyDate, $subTrip->startdateinrange, $subTrip->enddateinrange)) {

                // subtrip is not in range

                $data['in_holiday'][] = $subTrip;

                continue;

            }
            
            $offdateranges = json_decode($subTrip->offdateranges, true);

            $isInAnyRange = false;

            if (is_array($offdateranges) && !empty($offdateranges)) {

                foreach ($offdateranges as $range) {

                    $start = $range['start'] ?? null;

                    $end = $range['end'] ?? null;



                    if ($start && $end && $this->isDateInRange($journeyDate, $start, $end)) {

                        $isInAnyRange = true;

                        break;

                    }

                }

            }



            if ($isInAnyRange) {

                $data['in_holiday'][] = $subTrip;

                continue;

            }
            if (!$this->isDateInRange($journeyDate, $subTrip->repetedstartdate, $subTrip->repetedenddate)) {

                if($journeyDate != date('Y-m-d',strtotime($subTrip->startdate))){

                    //start date and not between start and edn date

                    $data['in_holiday'][] = $subTrip;

                    continue;    

                }

                

            }



            $today = new \DateTime(date('Y-m-d'));



            $journeyDateObj = new \DateTime(date('Y-m-d', strtotime($journeyDate)));

            $interval = $today->diff($journeyDateObj);

            $bookingToday = new \DateTime(date('Y-m-d'));
            $bookingWindowInterval = $bookingToday->diff($journeyDateObj);

            if ($subTrip->maxdayforbooking > 0 && ($subTrip->maxdayforbooking < $bookingWindowInterval->days)) {

                //not allowed to book tickets

                $data['in_holiday'][] = $subTrip;

                continue;

            }



            if ($this->isDateInRange($journeyDate, $subTrip->repetedstartdate, $subTrip->repetedenddate)) {

                if($journeyDate != date('Y-m-d',strtotime($subTrip->startdate))){

                    if($subTrip->repeted_after > 0 && $interval->days > 0){

                        if($interval->days%$subTrip->repeted_after > 0){

                            //start date and not between start and edn date

                            $data['in_holiday'][] = $subTrip;

                            continue;

                        }

                    }

                    

                }

                

            }


            if (@in_array($journeyDayOfWeek, explode(',', $subTrip->weekend))) {

                // subtrip is on holiday

                $data['in_holiday'][] = $subTrip;

                continue;

            }



            if (($subTrip->pick_location_id != $pick_location_id) || ($subTrip->drop_location_id != $drop_location_id)) {

                // subtrip is related to selected locations

                $data['you_may_like'][] = $subTrip;

                continue;

            }

            

            $subtripInfo = $this->subtripModel->find($subTrip->id);

            $this->ticketModel

            ->where('journeydata', $filterjourneydate)

            ->where('cancel_status', 0)

            ->where('refund', 0);



            if ($subtripInfo->type == 'subtrip') {

                $mainTripId = $subtripInfo->trip_id;

                $subtripStoppagePointsArr = array_filter(explode(',', $subtripInfo->stoppage));

                $mainTripMainSubtripId = $this->subtripModel->where('trip_id', $mainTripId)->where('type', 'main')->first();



                $subtripStopage = $this->subtripModel->where('trip_id', $mainTripId)->where('pick_location_id', $subtripInfo->pick_location_id)->where('drop_location_id', $subtripInfo->drop_location_id)->first();

                $results = $this->getDynamicPickupDropCombinations($subtripInfo->pick_location_id, $subtripInfo->drop_location_id, $subtripStopage->stoppage, $filterjourneydate, $mainTripId);

                $bookseat = array_column($results, 'seatnumber');



            } else {

                $this->ticketModel->where('tickets.trip_id', $subtripInfo->trip_id);

                $bookseat = array_column($this->ticketModel->findAll(), 'seatnumber');

            }



            $separatedSeats = [];

            foreach ($bookseat as $seats) {

                // Use explode to separate the comma-separated seat numbers

                $separatedSeats = array_merge($separatedSeats, explode(',', $seats));

            }

            $subTrip->bookseatCount = is_array($separatedSeats)?count($separatedSeats):0;

            $pickdrop = $this->picdropModel->select('pickdrops.id as pickdropid,pickdrops.*,stands.*, stands.name as stand_name')

                ->join('stands', 'stands.id = pickdrops.stand_id')

                ->where('trip_id', $subtripInfo->id)

                ->findAll();

            if(empty($pickdrop)){

                $pickdrop = $this->picdropModel->select('pickdrops.id as pickdropid,pickdrops.*,stands.*, stands.name as stand_name')

                    ->join('stands', 'stands.id = pickdrops.stand_id')

                    ->where('trip_id', $subtripInfo->trip_id)

                    ->findAll();

            }

            // print_r($pickdrop);

            $pickup_time = null;

            $drop_time = null;



            // foreach ($pickdrop as $item) {

            //     if ($item->type == 1) {

            //         $pickup_time = $item->time;

            //     } elseif ($item->type == 0) {

            //         $drop_time = $item->time;

            //     }

            // }

            $pickup_time = null;

            $drop_time = null;



            foreach ($pickdrop as $item) {

                if ($item->type == 1) {

                    // Smallest pickup time

                    if (is_null($pickup_time) || strtotime($item->time) < strtotime($pickup_time)) {

                        $pickup_time = $item->time;

                    }

                } elseif ($item->type == 0) {

                    // Largest drop time

                    if (is_null($drop_time) || strtotime($item->time) > strtotime($drop_time)) {

                        $drop_time = $item->time;

                    }

                }

            }





            $subTrip->pickup_time = $pickup_time;

            $subTrip->drop_time = $drop_time;



            $data['trips'][] = $subTrip;

        }



        $data['taxtype'] = $websetting->tax_type;

        $data['rountripStatus'] = 1;



        $data['module'] =    lang("Localize.ticket_booking");

        $data['title']  =    lang("Localize.book_ticket");



        $heading = lang("Localize.book") . ' ' . lang("Localize.ticket");

        $data['pageheading'] = $heading;

        $data['triptype'] = lang("Localize.round") . ' ' . lang("Localize.trip");

        $data['isrountrip'] = 1;

        $data['totalseat'] = $this->session->get('totalseat');



        $isroundtrip['isrountrip'] = 1;



        $this->session->set($isroundtrip);



        return view($this->Viewpath . '\ticket\index', $data);

    }





    public function roundcreate()

    {



        $ticketmailLibrary = new Ticketmail();



        //single Trip Ticket Booking

        $rand = substr(str_shuffle('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 1, 8);

        $rand = "TB" . $rand;

        $maitripid = null;

        $subtripid = null;

        $piclocation = null;

        $droplocation = null;

        $vehicles_id = null;

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

        $subTripId = $this->session->get('subtripId');

        $payment_detail_rocord = $this->request->getVar('paydetail');



        $discount = $this->request->getVar('discount');



        if ((!empty($discount)) && $discount > 0) {

            $getDiscount = (float) $discount / 2;

        } else {

            $getDiscount = 0;

        }



        $subtrips = $this->subtripModel->select('trips.id as tripid,trips.*,fleets.*,schedules.*,vehicles.*,subtrips.id as subtripId,subtrips.*,trips.company_id as companyId')

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

            ->join('fleets', 'fleets.id = trips.fleet_id')

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

            ->join('vehicles', 'vehicles.id = trips.vehicle_id', "left")

            ->where('subtrips.status', 1)

            ->where('subtrips.id', $subTripId)

            ->findAll();


        $companyId = $subtrips[0]->companyId??0;


        foreach ($subtrips as $key => $value) {

            $maitripid = $value->tripid;

            $subtripid = $value->id;

            $piclocation = $value->pick_location_id;

            $droplocation = $value->drop_location_id;

            $vehicles_id = $value->vehicle_id;

        }





        $login_email = $this->request->getVar('login_email');

        $login_mobile = $this->request->getVar('login_mobile');



        $userid = $this->userCheck($login_email, $login_mobile);



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



        $bookUserId = $this->session->get('role_id');



        $roelinfo = $this->roleModel->find($bookUserId);



        $bookUserType = $roelinfo->name;



        $pay_method_id = $this->request->getVar('pay_method');



        $payment_status = $this->request->getVar('payment_status');

        $payment_detail = $this->request->getVar('paydetail');



        $ticketbooking = array(

            "booking_id" => $rand,

            "trip_id" => $maitripid,

            "subtrip_id" => $subtripid,

            "passanger_id" => $userid,

            "pick_location_id" => $piclocation,

            "drop_location_id" => $droplocation,

            "pick_stand_id" => $this->session->get('pickstand'),

            "drop_stand_id" => $this->session->get('dropstand'),

            "price" => $this->session->get('totalprice'),

            "discount" =>  $getDiscount,

            "roundtrip_discount" =>  $this->session->get('roundtrip_discount'),

            "totaltax" => $this->session->get('tax'),

            "paidamount" => $this->session->get('grandtotal'),

            "adult" => $this->session->get('aseat'),

            "chield" => $this->session->get('cseat'),

            "special" => $this->session->get('spseat'),

            "vip" => $this->session->get('vpseat')??"",

            "refund" => 0,

            "bookby_user_id" =>  $loginUserId,

            "bookby_user_type" => $bookUserType,

            "journeydata" => $this->session->get('journeydate'),

            "pay_type_id" =>  $pay_method_id,

            // "payment_status" => $payment_status,

            "payment_detail" => $payment_detail,

            "vehicle_id" => $vehicles_id,

            "cancel_status" => 0,



            "offerer" => $this->session->get('offerer'),

            // "offerer" => 0,

            "seatnumber" => $this->session->get('seatnumbers'),

            "totalseat" => $this->session->get('totalseat'),



        );



        $validTicketbooking = array(



            "booking_id" => $rand,

            "trip_id" => $maitripid,

            "subtrip_id" => $subtripid,

            "passanger_id" => $userid,



            "pick_location_id" => $piclocation,

            "drop_location_id" => $droplocation,

            "pick_stand_id" => $this->session->get('pickstand'),

            "drop_stand_id" => $this->session->get('dropstand'),



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

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

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

            "totalseat" => $this->session->get('totalprice'),

            "bookby_user_id" => 1,

            "journeydata" => $this->session->get('journeydate'),

            "pay_type_id" => $pay_method_id,

            "payment_status" => $payment_status,

            "vehicle_id" => $vehicles_id,



        );





        if ($this->validation->run($validTicketbooking, 'ticket')) {

            $this->db->transStart();



            $paymentStatus = $this->request->getVar('payment_status');



            if ($paymentStatus == "unpaid") {

                $singleTripPaymentStatus = "unpaid";

                $roundTripPaymentStatus = "unpaid";

                $paidamount = $this->session->get('grandtotal');

                $roundtripPaid = $this->request->getVar('grandtotal');

                $roundPaidamount = (float) $roundtripPaid - (float)$paidamount;

                $transectionSingeltrip = 0;

                $transectionDoubletrip = 0;

            }

            if ($paymentStatus == "paid") {

                $paidamount = $this->session->get('grandtotal');

                $roundtripPaid = $this->request->getVar('grandtotal');

                $roundPaidamount = (float) $roundtripPaid - (float)$paidamount;

                $singleTripPaymentStatus = "paid";

                $roundTripPaymentStatus = "paid";

                $transectionSingeltrip = $paidamount;

                $transectionDoubletrip =   $roundPaidamount;

            }

            if ($paymentStatus == "partial") {

                $partialamount = $this->request->getVar('partialpay');

                $singelTripamount = $this->session->get('grandtotal');

                if ($partialamount < $singelTripamount) {

                    $paidamount = $this->session->get('grandtotal');

                    $roundtripPaid = $this->request->getVar('grandtotal');

                    $roundPaidamount = (float) $roundtripPaid - (float)$paidamount;

                    $singleTripPaymentStatus = "partial";

                    $roundTripPaymentStatus = "unpaid";

                    $transectionSingeltrip = $partialamount;

                    $transectionDoubletrip = 0;

                }



                if ($partialamount == $singelTripamount) {



                    $paidamount = $this->session->get('grandtotal');

                    $roundtripPaid = $this->request->getVar('grandtotal');

                    $roundPaidamount = (float) $roundtripPaid - (float)$paidamount;

                    $singleTripPaymentStatus = "paid";

                    $roundTripPaymentStatus = "unpaid";

                    $transectionSingeltrip = $partialamount;

                    $transectionDoubletrip = 0;

                }



                if ($partialamount > $singelTripamount) {



                    $paidamount = $this->session->get('grandtotal');

                    $roundtripPaid = $this->request->getVar('grandtotal');

                    $roundPaidamount = (float) $roundtripPaid - (float)$paidamount;



                    $extraMoney = (float) $partialamount - (float) $paidamount;

                    $singleTripPaymentStatus = "paid";

                    $roundTripPaymentStatus = "partial";



                    $transectionSingeltrip = $paidamount;

                    $transectionDoubletrip = $extraMoney;

                }

            }







            $ticketbooking['payment_status'] = $singleTripPaymentStatus;

            $this->ticketModel->insert($ticketbooking);



            $partialPaid = array(

                "booking_id" => $rand,

                "trip_id" => $maitripid,

                "subtrip_id" => $subtripid,

                "passanger_id" => $userid,

                "paidamount" => $transectionSingeltrip,

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

            );

            $paidpartial = array(

                "booking_id" => $rand,

                "trip_id" => $maitripid,

                "subtrip_id" => $subtripid,

                "passanger_id" => $userid,

                "paidamount" => $transectionSingeltrip,

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

                "payment_detail" => $payment_detail,

            );



            if ($this->validation->run($partialPaid, 'partialpay')) {

                $this->partialpaidModel->insert($paidpartial);

                $pick_stand_id = $this->session->get('pickstand');

                $drop_stand_id = $this->session->get('dropstand');



                $journeylist = $this->journeylist($rand, $userid, $maitripid, $subtripid, $piclocation, $droplocation, $pick_stand_id, $drop_stand_id, $ticketbooking['journeydata']);

                $userRole = $this->session->get('role_id');



                if (($userRole == 2) && ($singleTripPaymentStatus != "unpaid")) {

                    $totalprice =  $transectionSingeltrip;

                    $type = "income";

                    $message = "For Ticket Booking";

                    $agentIncome = agentIncomeCommission($backUserId, $totalprice, $rand, $subtripid, $userid, $message, $companyId);

                    $agentTotalIncome = agentTotal($backUserId, $totalprice, $rand, $type, $payment_detail_rocord);
                    
                      
                    $agetnDetail =  $this->agentModel->where('user_id', $this->session->get('user_id'))->first();

                    $agentIncome = agentExpenseTicketCharge($agetnDetail->id, $totalprice, $rand, $subtripid, $userid, $message, $companyId);

                }

            }





            if ($singleTripPaymentStatus != "unpaid") {

                $paymethod_id = $this->request->getVar('pay_method');

                $payDetail = $this->request->getVar('paydetail');

                $type = "income";

                $detail = "Ticket Booking (" . $rand . ") ";

                accoutTranjection($type, $detail, $transectionSingeltrip, $backUserId, $rand, "booking");

                paymethodTeanjection($rand, $paymethod_id, $transectionSingeltrip, $payDetail, $maitripid, $subtripid, $backUserId);

            }





            $roundrand = substr(str_shuffle('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 1, 8);

            $roundrand = "TB" . $roundrand;

            $maitripid = null;

            $subtripid = null;

            $piclocation = null;

            $droplocation = null;

            $vehicles_id = null;

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

            $subTripId = $this->request->getVar('subtripId');

            $payment_detail_rocord = $this->request->getVar('paydetail');



            $subtrips = $this->subtripModel->select('trips.id as tripid,trips.*,fleets.*,schedules.*,vehicles.*,subtrips.id as subtripId,subtrips.*,trips.company_id as companyId')

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

                ->join('fleets', 'fleets.id = trips.fleet_id')

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

                ->join('vehicles', 'vehicles.id = trips.vehicle_id',"left")

                ->where('subtrips.status', 1)

                ->where('subtrips.id', $subTripId)

                ->findAll();

            $companyId = $subtrips[0]->companyId??0;


            foreach ($subtrips as $key => $value) {

                $maitripid = $value->tripid;

                $subtripid = $value->id;

                $piclocation = $value->pick_location_id;

                $droplocation = $value->drop_location_id;

                $vehicles_id = $value->vehicle_id;

            }





            $roundticketbooking = array(

                "booking_id" => $roundrand,

                "trip_id" => $maitripid,

                "subtrip_id" => $subtripid,

                "passanger_id" => $userid,

                "pick_location_id" => $piclocation,

                "drop_location_id" => $droplocation,

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

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

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

                "discount" =>  $getDiscount,

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

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

                "paidamount" =>  $roundPaidamount,

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

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

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

                "vip" => $this->request->getVar('vpseat')??"",

                "refund" => 0,

                "bookby_user_id" =>  $loginUserId,

                "bookby_user_type" => $bookUserType,

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

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

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

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

                "vehicle_id" => $vehicles_id,

                "cancel_status" => 0,



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

                // "offerer" => 0,

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

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



            );



            $roundvalidTicketbooking = array(

                "booking_id" => $roundrand,

                "trip_id" => $maitripid,

                "subtrip_id" => $subtripid,

                "passanger_id" => $userid,



                "pick_location_id" => $piclocation,

                "drop_location_id" => $droplocation,

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

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



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

                "paidamount" =>  $roundPaidamount,

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

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

                "bookby_user_id" => 1,

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

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

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

                "vehicle_id" => $vehicles_id,



            );



            if ($this->validation->run($roundvalidTicketbooking, 'ticket')) {

                $partialPaid = array(

                    "booking_id" => $roundrand,

                    "trip_id" => $maitripid,

                    "subtrip_id" => $subtripid,

                    "passanger_id" => $userid,

                    "paidamount" => $transectionDoubletrip,

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

                );



                $paidpartial = array(

                    "booking_id" => $roundrand,

                    "trip_id" => $maitripid,

                    "subtrip_id" => $subtripid,

                    "passanger_id" => $userid,

                    "paidamount" => $transectionDoubletrip,

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

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

                );





                $roundticketbooking['payment_status'] = $roundTripPaymentStatus;

                $this->ticketModel->insert($roundticketbooking);





                if ($this->validation->run($partialPaid, 'partialpay')) {



                    $this->partialpaidModel->insert($paidpartial);



                    $pick_stand_id = $this->request->getVar('pickstand');

                    $drop_stand_id = $this->request->getVar('dropstand');



                    $journeylist = $this->journeylist($roundrand, $userid, $maitripid, $subtripid, $piclocation, $droplocation, $pick_stand_id, $drop_stand_id);



                    $userRole = $this->session->get('role_id');







                    if (($userRole == 2) && ($roundTripPaymentStatus != "unpaid")) {

                        $totalprice =  $transectionDoubletrip;

                        $type = "income";

                        $message = "For Ticket Booking";



                        $agentIncome = agentIncomeCommission($backUserId, $totalprice, $roundrand, $subtripid, $userid, $message,$companyId);



                        $agentTotalIncome =   agentTotal($backUserId, $totalprice, $roundrand, $type, $payment_detail_rocord);
                        
                        $agetnDetail =  $this->agentModel->where('user_id', $this->session->get('user_id'))->first();

                        $agentIncome = agentExpenseTicketCharge($agetnDetail->id, $totalprice, $roundrand, $subtripid, $userid, $message, $companyId);
                        

                    }

                }

            }



            if ($roundTripPaymentStatus != "unpaid") {

                $paymethod_id = $this->request->getVar('pay_method');

                $payDetail = $this->request->getVar('paydetail');

                $type = "income";

                $detail = "Ticket Booking (" . $roundrand . ") ";

                accoutTranjection($type, $detail, $transectionDoubletrip, $backUserId, $roundrand, "booking");

                paymethodTeanjection($rand, $paymethod_id, $transectionDoubletrip, $payDetail, $maitripid, $subtripid, $backUserId);

            }



            $couponcode = $this->request->getVar('offerer');

            if (!empty($couponcode)) {

                $validDetail = $this->couponModel->where('code', $couponcode)->findAll();





                $coupondetail = array(

                    "code" => $couponcode,

                    "coupon_id" => $validDetail[0]->id,

                    "booking_id" => $rand,

                    "subtrip_id" => $subtripid,

                    "amount" => $validDetail[0]->discount,



                );



                $coupondetailround = array(

                    "code" => $couponcode,

                    "coupon_id" => $validDetail[0]->id,

                    "booking_id" => $roundPaidamount,

                    "subtrip_id" => $subtripid,

                    "amount" => $validDetail[0]->discount,



                );



                $this->coupondiscountModel->insert($coupondetail);

                $this->coupondiscountModel->insert($coupondetailround);

            }





            $emaildata = $ticketmailLibrary->getticketEmailData($rand);

            $roundemaildata = $ticketmailLibrary->getticketEmailData($roundrand);

            $this->db->transComplete();

            $status = sendTicket($login_email, $emaildata);

            $rouondstatus = sendTicket($login_email, $roundemaildata);

            $status = true;

            $rouondstatus = true;



            if (($status == true) && ($rouondstatus == true)) {

                $this->session->remove('subtripId');

                $this->session->remove('seatnumbers');

                $this->session->remove('totalseat');

                $this->session->remove('journeydate');

                $this->session->remove('aseat');

                $this->session->remove('spseat');

                $this->session->remove('vpseat');

                $this->session->remove('cseat');

                $this->session->remove('totalprice');

                $this->session->remove('tax');

                $this->session->remove('grandtotal');

                $this->session->remove('pickstand');

                $this->session->remove('dropstand');

                $this->session->remove('isrountrip');

                $this->session->remove('discountPercent');

                $this->session->remove('roundtrip_discount');

                return redirect()->route('allbookinglist-ticket')->with("success", "Ticket Booking");

            }

        }



        return redirect()->route('new-ticket')->with("fail", $this->validation->getError());

    }

    

    public function pretrip()

    {

        $data['fleet_type'] = $this->fleetTypeModel->findAll();

        $data['vehicle'] = $this->vehicleModel->findAll();

        

        $company_id = session()->get('company_id') ?? 0;

        if(($this->request->getVar('company_id') || $this->request->getVar('company_id') == 0) && session()->get('role_id') == "1"){

            $data['companies'] = $this->CompanyModel->findAll();

        }else{

            $company_ids = explode(',', $company_id);

            $data['companies'] = $this->CompanyModel->whereIn('id', $company_ids)->findAll();

        }

            

        $data['trip'] = $this->tripModel->select('trips.id as tripid, trips.*, schedules.*, vehicles.*, pic_location.name as pic_location_name, drop_location.name as drop_location_name')

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

                ->join('vehicles', 'vehicles.id = trips.vehicle_id','left')

                ->join('locations as pic_location', 'pic_location.id = trips.pick_location_id', 'left')

                ->join('locations as drop_location', 'drop_location.id = trips.drop_location_id', 'left')

                ->findAll();

            

        $data['driver'] = $this->employeeModel->where('employeetype_id', 1)->findAll();

        $data['assistant'] = $this->employeeModel->where('employeetype_id', 2)->findAll();

        

        // print_r($data['trip'][0]);die;

        // reg_no

        

        return view($this->Viewpath . '\ticket\pretrip', $data);

    }

    

    public function pre_trip_booking()

    {

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

        $data1['trip_id'] = $this->request->getVar('tripid');

        $data1['Driver_id'] = $this->request->getVar('Driver_id');

        $data1['Assistant_id'] = $this->request->getVar('Assistant_id');

        $data1['bus_id'] = $this->request->getVar('bus_id');

        $data1['Number_of_Seats'] = $this->request->getVar('Number_of_Seats');

        $data1['gas_later'] = $this->request->getVar('Gas_later');

        $data1['bus_meter'] = $this->request->getVar('Bus_meter');

        $data1['notes'] = $this->request->getVar('notes');

        $data1['created_by'] = $loginUserId;

        $data1['create_at'] = $this->request->getVar('pretripDate');

        $data1['pretrip_id'] = 1;



        $tripId = $this->request->getVar('tripid');

        $trip = $this->tripModel->find($tripId);

        

        if ($trip) {

            $companyTripIds = $this->tripModel

                ->select('id')

                ->where('company_id', $trip->company_id)

                ->findColumn('id');



            $maxPretripId = $this->pretripModel

                ->selectMax('pretrip_id')

                ->whereIn('trip_id', $companyTripIds)

                ->first();

            $data1['pretrip_id'] = ($maxPretripId->pretrip_id ?? 0) + 1;

        }

        $today = date('Y-m-d');

        $existing = $this->pretripModel

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

            ->where("DATE(create_at)", $this->request->getVar('pretripDate'))

            ->first();



        if ($existing) {

            return redirect()->route('pre_trip_list')->with("fail", "pretrip is already created.");

        }

        

        $this->pretripModel->insert($data1);



        $data2['trip_id']       = $this->request->getVar('tripid');

        $data2['employee_id']   = $this->request->getVar('Driver_id');

        $data2['employee_type']   = 1;//static for driver

        $data2['created_at']   = $this->request->getVar('pretripDate');

        $this->stuffassignModel->insert($data2);



        $data3['trip_id']       = $this->request->getVar('tripid');

        $data3['employee_id']   = $this->request->getVar('Assistant_id');

        $data3['employee_type']   = 2;//static for Assistant

        $data3['created_at']   = $this->request->getVar('pretripDate');

        $this->stuffassignModel->insert($data3);

        

        // $data['fleet_type'] = $this->fleetTypeModel->findAll();

        // $data['vehicle'] = $this->vehicleModel->findAll();

            

            

        // $data['trip'] = $this->tripModel->select('trips.id as tripid, trips.*, schedules.*, vehicles.*, pic_location.name as pic_location_name, drop_location.name as drop_location_name')

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

        //         ->join('vehicles', 'vehicles.id = trips.vehicle_id')

        //         ->join('locations as pic_location', 'pic_location.id = trips.pick_location_id', 'left')

        //         ->join('locations as drop_location', 'drop_location.id = trips.drop_location_id', 'left')

        //         ->findAll();

            

        // $data['driver'] = $this->employeeModel->where('employeetype_id', 1)->findAll();

        // $data['assistant'] = $this->employeeModel->where('employeetype_id', 2)->findAll();

        

        // print_r($data['trip'][0]);die;

        // reg_no

        

        return redirect()->route('pre_trip_list')->with("success", "pretrip created");

        

        // return view($this->Viewpath . '\ticket\pretrip', $data);

    }

    

    public function pre_trip_list()

    {

        $roleId     = session()->get("role_id");

        $companyId  = session()->get("company_id");

        $user_id    = session()->get("user_id");

        if($roleId == 1){

            $data['pretrip'] = $this->pretripModel->select('pretrip.id as pretripId, pretrip.*, trips.*, CONCAT(driver.first_name," ",driver.last_name) as driverName, CONCAT(assistance.first_name," ",assistance.last_name) as assistanceName, vehicles.*, schedules.*, pic_location.name as pic_location_name, drop_location.name as drop_location_name, companies.name as company, pretrip.create_at as pretrip_create,  CONCAT(COALESCE(booker.first_name, booker_agents.first_name, booker_agents_emp.first_name), " ", COALESCE(booker.last_name, booker_agents.last_name, booker_agents_emp.last_name)) AS createdBy, schedules.start_time as schedule_time, pretrip.updated_at as updatedAt')

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

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

                ->join('employees AS driver', 'pretrip.Driver_id = driver.id')

                ->join('employees AS assistance', 'pretrip.Assistant_id = assistance.id',"left")

                ->join('vehicles', 'pretrip.bus_id = vehicles.id')

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

                ->join('locations as pic_location', 'pic_location.id = trips.pick_location_id', 'left')

                ->join('locations as drop_location', 'drop_location.id = trips.drop_location_id', 'left')

                ->join('user_details as booker', 'pretrip.created_by = booker.user_id', "left")

                ->join('agents as booker_agents', 'pretrip.created_by = booker_agents.user_id', "left")

                ->join("users","users.id = pretrip.created_by","left")

                ->join("employees AS booker_agents_emp","booker_agents_emp.email = users.login_email","left")

                // ->where('DATE(pretrip.create_at)',date('Y-m-d'))

                ->where('pretrip.deleted_at IS NULL')

                ->findAll();

        }else if($roleId == 7){

            $data['pretrip'] = $this->pretripModel->select('pretrip.id as pretripId, pretrip.*, trips.*, driver.first_name as driverName, assistance.first_name as assistanceName, vehicles.*, schedules.*, pic_location.name as pic_location_name, drop_location.name as drop_location_name,companies.name as company, pretrip.create_at as pretrip_create,  CONCAT(COALESCE(booker.first_name, booker_agents.first_name, booker_agents_emp.first_name), " ", COALESCE(booker.last_name, booker_agents.last_name, booker_agents_emp.last_name)) AS createdBy, schedules.start_time as schedule_time, pretrip.updated_at as updatedAt')

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

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

                ->join('employees AS driver', 'pretrip.Driver_id = driver.id')

                ->join('employees AS assistance', 'pretrip.Assistant_id = assistance.id',"left")

                ->join('vehicles', 'pretrip.bus_id = vehicles.id')

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

                ->join('locations as pic_location', 'pic_location.id = trips.pick_location_id', 'left')

                ->join('locations as drop_location', 'drop_location.id = trips.drop_location_id', 'left')

                ->join('user_details as booker', 'pretrip.created_by = booker.user_id', "left")

                ->join('agents as booker_agents', 'pretrip.created_by = booker_agents.user_id', "left")

                ->join("users","users.id = pretrip.created_by","left")

                ->join("employees AS booker_agents_emp","booker_agents_emp.email = users.login_email","left")

                // ->where('DATE(pretrip.create_at)',date('Y-m-d'))

                ->where('pretrip.deleted_at IS NULL')

                ->where('trips.company_id',$companyId)

                ->findAll();

        }else{

            $data['pretrip'] = $this->pretripModel->select('pretrip.id as pretripId, pretrip.*, trips.*, driver.first_name as driverName, assistance.first_name as assistanceName, vehicles.*, schedules.*, pic_location.name as pic_location_name, drop_location.name as drop_location_name, companies.name as company, pretrip.create_at as pretrip_create,  CONCAT(COALESCE(booker.first_name, booker_agents.first_name, booker_agents_emp.first_name), " ", COALESCE(booker.last_name, booker_agents.last_name, booker_agents_emp.last_name)) AS createdBy, schedules.start_time as schedule_time, pretrip.updated_at as updatedAt')

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

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

                ->join('employees AS driver', 'pretrip.Driver_id = driver.id')

                ->join('employees AS assistance', 'pretrip.Assistant_id = assistance.id',"left")

                ->join('vehicles', 'pretrip.bus_id = vehicles.id')

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

                ->join('locations as pic_location', 'pic_location.id = trips.pick_location_id', 'left')

                ->join('locations as drop_location', 'drop_location.id = trips.drop_location_id', 'left')

                ->join('user_details as booker', 'pretrip.created_by = booker.user_id', "left")

                ->join('agents as booker_agents', 'pretrip.created_by = booker_agents.user_id', "left")

                ->join("users","users.id = pretrip.created_by","left")

                ->join("employees AS booker_agents_emp","booker_agents_emp.email = users.login_email","left")

                // ->where('DATE(pretrip.create_at)',date('Y-m-d'))

                ->where('pretrip.deleted_at IS NULL')

                ->where('trips.company_id',$companyId)

                ->where('pretrip.created_by',$user_id)

                ->findAll();

        }

        



                

        // print_r($data['pretrip'][0]);die;

        

        

        return view($this->Viewpath . '\ticket\pretriplist', $data);    

    }

    

    public function edit_pretrip($id)

    {

        

        $data['fleet_type'] = $this->fleetTypeModel->findAll();

        $data['vehicle'] = $this->vehicleModel->findAll();

            

            

        $data['trip'] = $this->tripModel->select('trips.id as tripid, trips.*, schedules.*, vehicles.*, pic_location.name as pic_location_name, drop_location.name as drop_location_name')

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

                ->join('vehicles', 'vehicles.id = trips.vehicle_id')

                ->join('locations as pic_location', 'pic_location.id = trips.pick_location_id', 'left')

                ->join('locations as drop_location', 'drop_location.id = trips.drop_location_id', 'left')

                ->findAll();

            

        $data['driver'] = $this->employeeModel->where('employeetype_id', 1)->findAll();

        $data['assistant'] = $this->employeeModel->where('employeetype_id', 2)->findAll();

        

        

        $data['pretrip'] = $this->pretripModel->select('pretrip.id as pretripId, pretrip.*, trips.*, driver.first_name as driverName, assistance.first_name as assistanceName, vehicles.*, schedules.*, pic_location.name as pic_location_name, drop_location.name as drop_location_name')

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

                ->join('employees AS driver', 'pretrip.Driver_id = driver.id')

                ->join('employees AS assistance', 'pretrip.Assistant_id = assistance.id')

                ->join('vehicles', 'pretrip.bus_id = vehicles.id')

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

                ->join('locations as pic_location', 'pic_location.id = trips.pick_location_id', 'left')

                ->join('locations as drop_location', 'drop_location.id = trips.drop_location_id', 'left')

                ->where('pretrip.deleted_at IS NULL')

                ->where('pretrip.id', $id) // Example WHERE condition

                ->find();

        if (empty($data['pretrip'])) {
            return redirect()->route('pre_trip_list')->with('fail', 'Pre-trip not found or already deleted.');
        }

                

            // print_r($data['pretrip']);die;

            

        return view($this->Viewpath . '\ticket\pretrip_edit', $data);

    }

    

    public function edit_pre_trip_booking()

    {

        $id = $this->request->getVar('pretripId');

        

        $data['trip_id'] = $this->request->getVar('tripid');

        $data['Driver_id'] = $this->request->getVar('Driver_id');

        $data['Assistant_id'] = $this->request->getVar('Assistant_id');

        $data['bus_id'] = $this->request->getVar('bus_id');

        $data['Number_of_Seats'] = $this->request->getVar('Number_of_Seats');

        

        $this->pretripModel->update($id, $data);

        

        return redirect()->route('pre_trip_list')->with("success", "pretrip updated");

    }

    

    public function delete_pretrip($id)

    {

        if ($this->pretripModel->delete($id)) {

            return redirect()->route('pre_trip_list')->with("success", "pretrip deleted");

        } else {

            return redirect()->route('pre_trip_list')->with("fail", "not delete");

        }

    }

    public function getDynamicPickupDropCombinations($pickup, $drop, $tripSeries, $date, $tripId)

    {

        // Convert trip series to an array of stops

        $stops = explode(',', $tripSeries);

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

        

        // Start building the query

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

        $builder->select("tickets.*, subtrips.*");

        $builder->join('subtrips', 'tickets.subtrip_id = subtrips.id', 'LEFT');

        $builder->join('trips', 'tickets.trip_id = trips.id', 'LEFT');

        $builder->where('journeydata', $date);

        $builder->where('cancel_status', 0);

        $builder->where('trips.status', 1);

        $builder->where('refund', 0);

        $builder->where('refund', 0);

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

        

        // Build the dynamic WHERE conditions

        $whereClause = '';

        foreach ($stops as $stop) {

            if (!empty($whereClause)) {

                $whereClause .= ' OR ';

            }

            $whereClause .= "FIND_IN_SET('$stop', TRIM(BOTH ',' FROM REPLACE(REPLACE(subtrips.stoppage, subtrips.pick_location_id, ''), subtrips.drop_location_id, '')))";

        }



        foreach ($stops as $start) {

            foreach ($stops as $end) {

                // if (array_search($start, $stops) < array_search($end, $stops)) {

                    $whereClause .= " OR (subtrips.pick_location_id = '$start' AND subtrips.drop_location_id = '$end') OR (subtrips.pick_location_id = '$end' AND subtrips.drop_location_id = '$start')";

                // }

            }

        }



        $builder->where("($whereClause)");



        // $sql = $builder->getCompiledSelect();

        // echo "<pre>";

        // print_r($sql); // Die and Debug: This will print the raw SQL query and stop execution

        // dd($sql);

        // Execute the query

        $query = $builder->get();    

        return $query->getResultArray();

    }



    public function getDynamicPickupDropCombinationsTemp($pickup, $drop, $tripSeries, $date, $subtripId)

    {

        // Convert trip series to an array of stops

        $stops = explode(',', $tripSeries);

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

        

        // Start building the query

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

        $builder->select("temporarybooks.*, subtrips.*");

        $builder->join('subtrips', 'temporarybooks.subtrip_id = subtrips.id', 'LEFT');

        $builder->join('trips', 'subtrips.trip_id = trips.id', 'LEFT');

        $builder->where('journey_date', $date);

        $builder->where('expires_at >', date('Y-m-d H:i:s'));

        $builder->where('trips.status', 1);

        $builder->where('temporarybooks.subtrip_id', $subtripId);

        

        // Build the dynamic WHERE conditions

        $whereClause = '';

        foreach ($stops as $stop) {

            if (!empty($whereClause)) {

                $whereClause .= ' OR ';

            }

            $whereClause .= "FIND_IN_SET('$stop', TRIM(BOTH ',' FROM REPLACE(REPLACE(subtrips.stoppage, subtrips.pick_location_id, ''), subtrips.drop_location_id, '')))";

        }



        foreach ($stops as $start) {

            foreach ($stops as $end) {

                // if (array_search($start, $stops) < array_search($end, $stops)) {

                    $whereClause .= " OR (subtrips.pick_location_id = '$start' AND subtrips.drop_location_id = '$end') OR (subtrips.pick_location_id = '$end' AND subtrips.drop_location_id = '$start')";

                // }

            }

        }



        $builder->where("($whereClause)");



        // $sql = $builder->getCompiledSelect();

        // echo "<pre>";

        // print_r($sql); // Die and Debug: This will print the raw SQL query and stop execution

        // dd($sql);

        // Execute the query

        $query = $builder->get();    

        return $query->getResultArray();

    }



    public function isDateInRange($dateToCheck, $startDate, $endDate) {

        // Convert dates to DateTime objects

        $date       = new \DateTime($dateToCheck);

        $start      = new \DateTime($startDate);

        $end        = new \DateTime($endDate);



        // Check if the date is in the range

        return ($date >= $start && $date <= $end);

    }



    public function print_pretrip($id)

    {

        $data['pretrip'] = $this->pretripModel->select('pretrip.id as pretripId, pretrip.*, trips.*, CONCAT(driver.first_name," ",driver.last_name) as driverName, driver.phone as driverphone, CONCAT(assistance.first_name," ",assistance.last_name) as assistanceName, assistance.phone as assistancephone, vehicles.*, schedules.*, pic_location.name as pic_location_name, drop_location.name as drop_location_name, pretrip.gas_later as gas_later, pretrip.bus_meter as bus_meter, pretrip.notes as notes, CONCAT(COALESCE(booker.first_name, booker_agents.first_name, booker_agents_emp.first_name), " ", COALESCE(booker.last_name, booker_agents.last_name, booker_agents_emp.last_name)) AS createdBy, companies.name as company_name, pretrip.create_at as pretrip_created_at, pretrip.updated_at as pretrip_updated_at, booker_agents.id as booker_id, booker_agents.id as booker_agent_id, booker_agents_emp.id as booker_agents_emp_id,users.role_id as booker_agents_emp_role, roles.name AS role_name

            ')

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

                ->join('employees AS driver', 'pretrip.Driver_id = driver.id')

                ->join('employees AS assistance', 'pretrip.Assistant_id = assistance.id',"left")

                ->join('vehicles', 'pretrip.bus_id = vehicles.id')

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

                ->join('user_details as booker', 'pretrip.created_by = booker.user_id', "left")

                ->join('agents as booker_agents', 'pretrip.created_by = booker_agents.user_id', "left")

                ->join('locations as pic_location', 'pic_location.id = trips.pick_location_id', 'left')

                ->join('locations as drop_location', 'drop_location.id = trips.drop_location_id', 'left')

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

                ->join("users","users.id = pretrip.created_by","left")

                ->join('roles', 'users.role_id = roles.id',"left")

                ->join("employees AS booker_agents_emp","booker_agents_emp.email = users.login_email","left")

                // ->where('DATE(pretrip.create_at)',date('Y-m-d'))

                ->where('pretrip.deleted_at IS NULL')

                ->where('pretrip.id',$id)

                ->findAll();

        if (empty($data['pretrip'])) {
            return redirect()->route('pre_trip_list')->with('fail', 'Pre-trip not found or already deleted.');
        }

        $dropLocationIdsCsv = $data['pretrip'][0]->stoppage?? '';

        if ($dropLocationIdsCsv) {

            $dropIdsArray = explode(',', $dropLocationIdsCsv);

            $stoppageNames = $this->db->table('locations')

                ->select('GROUP_CONCAT(name ORDER BY FIELD(id, ' . $dropLocationIdsCsv . ') SEPARATOR ", ") AS stoppage')

                ->whereIn('id', $dropIdsArray)

                ->get()

                ->getRow();

            $data['pretrip'][0]->dropLocations = $stoppageNames->stoppage ?? '';

        } else {

            // $data['pretrip'][0]?->dropLocations = '';

            if (isset($data['pretrip'][0])) {

                $data['pretrip'][0]->dropLocations = '';

            }

            

        }



        // $boarding = $this->picdropModel->select('pickdrops.id as pickdropid,pickdrops.*,stands.*')

        //     ->join('stands', 'stands.id = pickdrops.stand_id')

        //     ->where('trip_id', $data['pretrip'][0]->trip_id)

        //     ->where('pickdrops.type', 1)

        //     ->first();

        // $dropping = $this->picdropModel->select('pickdrops.id as pickdropid,pickdrops.*,stands.*')

        //     ->join('stands', 'stands.id = pickdrops.stand_id')

        //     ->where('trip_id', $data['pretrip'][0]->trip_id)

        //     ->where('pickdrops.type', 0)

        //     ->first();

        // $data['pretrip'][0]->boarding = $boarding->name ??"";

        // $data['pretrip'][0]->dropping = $dropping->name ??"";



        // Earliest pickup (boarding)

        $boardingList = $this->picdropModel->select('pickdrops.id as pickdropid, pickdrops.*, stands.*, stands.name as stand_name')

            ->join('stands', 'stands.id = pickdrops.stand_id')

            ->where('trip_id', $data['pretrip'][0]->trip_id)

            ->where('pickdrops.type', 1)

            ->findAll();



        $boarding = null;

        foreach ($boardingList as $item) {

            if (is_null($boarding) || strtotime($item->time) < strtotime($boarding->time)) {

                $boarding = $item;

            }

        }



        // Latest drop (dropping)

        $droppingList = $this->picdropModel->select('pickdrops.id as pickdropid, pickdrops.*, stands.*, stands.name as stand_name')

            ->join('stands', 'stands.id = pickdrops.stand_id')

            ->where('trip_id', $data['pretrip'][0]->trip_id)

            ->where('pickdrops.type', 0)

            ->findAll();



        $dropping = null;

        foreach ($droppingList as $item) {

            if (is_null($dropping) || strtotime($item->time) > strtotime($dropping->time)) {

                $dropping = $item;

            }

        }



        $data['pretrip'][0]->boarding = $boarding->name ?? "";

        $data['pretrip'][0]->dropping = $dropping->name ?? "";











        // $data['module'] =    lang("Localize.ticket_booking");

        // $data['title']  =    lang("Localize.journey_list");

        return view($this->Viewpath . '\ticket\pretripprint', $data);

    }

    public function getTripsByCompany($companyId)

    {

        $trips = $this->tripModel->select('trips.id as tripid, trips.*, schedules.*, vehicles.*, pic_location.name as pic_location_name, drop_location.name as drop_location_name')

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

                ->join('vehicles', 'vehicles.id = trips.vehicle_id','left')

                ->join('locations as pic_location', 'pic_location.id = trips.pick_location_id', 'left')

                ->join('locations as drop_location', 'drop_location.id = trips.drop_location_id', 'left')

                ->where('trips.company_id', $companyId)

                ->findAll();

        echo json_encode($trips);

        exit;

    }

    public function getTripsVehicle($tripID, $companyId){

        $tripDetails = $this->tripModel

                            ->select('trips.fleet_id as fleetID')

                            ->where('trips.id', $tripID)

                            ->first();



    if ($tripDetails) {

        $fleetID = $tripDetails->fleetID;

        $VehicleDetails = $this->vehicleModel

            ->select('vehicles.*')

            ->where('fleet_id', $fleetID)

            ->where('company_id', $companyId)

            ->findAll();

        } else {

            $VehicleDetails = [];

        }

        echo json_encode($VehicleDetails);

        exit;

    }



    public function getVehicleDetails($vehicleId){

        $VehicleDetails = $this->vehicleModel

            ->select('vehicles.*, fleets.*')

            ->join('fleets', 'fleets.id = vehicles.fleet_id')

            ->where('vehicles.id', $vehicleId)

            ->first();

        echo json_encode($VehicleDetails);

        exit;

    }



    public function getDriverDetails($companyId){

        $Driver = $this->employeeModel->where('employeetype_id', 1)->where('company_id', $companyId)->findAll();

        echo json_encode($Driver);

        exit;

    }



    public function getAssistantDetails($companyId){

        $assistant = $this->employeeModel->where('employeetype_id', 2)->where('company_id', $companyId)->findAll();

        echo json_encode($assistant);

        exit;

    }

    // public function deleteHoldSeat(int $seatNumber,int $subtripId)

    // {

    //     $subtrip_id = $subtripId;



    //     if($this->temporaryBookModel->where('seat_names', $seatNumber)->where('subtrip_id',$subtrip_id)->delete()){

    //         return $this->response->setJSON([

    //             'status' => 'success',

    //             'response' => 200,

    //             'message' => true

    //         ]);    

    //     }else{

    //         return $this->response->setJSON([

    //             'status' => 'failed',

    //             'response' => 204,

    //             'message' => "Seat not unHolded"

    //         ]);            

    //     }

        

    // }

    public function deleteHoldSeat(string $seatNumber, int $subtripId)
    {
        BookingInventorySupport::syncBookingTimezone();
        (new TemporaryBookHoldService())->cleanupExpiredHolds();

        $seat_names = TemporaryBookHoldService::normalizeSeatNamesForMatch($seatNumber);
        $journey_date = trim((string) ($this->request->getVar('journeydate') ?? $this->request->getVar('journey_date') ?? ''));
        $ticket_token = trim((string) ($this->request->getVar('ticket_token') ?? ''));
        $pickstand = (int) ($this->request->getVar('pickstand') ?? 0);
        $temporary_book_id = (int) ($this->request->getVar('temporary_book_id') ?? $this->request->getVar('id') ?? 0);

        $deleted = (new TemporaryBookHoldService())->releaseHold(
            $temporary_book_id > 0 ? $temporary_book_id : null,
            $subtripId > 0 ? $subtripId : null,
            $ticket_token !== '' ? $ticket_token : null,
            $seat_names !== '' ? $seat_names : null,
            $journey_date !== '' ? $journey_date : null,
            $pickstand
        );

        if ($deleted > 0) {
            return $this->response->setJSON([
                'status' => 'success',
                'response' => 200,
                'message' => true,
            ]);
        }

        return $this->response->setJSON([
            'status' => 'failed',
            'response' => 204,
            'message' => 'Seat not unHolded',
        ]);
    }

    function isAlreadybooked($tripid, $subtripid, $userid, $piclocation, $droplocation, $totalseat, $seatNumbers, $journeydate)

    {

        return $this->ticketModel

            ->where('cancel_status', 0)
            
            ->where('refund', 0)

            ->where('trip_id', $tripid)

            ->where('subtrip_id', $subtripid)

            ->where('passanger_id', $userid)

            ->where('pick_location_id', $piclocation)

            ->where('drop_location_id', $droplocation)

            ->where('totalseat', $totalseat)

            ->where('seatnumber', $seatNumbers)

            ->where('journeydata',$journeydate)

            ->first();

    }


    public function serverList()
    {
        $request = service('request');

        // Role and company ID from session
        $userRole = session()->get('role_id');
        $userId = session()->get('user_id');
        $company_id = session()->get('company_id');

        // Check permissions
        $rolepermissionLibrary = new Rolepermission();
        $refund_create = $rolepermissionLibrary->create("refund_list");
        $refund_online_ticket = ((int) $userRole === 1) || $rolepermissionLibrary->create("refund_online_ticket");
        $cancel_create_office = ((int) $userRole === 1) || $rolepermissionLibrary->create("cancel_list");
        $cancel_create_online = ((int) $userRole === 1) || $rolepermissionLibrary->create("cancel_online_ticket");

        // DataTables request values
        $draw   = $request->getPost('draw');
        $start  = $request->getPost('start');
        $length = $request->getPost('length');
        $searchValue = $request->getPost('search')['value'] ?? '';

        // Column map
        $columns = [
            0 => 'tickets.id',
            1 => 'tickets.booking_id',
            2 => 'companies.name',
            3 => 'pick_location.name',
            4 => 'drop_location.name',
            5 => 'tickets.seatnumber',
            6 => null, // pick_stand (computed)
            7 => null, // drop_stand (computed)
            8 => 'user_details.first_name', // passenger_name (computed, use first_name for ordering)
            9 => 'tickets.payment_status',
            10 => 'tickets.journeydata',
            11 => 'tickets.trip_id',
            12 => null, // booked_by (computed)
            13 => null // action column
        ];

        // Order column & direction
        $order = $request->getPost('order');
        $orderColumnIndex = !empty($order) && isset($order[0]['column']) ? $order[0]['column'] : 0;
        $orderDirection   = !empty($order) && isset($order[0]['dir']) ? $order[0]['dir'] : 'desc';

        // ---- TOTAL RECORDS ----
        $countBuilder = $this->db->table('tickets');
        $countBuilder->select('tickets.id')
            ->distinct()
            ->join("user_details","user_details.user_id = tickets.passanger_id")
            ->join("trips","trips.id = tickets.trip_id","left")
            ->join("companies","trips.company_id = companies.id","left")
            ->where('tickets.cancel_status', 0)
            ->where('tickets.refund', 0)
            ->where('tickets.deleted_at IS NULL');

        // Apply role-based filtering for total count
        if (!in_array($userRole,[1,2,7])) {
            if (!$rolepermissionLibrary->create('all_tickets')) {
                $countBuilder->where('tickets.bookby_user_id', $userId);
            } else {
                $countBuilder->where('trips.company_id', $company_id);
            }
        } else {
            if(in_array($userRole,[7])){
                $countBuilder->where('trips.company_id', $company_id);
            }
            if(in_array($userRole,[2])){
                $countBuilder->whereIn('trips.company_id', explode(",", $company_id))->where('tickets.bookby_user_id', $userId);
            }
        }

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

        // ---- FILTERED QUERY ----
        $builder = $this->db->table('tickets');
        $builder->select('tickets.id as ticket_id, tickets.booking_id, tickets.passanger_id, tickets.bookby_user_id, tickets.payment_status, tickets.journeydata, tickets.trip_id, tickets.seatnumber, tickets.pick_location_id, tickets.drop_location_id, tickets.pick_stand_id, tickets.drop_stand_id, tickets.bookby_user_type, CONCAT(user_details.first_name," ",user_details.last_name) as passengerName, CONCAT(COALESCE(booker.first_name, booker_agents.first_name,booker_agents_emp.first_name), " ", COALESCE(booker.last_name, booker_agents.last_name, booker_agents_emp.last_name)) AS booked_by, companies.name as company_name, pick_location.name as pick_location_name, drop_location.name as drop_location_name')
            ->distinct()
            ->join("user_details","user_details.user_id = tickets.passanger_id")
            ->join("user_details AS booker","booker.user_id = tickets.bookby_user_id","left")
            ->join("agents AS booker_agents","booker_agents.user_id = tickets.bookby_user_id","left")
            ->join("users","users.id = tickets.bookby_user_id","left")
            ->join("employees AS booker_agents_emp","booker_agents_emp.email = users.login_email","left")
            ->join("trips","trips.id = tickets.trip_id","left")
            ->join("companies","trips.company_id = companies.id","left")
            ->join("locations as pick_location", "pick_location.id = tickets.pick_location_id", "left")
            ->join("locations as drop_location", "drop_location.id = tickets.drop_location_id", "left")
            ->where('tickets.cancel_status', 0)
            ->where('tickets.refund', 0)
            ->where('tickets.deleted_at IS NULL');

        // Apply role-based filtering
        if (!in_array($userRole,[1,2,7])) {
            if (!$rolepermissionLibrary->create('all_tickets')) {
                $builder->where('tickets.bookby_user_id', $userId);
            } else {
                $builder->where('trips.company_id', $company_id);
            }
        } else {
            if(in_array($userRole,[7])){
                $builder->where('trips.company_id', $company_id);
            }
            if(in_array($userRole,[2])){
                $builder->whereIn('trips.company_id', explode(",", $company_id))->where('tickets.bookby_user_id', $userId);
            }
        }

        // Apply search filter
        if (!empty($searchValue)) {
            $builder->groupStart()
                ->like('tickets.booking_id', $searchValue)
                ->orLike('companies.name', $searchValue)
                ->orLike('pick_location.name', $searchValue)
                ->orLike('drop_location.name', $searchValue)
                ->orLike('user_details.first_name', $searchValue)
                ->orLike('user_details.last_name', $searchValue)
                ->orLike('tickets.payment_status', $searchValue)
                ->orLike('tickets.seatnumber', $searchValue)
                ->orLike('tickets.trip_id', $searchValue)
                ->groupEnd();
        }

        // Create a separate builder for filtered count
        $filteredCountBuilder = $this->db->table('tickets');
        $filteredCountBuilder->select('tickets.id')
            ->distinct()
            ->join("user_details","user_details.user_id = tickets.passanger_id")
            ->join("trips","trips.id = tickets.trip_id","left")
            ->join("companies","trips.company_id = companies.id","left")
            ->join("locations as pick_location", "pick_location.id = tickets.pick_location_id", "left")
            ->join("locations as drop_location", "drop_location.id = tickets.drop_location_id", "left")
            ->where('tickets.cancel_status', 0)
            ->where('tickets.refund', 0)
            ->where('tickets.deleted_at IS NULL');

        // Apply role-based filtering for filtered count
        if (!in_array($userRole,[1,2,7])) {
            if (!$rolepermissionLibrary->create('all_tickets')) {
                $filteredCountBuilder->where('tickets.bookby_user_id', $userId);
            } else {
                $filteredCountBuilder->where('trips.company_id', $company_id);
            }
        } else {
            if(in_array($userRole,[7])){
                $filteredCountBuilder->where('trips.company_id', $company_id);
            }
            if(in_array($userRole,[2])){
                $filteredCountBuilder->whereIn('trips.company_id', explode(",", $company_id))->where('tickets.bookby_user_id', $userId);
            }
        }

        // Apply search filter for filtered count
        if (!empty($searchValue)) {
            $filteredCountBuilder->groupStart()
                ->like('tickets.booking_id', $searchValue)
                ->orLike('companies.name', $searchValue)
                ->orLike('pick_location.name', $searchValue)
                ->orLike('drop_location.name', $searchValue)
                ->orLike('user_details.first_name', $searchValue)
                ->orLike('user_details.last_name', $searchValue)
                ->orLike('tickets.payment_status', $searchValue)
                ->orLike('tickets.seatnumber', $searchValue)
                ->orLike('tickets.trip_id', $searchValue)
                ->groupEnd();
        }

        // ---- TOTAL FILTERED ----
        $totalRecordwithFilter = $filteredCountBuilder->countAllResults(false);

        // ---- ORDERING ----
        if (isset($columns[$orderColumnIndex]) && $columns[$orderColumnIndex] !== null) {
            $builder->orderBy($columns[$orderColumnIndex], $orderDirection);
        } else {
            $builder->orderBy('tickets.id', 'desc');
        }

        // ---- PAGINATION ----
        if ($length > 0) {
            $builder->limit($length, $start);
        }

        // ---- FETCH RECORDS ----
        $records = $builder->get()->getResult();

        // Load locations and stands for display
        $locations = $this->locationModel->withDeleted()->findAll();
        $pickdrops = $this->picdropModel
            ->select('stands.id as standId,stands.*,pickdrops.*, stands.name as stand_name')
            ->join('stands', 'stands.id = pickdrops.stand_id')
            ->withDeleted()
            ->findAll();

        // Create lookup arrays
        $locationMap = [];
        foreach ($locations as $loc) {
            $locationMap[$loc->id] = $loc->name;
        }

        $standMap = [];
        foreach ($pickdrops as $pd) {
            $standMap[$pd->id] = [
                'name' => $pd->stand_name,
                'time' => $pd->time ?? ''
            ];
        }

        // ---- FORMAT JSON ----
        $data = [];
        $i = $start + 1;

        foreach ($records as $row) {
            // Get pick and drop location names
            $pickLocName = $locationMap[$row->pick_location_id] ?? '';
            $dropLocName = $locationMap[$row->drop_location_id] ?? '';

            // Get pick and drop stand names
            $pickStandHtml = '';
            if (isset($row->pick_stand_id) && isset($standMap[$row->pick_stand_id])) {
                $pickStand = $standMap[$row->pick_stand_id];
                $pickStandHtml = esc($pickStand['name']) . '<br/><small> ( ' . esc($pickStand['time']) . ' )</small>';
            }

            $dropStandHtml = '';
            if (isset($row->drop_stand_id) && isset($standMap[$row->drop_stand_id])) {
                $dropStand = $standMap[$row->drop_stand_id];
                $dropStandHtml = esc($dropStand['name']) . '<br/><small> ( ' . esc($dropStand['time']) . ' )</small>';
            }

            // Format payment status
            $paymentStatusHtml = '';
            if ($row->payment_status == "unpaid") {
                $paymentStatusHtml = lang("Localize.unpaid");
            } elseif ($row->payment_status == "paid") {
                $paymentStatusHtml = lang("Localize.paid");
            } else {
                $paymentStatusHtml = lang("Localize.partial");
            }

            // Format booked by
            $bookedByHtml = '';
            if (isset($row->bookby_user_type)) {
                if ($row->bookby_user_type == "passanger") {
                    $bookedByHtml = "online";
                } else {
                    $bookedByHtml = $row->bookby_user_type . "(" . ($row->booked_by ?? '') . ")";
                }
            }

            // Format journey date
            $journeyDate = '';
            if (!empty($row->journeydata)) {
                $journeyDate = date("Y-m-d", strtotime($row->journeydata));
            }

            $rowData = [
                "index" => $i++,
                "booking_id" => esc($row->booking_id),
                "company_name" => esc($row->company_name ?? ''),
                "pick_location" => esc($pickLocName),
                "drop_location" => esc($dropLocName),
                "seatnumber" => esc($row->seatnumber ?? ''),
                "pick_stand" => $pickStandHtml,
                "drop_stand" => $dropStandHtml,
                "passengerName" => esc($row->passengerName ?? ''),
                "payment_status" => $paymentStatusHtml,
                "journeydata" => $journeyDate,
                "trip_id" => esc($row->trip_id ?? ''),
                "booked_by" => esc($bookedByHtml),
                "action" => $this->generateActionButtons($row, $cancel_create_office, $cancel_create_online, $refund_create, $refund_online_ticket)
            ];

            $data[] = $rowData;
        }

        return $this->response->setJSON([
            "draw" => intval($draw),
            "recordsTotal" => $totalRecords,
            "recordsFiltered" => $totalRecordwithFilter,
            "data" => $data
        ]);
    }

    private function ticketRowIsBookedOnline(object $row): bool
    {
        return isset($row->bookby_user_type) && (string) $row->bookby_user_type === 'passanger';
    }

    private function generateActionButtons($row, $cancel_create_office, $cancel_create_online, $refund_create, $refund_online_ticket)
    {
        $security = \Config\Services::security();
        $csrfToken = $security->getTokenName();
        $csrfHash = $security->getHash();

        $userRole = (int) session()->get('role_id');
        $isOnlineBooking = $this->ticketRowIsBookedOnline($row);

        $actionHtml = '';

        $showCancel = $isOnlineBooking ? $cancel_create_online : $cancel_create_office;
        if ($showCancel) {
            $actionHtml .= '<a href="' . base_url(route_to('new-cancel', $row->ticket_id, "ticket")) . '" class="btn btn-sm btn-info text-white"><i class="far fa-times-circle"></i> ' . lang("Localize.cancel") . '</a> ';
        }

        if (($row->payment_status == "unpaid") || ($row->payment_status == "partial")) {
            $actionHtml .= '<a href="' . base_url(route_to('new-partialpaid', $row->ticket_id)) . '" class="btn btn-sm btn-primary text-white"><i class="far fa-money-bill-alt"></i> ' . lang("Localize.make") . ' ' . lang("Localize.payment") . ' </a> ';
        }

        if ($row->payment_status == "paid") {
            $actionHtml .= '<a href="' . base_url(route_to('detail-partialpaid', $row->booking_id)) . '" class="btn btn-sm btn-primary "><i class="fas fa-th-list"></i> ' . lang("Localize.payment") . ' ' . lang("Localize.details") . ' </a> ';
        }

        $actionHtml .= '<a href="' . base_url(route_to('show-ticketinvoice', $row->booking_id)) . '" class="btn btn-sm btn-success text-white"><i class="fas fa-file-invoice-dollar"></i> ' . lang("Localize.invoice") . ' </a> ';

        $actionHtml .= '<a target="_blank" href="' . base_url(route_to('print-ticketinvoice', $row->booking_id)) . '" class="btn btn-dark btn-sm"><i class="fas fa-print"></i></a> ';

        if ($row->payment_status != 'unpaid') {
            if ($isOnlineBooking) {
                if ($userRole === 1 || $refund_online_ticket) {
                    $refundUrl = base_url(route_to('new-online-manual-refund', $row->ticket_id));
                    $actionHtml .= '<a href="' . $refundUrl . '" class="btn btn-sm btn-warning text-white"><i class="fas fa-money-bill-wave"></i> ' . lang('Localize.refund') . ' </a>';
                }
            } elseif ($refund_create) {
                $refundUrl = base_url(route_to('new-refund', $row->ticket_id, 'ticket'));
                $actionHtml .= '<a href="' . $refundUrl . '" class="btn btn-sm btn-warning text-white"><i class="fas fa-money-bill-wave"></i> ' . lang('Localize.refund') . ' </a>';
            }
        }

        return $actionHtml;
    }
    
        public function serverListPretrip()
    {
        $request = service('request');

        // Role and company ID from session
        $roleId = session()->get('role_id');
        $companyId = session()->get('company_id');
        $userId = session()->get('user_id');

        // DataTables request values
        $draw   = $request->getPost('draw');
        $start  = $request->getPost('start');
        $length = $request->getPost('length');
        $searchValue = $request->getPost('search')['value'] ?? '';

        // Column map
        $columns = [
            0 => null, // index
            1 => 'companies.name', // company
            2 => 'pretrip.pretrip_id', // pre-trip no
            3 => 'vehicles.reg_no', // bus plate no
            4 => 'vehicles.bus_plate_no', // bus no
            5 => 'pretrip.bus_meter', // bus start meter
            6 => 'pretrip.trip_id', // trip
            7 => 'pic_location.name', // pick up
            8 => 'drop_location.name', // drop
            9 => 'pretrip.create_at', // trip date
            10 => 'schedules.start_time', // time
            11 => null, // driver (computed)
            12 => null, // assistance (computed)
            13 => 'vehicles.reg_no', // bus plate number
            14 => null, // created by (computed)
            15 => 'pretrip.Number_of_Seats', // seat
            16 => 'pretrip.notes', // note
            17 => 'pretrip.updated_at', // created date
            18 => null // action column
        ];

        // Order column & direction
        $order = $request->getPost('order');
        $orderColumnIndex = !empty($order) && isset($order[0]['column']) ? $order[0]['column'] : 17;
        $orderDirection   = !empty($order) && isset($order[0]['dir']) ? $order[0]['dir'] : 'desc';

        // ---- TOTAL RECORDS ----
        $countBuilder = $this->db->table('pretrip');
        $countBuilder->select('pretrip.id')
            ->join('trips', 'pretrip.trip_id = trips.id')
            ->join('companies', 'companies.id = trips.company_id', 'left');

        // Apply role-based filtering for total count
        if ($roleId == 1) {
            // Super admin sees all
        } elseif ($roleId == 7) {
            $countBuilder->where('trips.company_id', $companyId);
        } else {
            $countBuilder->where('trips.company_id', $companyId)
                ->where('pretrip.created_by', $userId);
        }
        $countBuilder->where('pretrip.deleted_at IS NULL');

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

        // ---- FILTERED QUERY ----
        $builder = $this->db->table('pretrip');
        $builder->select('
                pretrip.id as pretripId,
                pretrip.pretrip_id,
                pretrip.bus_id,
                pretrip.trip_id,
                pretrip.Driver_id,
                pretrip.Assistant_id,
                pretrip.bus_meter,
                pretrip.Number_of_Seats,
                pretrip.notes,
                pretrip.create_at as pretrip_create,
                pretrip.updated_at as updatedAt,
                pretrip.created_by,
                trips.company_id,
                CONCAT(driver.first_name, " ", COALESCE(driver.last_name, "")) as driverName,
                CONCAT(COALESCE(assistance.first_name, ""), " ", COALESCE(assistance.last_name, "")) as assistanceName,
                vehicles.reg_no,
                vehicles.bus_plate_no,
                schedules.start_time as schedule_time,
                pic_location.name as pic_location_name,
                drop_location.name as drop_location_name,
                companies.name as company,
                CONCAT(COALESCE(booker.first_name, booker_agents.first_name, booker_agents_emp.first_name), " ", COALESCE(booker.last_name, booker_agents.last_name, booker_agents_emp.last_name)) AS createdBy
            ')
            ->join('trips', 'pretrip.trip_id = trips.id')
            ->join('companies', 'companies.id = trips.company_id', 'left')
            ->join('employees AS driver', 'pretrip.Driver_id = driver.id')
            ->join('employees AS assistance', 'pretrip.Assistant_id = assistance.id', 'left')
            ->join('vehicles', 'pretrip.bus_id = vehicles.id')
            ->join('schedules', 'trips.schedule_id = schedules.id')
            ->join('locations as pic_location', 'pic_location.id = trips.pick_location_id', 'left')
            ->join('locations as drop_location', 'drop_location.id = trips.drop_location_id', 'left')
            ->join('user_details as booker', 'pretrip.created_by = booker.user_id', 'left')
            ->join('agents as booker_agents', 'pretrip.created_by = booker_agents.user_id', 'left')
            ->join('users', 'users.id = pretrip.created_by', 'left')
            ->join('employees AS booker_agents_emp', 'booker_agents_emp.email = users.login_email', 'left');

        // Apply role-based filtering
        if ($roleId == 1) {
            // Super admin sees all
        } elseif ($roleId == 7) {
            $builder->where('trips.company_id', $companyId);
        } else {
            $builder->where('trips.company_id', $companyId)
                ->where('pretrip.created_by', $userId);
        }
        $builder->where('pretrip.deleted_at IS NULL');

        // Global search
        if (!empty($searchValue)) {
            $builder->groupStart()
                ->like('companies.name', $searchValue)
                ->orLike('pretrip.pretrip_id', $searchValue)
                ->orLike('vehicles.reg_no', $searchValue)
                ->orLike('vehicles.bus_plate_no', $searchValue)
                ->orLike('pretrip.bus_meter', $searchValue)
                ->orLike('pretrip.trip_id', $searchValue)
                ->orLike('pic_location.name', $searchValue)
                ->orLike('drop_location.name', $searchValue)
                ->orLike('schedules.start_time', $searchValue)
                ->orLike('driver.first_name', $searchValue)
                ->orLike('driver.last_name', $searchValue)
                ->orLike('assistance.first_name', $searchValue)
                ->orLike('assistance.last_name', $searchValue)
                ->orLike('pretrip.Number_of_Seats', $searchValue)
                ->orLike('pretrip.notes', $searchValue)
                ->orLike('booker.first_name', $searchValue)
                ->orLike('booker.last_name', $searchValue)
                ->groupEnd();
        }

        // Create a separate builder for filtered count
        $filteredCountBuilder = $this->db->table('pretrip');
        $filteredCountBuilder->select('pretrip.id')
            ->join('trips', 'pretrip.trip_id = trips.id')
            ->join('companies', 'companies.id = trips.company_id', 'left')
            ->join('employees AS driver', 'pretrip.Driver_id = driver.id')
            ->join('employees AS assistance', 'pretrip.Assistant_id = assistance.id', 'left')
            ->join('vehicles', 'pretrip.bus_id = vehicles.id')
            ->join('schedules', 'trips.schedule_id = schedules.id')
            ->join('locations as pic_location', 'pic_location.id = trips.pick_location_id', 'left')
            ->join('locations as drop_location', 'drop_location.id = trips.drop_location_id', 'left');

        // Apply role-based filtering for filtered count
        if ($roleId == 1) {
            // Super admin sees all
        } elseif ($roleId == 7) {
            $filteredCountBuilder->where('trips.company_id', $companyId);
        } else {
            $filteredCountBuilder->where('trips.company_id', $companyId)
                ->where('pretrip.created_by', $userId);
        }
        $filteredCountBuilder->where('pretrip.deleted_at IS NULL');

        // Apply search filter for filtered count
        if (!empty($searchValue)) {
            $filteredCountBuilder->groupStart()
                ->like('companies.name', $searchValue)
                ->orLike('pretrip.pretrip_id', $searchValue)
                ->orLike('vehicles.reg_no', $searchValue)
                ->orLike('vehicles.bus_plate_no', $searchValue)
                ->orLike('pretrip.bus_meter', $searchValue)
                ->orLike('pretrip.trip_id', $searchValue)
                ->orLike('pic_location.name', $searchValue)
                ->orLike('drop_location.name', $searchValue)
                ->orLike('schedules.start_time', $searchValue)
                ->orLike('driver.first_name', $searchValue)
                ->orLike('driver.last_name', $searchValue)
                ->orLike('assistance.first_name', $searchValue)
                ->orLike('assistance.last_name', $searchValue)
                ->orLike('pretrip.Number_of_Seats', $searchValue)
                ->orLike('pretrip.notes', $searchValue)
                ->groupEnd();
        }

        // ---- TOTAL FILTERED ----
        $totalRecordwithFilter = $filteredCountBuilder->countAllResults(false);

        // ---- ORDERING ----
        if (isset($columns[$orderColumnIndex]) && $columns[$orderColumnIndex] !== null) {
            $builder->orderBy($columns[$orderColumnIndex], $orderDirection);
        } else {
            $builder->orderBy('pretrip.updated_at', 'desc');
        }

        // ---- PAGINATION ----
        if ($length > 0) {
            $builder->limit($length, $start);
        }

        // ---- FETCH RECORDS ----
        $records = $builder->get()->getResult();

        // ---- FORMAT JSON ----
        $data = [];
        $i = $start + 1;

        foreach ($records as $row) {
            // Check if delete button should be shown (only if scheduled time is in future)
            $scheduledDateTimeStr = date('Y-m-d', strtotime($row->pretrip_create)) . ' ' . $row->schedule_time;
            $scheduledDateTime = strtotime($scheduledDateTimeStr);
            $currentDateTime = time();
            $canDelete = ($scheduledDateTime > $currentDateTime);

            $data[] = [
                "index" => $i++,
                "company" => esc($row->company ?? ''),
                "pretrip_id" => esc($row->pretrip_id ?? ''),
                "reg_no" => esc($row->reg_no ?? ''),
                "bus_plate_no" => "000" . esc($row->bus_plate_no ?? ''),
                "bus_meter" => esc($row->bus_meter ?? ''),
                "trip_id" => esc($row->trip_id ?? ''),
                "pic_location_name" => esc($row->pic_location_name ?? ''),
                "drop_location_name" => esc($row->drop_location_name ?? ''),
                "trip_date" => date("Y-m-d", strtotime($row->pretrip_create)),
                "schedule_time" => esc($row->schedule_time ?? ''),
                "driverName" => esc($row->driverName ?? ''),
                "assistanceName" => esc($row->assistanceName ?? ''),
                "bus_plate_number" => esc($row->reg_no ?? ''),
                "createdBy" => esc($row->createdBy ?? ''),
                "Number_of_Seats" => esc($row->Number_of_Seats ?? ''),
                "notes" => esc($row->notes ?? ''),
                "updatedAt" => date("Y-m-d H:i", strtotime($row->updatedAt)),
                "action" => $this->generatePretripActionButtons($row->pretripId, $canDelete)
            ];
        }

        return $this->response->setJSON([
            "draw" => intval($draw),
            "recordsTotal" => $totalRecords,
            "recordsFiltered" => $totalRecordwithFilter,
            "data" => $data
        ]);
    }

    private function generatePretripActionButtons($pretripId, $canDelete)
    {
        $actionHtml = '';
        
        // Print button (always shown)
        $actionHtml .= '<a target="_blank" href="' . base_url(route_to('print-pretrip', $pretripId)) . '" class="btn btn-sm btn-success text-white" title="' . lang("Localize.print") . '"><i class="fas fa-print"></i></a>';
        
        // Delete button (only if scheduled time is in future)
        if ($canDelete) {
            $actionHtml .= ' <a href="' . base_url(route_to('delete-pretrip', $pretripId)) . '" class="btn btn-sm btn-danger text-white" title="' . lang("Localize.delete") . '"><i class="fas fa-trash-alt"></i></a>';
        }
        
        return $actionHtml;
    }
    
    /**
     * Create 3 scheduled notifications for a ticket
     * @param string $bookingId Booking ID
     * @param int $passengerId Passenger user ID
     * @param int $tripId Trip ID
     * @param int $subtripId Subtrip ID
     * @param string $journeyDate Journey date
     */
    private function createTicketNotifications($bookingId, $passengerId, $tripId, $subtripId, $journeyDate)
    {
        try {
            $passengerDetail = $this->userDetailModel->where('user_id', $passengerId)->first();
            $passengerName = $passengerDetail
                ? trim(($passengerDetail->first_name ?? '') . ' ' . ($passengerDetail->last_name ?? ''))
                : 'Passenger';
            if ($passengerName === '') {
                $passengerName = 'Passenger';
            }

            $trip = $this->tripModel->find($tripId);
            if (! $trip) {
                return;
            }

            $subtrip = $this->subtripModel->find($subtripId);
            if (! $subtrip) {
                return;
            }

            $schedule = $this->scheduleeModel->find($trip->schedule_id);
            $scheduleStartTime = $schedule ? (string) ($schedule->start_time ?? '') : '';

            $ticket = $this->ticketModel->where('booking_id', $bookingId)->first();

            // Boarding point time + stand (pick_stand_id stores pickdrops.id)
            $boardingTime = $scheduleStartTime;
            $pickupStandName = 'Pickup location';
            $dropStandName = 'Drop location';

            $pickLocation = $this->locationModel->find($subtrip->pick_location_id ?? $trip->pick_location_id);
            if ($pickLocation) {
                $pickupStandName = (string) ($pickLocation->name ?? $pickupStandName);
            }
            $dropLocation = $this->locationModel->find($subtrip->drop_location_id ?? $trip->drop_location_id);
            if ($dropLocation) {
                $dropStandName = (string) ($dropLocation->name ?? $dropStandName);
            }

            if ($ticket && ! empty($ticket->pick_stand_id)) {
                $pickdrop = $this->picdropModel
                    ->select('pickdrops.time, stands.name as stand_name')
                    ->join('stands', 'stands.id = pickdrops.stand_id', 'left')
                    ->where('pickdrops.id', (int) $ticket->pick_stand_id)
                    ->withDeleted()
                    ->first();
                if ($pickdrop) {
                    if (! empty($pickdrop->time)) {
                        $boardingTime = (string) $pickdrop->time;
                    }
                    if (! empty($pickdrop->stand_name)) {
                        $pickupStandName = (string) $pickdrop->stand_name;
                    }
                }
            }

            if ($ticket && ! empty($ticket->drop_stand_id)) {
                $dropPickdrop = $this->picdropModel
                    ->select('stands.name as stand_name')
                    ->join('stands', 'stands.id = pickdrops.stand_id', 'left')
                    ->where('pickdrops.id', (int) $ticket->drop_stand_id)
                    ->withDeleted()
                    ->first();
                if ($dropPickdrop && ! empty($dropPickdrop->stand_name)) {
                    $dropStandName = (string) $dropPickdrop->stand_name;
                }
            }

            $driverName = 'Not assigned';
            $driverMobile = 'N/A';
            $driverAssignment = $this->stuffassignModel
                ->where('trip_id', $tripId)
                ->where('employee_type', '1')
                ->first();
            if ($driverAssignment) {
                $driver = $this->employeeModel->find($driverAssignment->employee_id);
                if ($driver) {
                    $driverName = trim(($driver->first_name ?? '') . ' ' . ($driver->last_name ?? ''));
                    if ($driverName === '') {
                        $driverName = (string) ($driver->name ?? 'Not assigned');
                    }
                    $driverMobile = trim((string) ($driver->phone ?? ''));
                    if ($driverMobile === '') {
                        $driverMobile = 'N/A';
                    }
                }
            }

            $busType = 'N/A';
            $vehicleId = $trip->vehicle_id ?? ($ticket->vehicle_id ?? null);
            $vehicle = $vehicleId ? $this->vehicleModel->find($vehicleId) : null;
            if ($vehicle) {
                if (! empty($vehicle->bus_type)) {
                    $fleetType = $this->fleetTypeModel->find($vehicle->bus_type);
                    if ($fleetType && ! empty($fleetType->type)) {
                        $busType = (string) $fleetType->type;
                    }
                }
                if ($busType === 'N/A' && ! empty($vehicle->reg_no)) {
                    $busType = (string) $vehicle->reg_no;
                }
            }

            $journeyDateOnly = date('Y-m-d', strtotime((string) $journeyDate));
            $journeyDateTime = $journeyDateOnly . ' ' . $boardingTime;
            $tripDateTime = strtotime($journeyDateTime);
            if ($tripDateTime === false) {
                return;
            }

            $notificationTime1 = date('Y-m-d H:i:s', $tripDateTime - (2 * 60 * 60));
            $notificationTime2 = date('Y-m-d H:i:s', $tripDateTime - (1 * 60 * 60));
            $notificationTime3 = date('Y-m-d H:i:s', $tripDateTime - (30 * 60));
            $currentTime = time();

            $templates = [
                [
                    'offset' => 2 * 60 * 60,
                    'when' => $notificationTime1,
                    'subject' => 'Your Trip is in 2 Hours! 🚌 | رحلتك بعد ساعتين! 🚌',
                    'message' => "Hi {$passengerName},\n"
                        . "Your ride is scheduled for {$boardingTime} today. Pickup at {$pickupStandName}\n"
                        . "Dropping at {$dropStandName}.\n"
                        . "Get ready and be at the pickup spot a few minutes early. We'll match you with your driver soon.\n"
                        . "Open the app for live updates!\n\n"
                        . "مرحباً {$passengerName}،\n"
                        . "رحلتك المحدده اليوم في {$boardingTime}.\n"
                        . "محطة الركوب {$pickupStandName}.\n"
                        . "محطه الوصول {$dropStandName}\n"
                        . "استعد وتواجد في محطة الركوب قبل الموعد ببضع دقائق. سنُعرّفك على سائقك قريباً.\n\n"
                        . "ابقي التطبيق مفتوح للاطلاع على آخر التحديثات!",
                ],
                [
                    'offset' => 1 * 60 * 60,
                    'when' => $notificationTime2,
                    'subject' => '1 Hour Until Your Ride! ⏰ | ⏰ !ساعة واحدة تفصلك عن رحلتك',
                    'message' => "Hello {$passengerName},\n"
                        . "Just a reminder: Your trip starts in 1 hour at {$boardingTime} from {$pickupStandName}.\n"
                        . "Your driver {$driverName}\n"
                        . "Mobile {$driverMobile}\n"
                        . "will be arriving in a {$busType}.\n\n"
                        . "مرحباً {$passengerName}،\n"
                        . "تذكير: تبدأ رحلتك بعد ساعة واحدة في تمام الساعة {$boardingTime} من {$pickupStandName}.\n"
                        . "سيصل سائقك {$driverName}\n"
                        . "رقم التواصل {$driverMobile}\n"
                        . "الباص {$busType}.",
                ],
                [
                    'offset' => 30 * 60,
                    'when' => $notificationTime3,
                    'subject' => 'Your Driver is on the Way – 30 Minutes to Go! 🚖 | سائقك في الطريق اليك - ٣٠ دقيقة متبقية! 🚌',
                    'message' => "Hey {$passengerName},\n"
                        . "Your ride is almost here! Pickup at {$boardingTime} ({$pickupStandName}).\n"
                        . "Driver: {$driverName}\n"
                        . "Mobile: {$driverMobile}\n"
                        . "| Vehicle: {$busType}\n"
                        . "Be ready outside – see you soon!\n\n"
                        . "مرحباً {$passengerName}،\n"
                        . "الباص على وشك الوصول! موعد الانطلاق {$boardingTime} ({$pickupStandName}).\n\n"
                        . "{$driverName} :السائق\n"
                        . "{$driverMobile} :رقم التواصل\n"
                        . "{$busType} :الباص\n"
                        . "كن مستعداً في الخارج - نراك قريباً!",
                ],
            ];

            foreach ($templates as $tpl) {
                if (($tripDateTime - (int) $tpl['offset']) <= $currentTime) {
                    continue;
                }

                $notificationId = $this->notificationModel->insert([
                    'subject' => $tpl['subject'],
                    'message' => $tpl['message'],
                    'notification_type' => 'scheduled',
                    'target_group' => 'specific_user',
                    'trip_id' => $tripId,
                    'journey_date' => $journeyDateOnly,
                    'notification_date' => $tpl['when'],
                    'repeat_option' => 'none',
                    'status' => 'scheduled',
                    'is_push_notification' => 1,
                    'created_by' => 0,
                ]);

                if ($notificationId) {
                    $this->userNotificationModel->insert([
                        'notification_id' => $notificationId,
                        'user_id' => $passengerId,
                        'is_read' => 0,
                    ]);
                }
            }
        } catch (\Exception $e) {
            log_message('error', 'Failed to create ticket notifications: ' . $e->getMessage());
        }
    }


}

