<?php



namespace Modules\Ticket\Controllers\Api;



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\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\Company\Models\CompanyModel;

use Modules\User\Models\UserDetailModel;

use Modules\User\Models\UserModel;

use Modules\Ticket\Models\TemporaryBook;

use Modules\HoldSeat\Models\HoldSeatModel;

use Modules\Paymethod\Models\GeideaWave as ModelsGeideaWave;

use Modules\Ticket\Models\TemporaryBook as TemporaryBookModel;



use App\Libraries\Ticketmail;

use Modules\Paymethod\Models\StripeModel;

use Modules\Website\Models\WebsettingModel;

use Modules\Page\Models\PrivacyModel;
use Modules\Page\Models\TermsModel;



class Ticket extends BaseController

{

    use ResponseTrait;



    protected $Viewpath;

    protected $ticketModel;

    protected $tripModel;

    protected $companyModel;

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

    protected $userModel;

    protected $userDetailModel;

    protected $journeylistModel;

    protected $partialpaidModel;

    protected $maxtimeModel;

    protected $webSettingModel;

    protected $geideaWaveModel;

    protected $TemporaryBook;

    protected $temporaryBookModel;

    protected $holdSeatModel;
    
    protected $termsModel;
    
    protected $secretKey = 'vikas';



    public function __construct()

    {

        $this->ticketModel = new TicketModel();

        $this->tripModel = new TripModel();

        $this->companyModel = new CompanyModel();

        $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->stripeModel = new StripeModel;



        $this->userModel = new UserModel();

        $this->userDetailModel = new UserDetailModel();



        $this->journeylistModel = new JourneylistModel();

        $this->partialpaidModel = new PartialpaidModel();



        $this->maxtimeModel = new MaxtimeModel();

        $this->webSettingModel = new WebsettingModel;

        $this->geideaWaveModel = new ModelsGeideaWave();

        $this->TemporaryBook = new TemporaryBook();

        $this->temporaryBookModel = new TemporaryBookModel;

        $this->holdSeatModel = new HoldSeatModel();
        
        $this->termsModel = new TermsModel();

    }







    public function bookticket()

    {

        $ticketmailLibrary = new Ticketmail();

        $ticketid = null;

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

        $rand = "TB" . $rand;



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





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

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

        $this->db->transStart();



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

        if (empty($userid)) {

            $data = [

                'message' => "User check fail",

                'status' => "fail",

                'response' => 404,

                'data' => "user check error",

            ];

            return $this->response->setJSON($data);

        }













        $ticketbooking = array(

            "booking_id" => $rand,

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

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

            "passanger_id" => $userid,

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

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

            "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'),

            "refund" => 0,

            "bookby_user_id" => $userid,

            "bookby_user_type" => "passanger",

            "journeydata" => $journeyDate,

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

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

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

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

            "cancel_status" => 0,



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



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

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



        );



        $validTicketbooking = array(



            "booking_id" => $rand,

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

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

            "passanger_id" => $userid,



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

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

            "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'),



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

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



        );





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





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

            }







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



            if (empty($ticketid)) {



                $data = [

                    'message' => "booking data error",

                    'status' => "success",

                    'response' => 204,

                    'data' => "booking data not appropriate",

                ];

                return $this->response->setJSON($data);

            }







            $partialPaid = array(

                "booking_id" => $rand,

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

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

                "passanger_id" => $userid,

                "paidamount" => $paidamount,



            );

            $paidpartial = array(

                "booking_id" => $rand,

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

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

                "passanger_id" => $userid,

                "paidamount" => $paidamount,

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

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

            );









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



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









                $maitripid = $this->request->getVar('trip_id');

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

                $piclocation = $this->request->getVar('pick_location_id');

                $droplocation = $this->request->getVar('drop_location_id');

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



                if (empty($journeylist)) {

                    $data = [

                        'status' => "fail",

                        'response' => 204,

                        'data' => "journey list data not inserted",

                    ];

                }



                $this->db->transComplete();



                $ticketInfo =  $this->ticketModel->find($ticketid);



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



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



                if ($status == true) {

                    $data = [

                        'status' => "success",

                        'response' => 200,

                        'data' => $ticketInfo,

                    ];

                } else {

                    $data = [

                        'status' => "success",

                        'response' => 200,

                        'data' => $ticketInfo,

                        'emailerror' => $status,

                    ];

                }

            } else {



                $errors = $this->validation;

                $data = [

                    'message' => "Booking & Paid Information Not Valid",

                    'status' => "failed",

                    'response' => 204,

                    'errors' => $errors->listErrors(),

                ];

            }

        } else {



            $errors = $this->validation;

            $data = [

                'message' => "Booking Information Not Valid",

                'status' => "failed",

                'response' => 204,

                'errors' => $errors,

            ];

        }





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



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



        return $this->response->setJSON($data);

    }



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

    {

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



        $newPassangerFName =  json_decode($newPassangerFName, true);

        $newPassangerLName =  json_decode($newPassangerLName, true);

        $newPassangerMobile =  json_decode($newPassangerMobile, true);

        $newPassangerNidNumber =  json_decode($newPassangerNidNumber, true);



        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],



                );

            }







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



            if (empty($alljourneydata)) {

                $data = [

                    'message' => "Multiple Pasanger input error",

                    'status' => "failed",

                    'response' => 204,

                    'data' => "journey list input error",

                ];

                return $this->response->setJSON($data);

            }

        }





        return   $joruneylistid;

    }





    public function userCheck($login_email, $login_mobile)

    {

        $userid = null;

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





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



                $validdata = array(

                    "user_id" => $userid,

                    "first_name" => $this->request->getVar('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'),

                );



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

                    $data = array(

                        "user_id" => $userid,

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

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

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

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

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

        }

    }



    public function busSeat($subTripId, $journeyDate)

    {

        $bookSeat = array();

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

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

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



        $getData = $this->ticketModel

            ->where('subtrip_id', $subTripId)

            ->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();

            }

        }



        $displaySeat = array();

        $sortingdisplaySeat = array();

        $anotherarray = array();

        $lastSeat = null;



        // sub trip and fllet details

        $subtripInfo = $this->subtripModel

            ->select('subtrips.*, trips.fleet_id')

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

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

            ->first();



        $totalseat = 0;

        $getFleetDetails = [];



        if(isset($subtripInfo->fleet_id) && !empty($subtripInfo->fleet_id)){



            $getFleetDetails = $this->fleetTypeModel->where('status', 1)->find($subtripInfo->fleet_id);

            // total seat

            $totalseat = (int) $getFleetDetails->total_seat + (int)$getFleetDetails->last_seat;



        }        

        



        // booked seats (exclude refunded so seats are bookable again)

        $this->ticketModel

            ->where('journeydata', $journeyDate)

            ->where('cancel_status', 0)

            ->where('refund', 0);



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

            $mainTripId = $subtripInfo->trip_id;

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

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



            $this->ticketModel

                ->groupStart()

                    ->whereIn('subtrip_id', [$subtripInfo->id, $mainTripMainSubtripId->id])



                    ->orGroupStart()

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

                        ->whereIn('pick_location_id', array_filter($subtripStoppagePointsArr, fn ($stp_id) => $stp_id != $subtripInfo->drop_location_id))

                    ->groupEnd()



                    ->orGroupStart()

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

                        ->whereIn('drop_location_id', array_filter($subtripStoppagePointsArr, fn ($stp_id) => $stp_id != $subtripInfo->pick_location_id))

                    ->groupEnd()

                ->groupEnd();

        } else {

            if(isset($subtripInfo->trip_id) && !empty($subtripInfo->trip_id)){

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

            }

            

        }



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

        $bookSeat = array_merge(...array_map(fn ($v) => explode(',', $v), $resBookSeats));



        // build layout

        $layout = [];

        $seatnumber = [];

        if(isset($getFleetDetails->layout) && !empty($getFleetDetails->layout)){

            $layout = explode("-", $getFleetDetails->layout);

            $seatnumber = explode(",", $getFleetDetails->seat_number);

        }

        

        $seatColumn = count($layout);

        $numberSeatRow = array_sum($layout);

        $storeSeatNumber = $seatnumber;





        if (isset($getFleetDetails->last_seat) && $getFleetDetails->last_seat) {

            $lastSeat = array_slice($seatnumber, -1, 1);

            array_pop($seatnumber);

        }

        $totalseatnumber = count($seatnumber);



        if($numberSeatRow > 0){

            $seatloopslicenumber =  floor($totalseatnumber / $numberSeatRow);

        }else{

            $seatloopslicenumber =  floor($totalseatnumber / 1);

        }

        



        for ($i = 1; $i <= $seatloopslicenumber; $i++) {

            $arrayslice = null;

            $arrayslice = array_splice($seatnumber, $numberSeatRow);

            $displaySeat[$i] = $seatnumber;

            $seatnumber  =  $arrayslice;

        }







        for ($totalseatrow = 1; $totalseatrow  <= $seatloopslicenumber; $totalseatrow++) {



            for ($column = 0; $column < $seatColumn; $column++) {

                $x = 0;

                foreach ($displaySeat[$totalseatrow] as $key => $seatvalue) {



                    if ($layout[$column] >= $key + 1) {

                        array_push($anotherarray, $seatvalue);

                    } else {

                        array_push($anotherarray, null);



                        break;

                    }

                    array_shift($displaySeat[$totalseatrow]);

                }

            }

            $sortingdisplaySeat[$totalseatrow] = $anotherarray;

            $anotherarray = array();

        }











        $kyepos = null;

        if (!empty($lastSeat)) {



            foreach ($sortingdisplaySeat[$seatloopslicenumber] as $key => $checknull) {

                if ($checknull == null) {

                    $sortingdisplaySeat[$seatloopslicenumber][$key] = $lastSeat[0];

                }

            }

        }







        $newseatarray = array();

        $arraynew = array();

        $id = 1;

        foreach ($sortingdisplaySeat as $key => $shortseat) {



            foreach ($shortseat as $skey => $newseat) {



                if ($newseat == null) {

                    array_push($newseatarray, null);

                } else {

                    if (in_array($newseat, $bookSeat)) {

                        $seatvalue = true;

                    } else {

                        $seatvalue = false;

                    }

                    $seatarray  = array(

                        "id" => $id,

                        "seatNumber" => $newseat,

                        "isReserved" => $seatvalue,

                    );

                    array_push($newseatarray, $seatarray);

                }





                $id = $id + 1;

            }



            $arraynew[] = $newseatarray;

            $newseatarray = array();

        }



        // print_r($arraynew);

        // exit;

        $data = [

            'status' => "success",

            'response' => 200,

            'layout' =>  $getFleetDetails->layout ?? [],

            'seatlayout' => $arraynew,

            'totalseat' => $totalseat,



        ];



        return $this->response->setJSON($data);

    }





    public function singelBooking($bookingid)

    {







        $ticket =  $this->ticketModel->where('booking_id', $bookingid)->first();
        
        $main_privacy_policy = $this->termsModel->first();



        if (empty($ticket)) {



            $data = [

                'message' => "No ticket Found",

                'status' => "fail",

                'response' => 201,

                'data' => $ticket,

            ];

        } else {

            $passengerdata = $this->userModel->find($ticket->passanger_id);

            $ticket->mobile = $passengerdata->login_mobile;

            $ticket->email = $passengerdata->login_email;

            $passengerdetail = $this->userDetailModel->where('user_id', $passengerdata->id)->first();

            $ticket->fullName = $passengerdetail->first_name . ' ' . $passengerdetail->last_name;



            $company = $this->vehicleModel->where('id', $ticket->vehicle_id)->first();

            $ticket->company = $company->company??"";



            $seatwithClass = [];

            $classData = [];

            $company_name = $this->tripModel->where('id', $ticket->trip_id)->first();

            $this->db->transStart();

            $allSeatClass = $this->db->table('seat_class')->get()->getResult();

            $this->db->transComplete();

            foreach ($allSeatClass as $class) {

                $classData[$class->id] = $class;

            }



            $subtripInformation = $this->subtripModel->find($ticket->subtrip_id);

            if(isset($subtripInformation->subtrip_seatclass) && !empty($subtripInformation->subtrip_seatclass)){

                $seatclass = $subtripInformation->subtrip_seatclass ?? [];

            }else{

                $seatclass = $company_name->seatclass ??[];

            }

            $seatclass = is_string($seatclass) ? json_decode($seatclass, true) : $seatclass;



            if (!empty($ticket->seatnumber)) {

                $seatNumbers = explode(',', $ticket->seatnumber); // example: "1,2,3"



                foreach ($seatNumbers as $seat) {

                    $seat = trim($seat);

                    $classFound = null;



                    // Find seat class for this seat

                    foreach ($seatclass as $sc) {

                        if (in_array($seat, $sc['seatNo'])) {

                            $classFound = $sc['seatClass'];

                            break;

                        }

                    }



                    $seatwithClass[] = [

                        "seatnumber" => $seat,

                        "seatclass"  => $classFound ? $classData[$classFound]->name :'Economy', // fallback if no match

                    ];

                }

            }





            $ticket->seatwithClass = $seatwithClass;
            $companyTerms = [];
            if(isset($company_name)){
                $companyName = $this->companyModel->where('id', $company_name->company_id)->first();
                $this->db->transStart();
                $companyTerms = $this->db->table('company_terms')
                    ->where('company_id', $company_name->company_id)
                    ->get()
                    ->getRow();
                
                $this->db->transComplete();
            }



            // $ticket->company_name = $company_name->company_name;
            
            


            $ticket->company_name = $companyName->name ?? "";

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

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

                                    ->where('pickdrops.id', $ticket->pick_stand_id)

                                    ->first();

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

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

                ->where('pickdrops.id', $ticket->drop_stand_id)

                ->first();
                
            $pickUpLocationName = $this->locationModel->withDeleted()->select('*')

                ->where('id', $ticket->pick_location_id)

                ->first();

            $pickDropLocationName = $this->locationModel->withDeleted()->select('*')

                ->where('id', $ticket->drop_location_id)

                ->first();

            $ticket->Pickupstand = $pickUpStandName->stand_name ??"";
            $ticket->PickDropstand = $pickDropStandName->stand_name ??"";
            $ticket->PickupLocation = $pickUpLocationName->name ??"";
            $ticket->PickupLocationTime = $pickUpStandName->time ?? "";
            $ticket->PickDropLocationTime = $pickDropStandName->time ?? "";
            $ticket->PickDropLocation = $pickDropLocationName->name ?? "";
            $ticket->main_privacy_policy = $main_privacy_policy ?? "";
            $ticket->privacy_policy = $companyTerms?$companyTerms->description: "";
            
                        $facility = "";
            if (!empty($company_name->facility)) {
                $facilityIds = array_filter(explode(',', $company_name->facility));
                if (!empty($facilityIds)) {
                    $this->db->transStart();
                    $facilitys = $this->db->table('facilitys')
                        ->whereIn('id', $facilityIds)
                        ->get()
                        ->getResult();
                    $this->db->transComplete();
                    
                    if (!empty($facilitys)) {
                        $facilityNames = array_column($facilitys, 'name');
                        $facility = implode(", ", $facilityNames);
                    }
                }
            }
            $ticket->Facility = $facility;
            


            $data = [

                'message' => "Ticket found",

                'status' => "success",

                'response' => 200,

                'data' => $ticket,

            ];

        }



        return $this->response->setJSON($data);

    }







    public function paylaterByUser()

    {





        $bookingid = $this->request->getVar('booking_id');



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



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



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



        $ticketDetail =  $this->ticketModel->where('booking_id', $bookingid)->first();





        $tickeid =     $ticketDetail->id;

        $backUserId = $ticketDetail->passanger_id;

        $payment_detail_rocord = $paydetail;

        $amountToPaid = $ticketDetail->paidamount;

        $subtripid = $ticketDetail->subtrip_id;

        $maitripid = $ticketDetail->trip_id;

        $rand = $bookingid;





        if ($paidamount == $amountToPaid) {



            $validPaid = array(

                "booking_id" => $bookingid,

                "trip_id" => $maitripid,

                "subtrip_id" => $subtripid,

                "passanger_id" => $backUserId,

                "paidamount" => $paidamount,

                "pay_method_id" => $pay_type_id,

            );

            $paidpartial = array(

                "booking_id" => $bookingid,

                "trip_id" => $maitripid,

                "subtrip_id" => $subtripid,

                "passanger_id" => $backUserId,

                "paidamount" => $paidamount,

                "pay_method_id" => $pay_type_id,

                "payment_detail" => $payment_detail_rocord,

            );



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



                $this->db->transStart();



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



                $data = [

                    'id' => $tickeid,

                    'payment_status' => "paid",

                    "pay_method_id" => $pay_type_id,

                ];



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





                $paymethod_id =  $pay_type_id;

                $payDetail = $payment_detail_rocord;

                $type = "income";

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

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

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



                $this->db->transComplete();



                $data = [

                    'message' => "Transaction success",

                    'status' => "success",

                    'response' => 200,



                ];

                return $this->response->setJSON($data);

            } else {



                $data = [

                    'message' => "Error in Validation",

                    'error' => $this->validation->getErrors(),

                    'status' => "fail",

                    'response' => 404,

                ];



                return $this->response->setJSON($data);

            }

        } else {



            $data = [

                'message' => "Error in amount",

                'status' => "fail",

                'response' => 404,

            ];



            return $this->response->setJSON($data);

        }

    }



    public function stripePayment()

    {

        $rules = [

            'stripetoken'  => 'required',

            'amount'       => 'required',

        ];



        if ($this->validate($rules)) {

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

            $paymentToken = $this->request->getVar('stripetoken');

            $getPayData = $this->stripeModel->first();



            if ($getPayData->environment == 1) {

                $secret_key = $getPayData->live_s_kye;

                $environment = "live";

            } else {

                $secret_key = $getPayData->test_s_kye;

                $environment = "Test";

            }



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

            $currencybuilder = $this->db->table('currencies');

            $curencyquery = $currencybuilder->where('id', $websetting->currency)->get();

            $currency = $curencyquery->getRow()->code;



            try {

                \Stripe\Stripe::setApiKey($secret_key);



                // stripe, old charge code

                /* $paymentIntent = \Stripe\Charge::create([

                    "amount"     => $amount * 100,

                    "currency"     => $currency,

                    "source"     => $paymentToken,

                    "description"   => "Seat Booking Payment"

                ]); */



                // upgrading to 3Ds

                $customer = \Stripe\Customer::create([

                    'name' => 'Jahid Limon',

                    'email' => 'jahid@bdtask.net'

                ]);



                $paymentIntent = \Stripe\PaymentIntent::create([

                    'amount' => $amount,

                    'currency' => $currency,

                    'payment_method_data' => [

                        'type' => 'card',

                        'card' => [

                            'token' => $paymentToken,

                        ],

                    ],

                    'confirmation_method' => 'manual',

                    'customer' => $customer->id

                ]);



                $paymentIntent->confirm();



                $data = [

                    'message'   => "Payment Successfull",

                    'status'    => "success",

                    'response'  => 200,

                    'data'      => $paymentIntent,

                ];

                return $this->response->setJSON($data);

            } catch (\Exception $e) {

                $data = [

                    'message' => "Payment Fail",

                    'status' => "fail",

                    'response' => 404,

                    'data' => $e->getMessage(),

                ];

                return $this->response->setJSON($data);

            }

        } else {

            $data = array(

                'success' => false,

                'response' => 204,

                'message' => 'All field required',

                'data' => $this->validator->getErrors(),

            );

            return $this->response->setJSON($data);

        }

    }



    public function laterBookticket()

    {

        $ticketmailLibrary = new Ticketmail();

        $ticketid = null;

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

        $rand = "TB" . $rand;



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





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

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

        $this->db->transStart();



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

        if (empty($userid)) {

            $data = [

                'message' => "User check fail",

                'status' => "fail",

                'response' => 404,

                'data' => "user check error",

            ];

            return $this->response->setJSON($data);

        }













        $ticketbooking = array(

            "booking_id" => $rand,

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

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

            "passanger_id" => $userid,

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

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

            "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'),

            "refund" => 0,

            "bookby_user_id" => $userid,

            "bookby_user_type" => "passanger",

            "journeydata" => $journeyDate,

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

            "pay_method_id" => 999,

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

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

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

            "cancel_status" => 0,



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

            "offerer" => 0,

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

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



        );



        $validTicketbooking = array(



            "booking_id" => $rand,

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

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

            "passanger_id" => $userid,



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

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

            "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'),



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

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



        );





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





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



            if ($paymentStatus == "unpaid") {

                $paidamount = 0;

            }









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



            if (empty($ticketid)) {



                $data = [

                    'message' => "booking data error",

                    'status' => "success",

                    'response' => 204,

                    'data' => "booking data not appropriate",

                ];

                return $this->response->setJSON($data);

            }







            $partialPaid = array(

                "booking_id" => $rand,

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

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

                "passanger_id" => $userid,

                "paidamount" => $paidamount,



            );

            $paidpartial = array(

                "booking_id" => $rand,

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

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

                "passanger_id" => $userid,

                "paidamount" => $paidamount,

                "pay_method_id" => 999,

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

            );









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



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









                $maitripid = $this->request->getVar('trip_id');

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

                $piclocation = $this->request->getVar('pick_location_id');

                $droplocation = $this->request->getVar('drop_location_id');

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



                if (empty($journeylist)) {

                    $data = [

                        'status' => "fail",

                        'response' => 204,

                        'data' => "journey list data not inserted",

                    ];

                }



                $this->db->transComplete();









                $ticketInfo =  $this->ticketModel->find($ticketid);









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



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



                if ($status == true) {

                    $data = [

                        'status' => "success",

                        'response' => 200,

                        'data' => $ticketInfo,

                    ];

                } else {

                    $data = [

                        'status' => "success",

                        'response' => 200,

                        'data' => $ticketInfo,

                        'emailerror' => $status,

                    ];

                }

            } else {



                $errors = $this->validation;

                $data = [

                    'message' => "Booking & Paid Information Not Valid",

                    'status' => "failed",

                    'response' => 204,

                    'errors' => $errors->listErrors(),

                ];

            }

        } else {



            $errors = $this->validation->getErrors();

            $data = [

                'message' => "Booking Information Not Valid",

                'status' => "failed",

                'response' => 204,

                'errors' => $errors,

            ];

        }



        return $this->response->setJSON($data);

    }



    public function busSeatNew($subTripId, $journeyDate)

    {

        $subTripId = $subTripId;

        $subtripInfo = $this->subtripModel

            ->select('subtrips.*, trips.fleet_id, trips.seatclass')

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

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

            ->first();

        if(!empty($subtripInfo)){

            $fleetId = $subtripInfo->fleet_id;

            $seatClass  = $subtripInfo->subtrip_seatclass;

            if(empty($seatClass)){

                $seatClass  = $subtripInfo->seatclass;

            }

            $seatData = [];

            if(empty($seatClass)){

                $seatData = json_decode($subtripInfo->subtrip_seatclass,true);

            } else {

                $seatData = json_decode($subtripInfo->seatclass,true);

            }



            $bookedSeats = [];

            $holdSeats = [];

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



            foreach ($TempBookedSeat as $row) {

                // print_r($row['seat_names']);

                $seats = explode(',', $row['seat_names']);

                foreach ($seats as $seat) {

                    $holdSeats[] = trim($seat);

                }

            }

            // print_r($holdSeats);

            // exit;

            // $holdSeats = $TempBookedSeat;





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



        // Release non paid expired seats

        $getData = $this->ticketModel

            ->where('trip_id', $subtripInformation->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();

            }

        }



        $this->ticketModel

                ->where('journeydata', $journeyDate)

                ->where('cancel_status', 0)

                ->where('refund', 0);

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

            $mainTripId = $subtripInformation->trip_id;

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

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

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

            

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

            

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

            $holdseat =[];

            $blockseat =[];



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

            // $builder->where('subtrip_id', $subtripInformation->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, $mainTripId);



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

            $egyptNow = new \DateTime("now", new \DateTimeZone("Africa/Cairo"));

            $currentTime = $egyptNow->format("Y-m-d H:i:s");



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

            $builder

            // ->where('subtrip_id', $subtripInformation->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);

            $query = $builder->get();

            $holdSeat = $query->getResultArray();



            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 {

            $holdseat =[];

            $blockseat = [];

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

            $egyptNow = new \DateTime("now", new \DateTimeZone("Africa/Cairo"));

            $currentTime = $egyptNow->format("Y-m-d H:i:s");

            

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

            $builder

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

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

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

                    ->where('status', 1)

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

            $query = $builder->get();

            $holdSeat = $query->getResultArray();

            $mainTripId = $subtripInformation->trip_id;

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



            $TempBookedSeat = $this->getDynamicPickupDropCombinationsTemp($subtripInformation->pick_location_id, $subtripInformation->drop_location_id, $subtripStopage->stoppage, $journeyDate, $subtripInformation->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', $subtripInformation->trip_id);

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

        }





            $bookedSeatslot = [];



            foreach ($bookedSeats as $row) {

                $seats = explode(',', $row);

                foreach ($seats as $seat) {

                    $bookedSeatslot[] = trim($seat);

                }

            }



            // print_r($bookedSeatslot);

            // exit;

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



            $this->db->transStart();

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

            $query = $builder->select('id, name')->get();



            $seatclassName = [];

            foreach ($query->getResult() as $row) {

                $seatclassName[$row->id] = $row->name;

            }



            $this->db->transComplete();



            // build seat group/row

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

            $seatRows = array_map(function ($singleRow) use ($seatLayoutArr, $tSeatRowWithB, $bookedSeatslot, $holdSeats, $blockseat, $seatData, $seatclassName) {

            // print_r($tSeatRowWithB);die;

                $newSingleRow = array();

                $currentTotalIndex = 0;

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

                    $seatRowIndex++;

                        $seatClass = 0;

                        if(isset($seatData) && !empty($seatData)){

                            foreach ($seatData as $group) {

                                if (in_array($singleSeat, $group['seatNo'])) {

                                    $seatClass = $group['seatClass'];

                                    break;

                                }

                            }    

                        }

                    $newSingleRow[] = array(

                        'seatName' => $singleSeat, 

                        'isBooked' => in_array($singleSeat, $bookedSeatslot) ? 1 : 0,

                        'isHold' => in_array($singleSeat, (array) $holdSeats) ? 1 : 0,

                        'isBlocked' => in_array($singleSeat, (array) $blockseat) ? 1 : 0,

                        'seatClass' => $seatClass,

                        'seatClassName' => $seatClass?$seatclassName[$seatClass]:"Economy"

                    );



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

                        $newSingleRow[] = '';

                        $currentTotalIndex += current($seatLayoutArr);

                        array_shift($seatLayoutArr);

                    }

                }



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

            }, $seatRowGroup);

            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]);

            }



            if ($lastSeat !== '') {

                // last seat exists

                // build last seat info

                $lastSeatInfo =  array(

                    'seatName' => $lastSeat,

                    'isBooked' => in_array($lastSeat, $bookedSeatslot) 

                );

                

                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;

                }

            }

            $getFleetDetails = $this->fleetTypeModel->where('status', 1)->find($subtripInfo->fleet_id);

            $totalseat = (int) $getFleetDetails->total_seat + (int)$getFleetDetails->last_seat;

            $data = [

                'status' => "success",

                'response' => 200,

                'layout' =>  $getFleetDetails->layout ?? [],

                'seatlayout' => $seatRows,

                'totalseat' => $fleetInfo->total_seat,

                'totalSeatInRow' => $totalSeatInRow,

                'fleetTotalSeat' => $fleetTotalSeat,

                'seatinfo' => $seatinfo,

            ];

        }else{

            $data = [

                'status' => "Data not found.",

                'response' => 400,

            ];

            

        }



        return $this->response->setJSON($data);

    }

    public function busSeatLayoutNew($subTripId, $journeyDate)

    {

        $subTripId = $subTripId;

        $subtripInfo = $this->subtripModel

            ->select('subtrips.*, trips.fleet_id')

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

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

            ->first();

        $fleetId = $subtripInfo->fleet_id;

        $bookedSeats = [];//needd to check

        $holdSeats = [];//needd to check

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

        $fleetTotalSeat = $fleetInfo->total_seat;

        $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) {

        // print_r($tSeatRowWithB);die;

            $newSingleRow = array();

            $currentTotalIndex = 0;



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

                $seatRowIndex++;

                $newSingleRow[] = array(

                    'seatName' => $singleSeat, 

                    'isBooked' => in_array($singleSeat, $bookedSeats) ?? 0,

                    'isHold' => in_array($singleSeat, (array) $holdSeats) ?? 0

                );



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

                    $newSingleRow[] = '';

                    $currentTotalIndex += current($seatLayoutArr);

                    array_shift($seatLayoutArr);

                }

            }



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

        }, $seatRowGroup);



        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);die;

        if ($lastSeat !== '') {

            // last seat exists

            // build last seat info

            $lastSeatInfo =  array(

                'seatName' => $lastSeat,

                'isBooked' => in_array($lastSeat, $bookedSeats) 

            );

            

            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'){

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

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

        }

    }

    public function processPayment()

    {

        // $this->writeLogsInFile("geidea",$this->request->getVar());

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

        $userId             = $this->request->getVar('user_id');

        $tripId             = $this->request->getVar('trip_id');

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

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

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

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

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

        $totalprice         = $this->request->getVar('amount');

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

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

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

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

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

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

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

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

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



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

        // $this->writeLogsInFile("geidea",var_dump($amount));

        // $this->writeLogsInFile("geidea",var_dump($amount));

        // $this->writeLogsInFile("geidea",$this->request->getVar());

        if (!$amount || !is_numeric($amount)) {

            $data = [

                'message' => 'Invalid or missing amount.',

                'status' => 'fail',

                'response' => 201,

                'data' => $amount,

            ];

            return $this->response->setJSON($data);

        }



        $geideaData = $this->geideaWaveModel->first();



        if (!$geideaData) {

            $data = [

                'message' => 'Geidea credentials not found.',

                'status' => 'fail',

                'response' => 201,

                'data' => null,

            ];

            return $this->response->setJSON($data);

        }



        if ($geideaData->environment == 0) {

            $publicKey = $geideaData->test_public_key;

            $apiPassword = $geideaData->test_api_pass;

        } else {

            $publicKey = $geideaData->live_public_key;

            $apiPassword = $geideaData->live_api_pass;

        }



        $url = 'https://api.merchant.geidea.net/payment-intent/api/v2/direct/session';

        $merchantReferenceId = "order" . time();

        $timestamp = gmdate("Y-m-d\TH:i:s\Z");

        $signature = $this->generateGeideaSignature($publicKey, $amount, 'EGP', $merchantReferenceId, $apiPassword, $timestamp);



        $payload = [

            'amount' => (float) $amount,

            'currency' => 'EGP',

            'merchantReferenceId' => $merchantReferenceId,

            'timestamp' => $timestamp,

            'signature' => $signature,

            'callbackUrl' => base_url('modules/api/v1/tickets/payment-sucess'),

        ];



        try {

            $client = \Config\Services::curlrequest();

            $response = $client->post($url, [

                'auth' => [$publicKey, $apiPassword],

                'json' => $payload,

            ]);



            $body = json_decode($response->getBody(), true);

            $sessionId = $body['session']['id'];

            $data = [

                        'user_id'           => $userId,

                        'trip_id'           => $tripId,

                        'subtrip_id'        => $subtripId,

                        'merchant_id'       => $merchantReferenceId,

                        'sessionId'         => $sessionId,

                        'amount'            => $amount,

                        "pick_location_id"  => $pick_location_id,

                        "drop_location_id"  => $drop_location_id,

                        "pickstand"         => $pickstand,

                        "dropstand"         => $dropstand,

                        "totalprice"        => $totalprice,

                        "discount"          => $discount,

                        "tax"               => $tax,

                        "grandtotal"        => $grandtotal,

                        "refund"            => 0,

                        "offerer"           => $offerer,

                        "seatnumbers"       => $seatnumbers,

                        "totalseat"         => $totalseat,

                        'journeydata'       => $journeyDate,

                    ];

            $this->db->transStart();

            $this->db->table('paystatusgeidea')->insert($data);

            $this->db->transComplete();

            



            if ($response->getStatusCode() === 200 && isset($body['session']['id'])) {

                $data = [

                    'message' => 'Session created successfully.',

                    'status' => 'success',

                    'response' => 200,

                    'data' => [

                        'sessionId' => $body['session']['id']

                        // 'csrfTokenName' => csrf_token(),

                        // 'csrfToken' => csrf_hash()

                    ]

                ];

            } else {

                $data = [

                    'message' => 'Session ID missing in response.',

                    'status' => 'fail',

                    'response' => 201,

                    'data' => $body

                ];

            }

        } catch (\Exception $e) {

            $data = [

                'message' => 'Payment session creation failed: ' . $e->getMessage(),

                'status' => 'fail',

                'response' => 500,

                'data' => null

            ];

        }



        return $this->response->setJSON($data);

    }

    public function paymentSucess(){

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

        $this->writeLogsInFile("geidea",$callbackData);

        $sessionId          = $callbackData->sessionId;

        $merchantId         = $callbackData->order->merchantReferenceId;

        $transactionStatus  = $callbackData->order->transactions[0]->status;

        $orderId            = $callbackData->order->orderId;

        $this->writeLogsInFile("geidea",$orderId);

        $this->writeLogsInFile("geidea",$merchantId);

        $updateData = [

                'status'    => $transactionStatus,

                'order_id'  =>  $orderId

            ];

        $this->db->transStart();

        $this->db->table('paystatusgeidea')

            ->where('sessionId', $sessionId)

            ->where('merchant_id', $merchantId)

            ->update($updateData);

        $this->db->transComplete();



        if($transactionStatus == "Success"){

            $this->writeLogsInFile('geideaBook', $sessionId);

            $this->writeLogsInFile('geideaBook', $merchantId);

            $this->bookticketGeidea($sessionId, $merchantId);

        }



    }

    private function generateGeideaSignature($merchantPublicKey, $orderAmount, $orderCurrency, $orderMerchantReferenceId, $apiPassword, $timestamp) {

        // Ensure the amount is properly formatted

        $amountStr = number_format($orderAmount, 2, '.', '');



        // Build the string to hash

        $data = "{$merchantPublicKey}{$amountStr}{$orderCurrency}{$orderMerchantReferenceId}{$timestamp}";



        // Generate the HMAC SHA256 hash

        $hash = hash_hmac('sha256', $data, $apiPassword, true);



        // Return the signature as a base64 encoded string

        return base64_encode($hash);

    }

    private function writeLogsInFile($logFileName, $msgArray)

    {

        $date = date("Y-m-d");

        $logDir = WRITEPATH . 'logs/geidea'; // Safe writable path

        if (!is_dir($logDir)) {

            mkdir($logDir, 0777, true); // create if not exists

        }



        $filePath = $logDir . '/' . $logFileName . '_' . $date . '.log';



        $logEntry = "[" . date('Y-m-d H:i:s') . "] " . print_r($msgArray, true) . "\n";



        file_put_contents($filePath, $logEntry, FILE_APPEND);

    }

    public function bookticketGeidea($sessionId, $merchantId){

        // $sessionId = $this->request->getVar('sessionId');

        // $merchantId = $this->request->getVar('merchantId');

        $this->writeLogsInFile('geideaBook', $sessionId);

        $this->writeLogsInFile('geideaBook', $merchantId);

        $this->db->transStart();

        $results = $this->db->table('paystatusgeidea')

            ->select('users.*, paystatusgeidea.*, paystatusgeidea.id as paystatusgeidea_id')

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

            ->where('sessionId', $sessionId)

            ->where('merchant_id', $merchantId)

            ->get()

            ->getResult();

        $this->writeLogsInFile('geideaBook', $results);

        $this->db->transComplete();

        foreach ($results as $result) {

            $userId         = $result->user_id;

            $tripId         = $result->trip_id;

            $subtripId      = $result->subtrip_id;

            $journeyDate    = $result->journeydata;

            $pickupLocation = $result->pick_location_id;

            $dropLocation = $result->drop_location_id;

            $pickstand = $result->pickstand;

            $dropstand = $result->dropstand;

            $totalprice = $result->amount;

            $discount = $result->discount;
            
            $roundtripdiscount = $result->roundtrip_discount;

            $tax = $result->tax;

            $grandtotal = $result->amount;

            $offerer = $result->offerer;

            $seatnumbers = $result->seatnumbers;

            $totalseat = $result->totalseat;
            
            if($roundtripdiscount > 0){
                $grandtotal = $grandtotal - ($grandtotal*$roundtripdiscount)/100;
                
            }


            $ticketmailLibrary = new Ticketmail();

            $ticketid = null;

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

            $rand = "TB" . $rand;





            $login_email = $result->login_email;

            $login_mobile = $result->login_mobile;

            $this->db->transStart();



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

            if (empty($userid)) {

                $data = [

                    'message' => "User check fail",

                    'status' => "fail",

                    'response' => 404,

                    'data' => "user check error",

                ];

                return $this->response->setJSON($data);

            }



            $ticketbooking = array(

                "booking_id" => $rand,

                "trip_id" => $tripId,

                "subtrip_id" => $subtripId,

                "passanger_id" => $userid,

                "pick_location_id" => $pickupLocation,

                "drop_location_id" => $dropLocation,

                "pick_stand_id" => $pickstand,

                "drop_stand_id" => $dropstand,

                "price" => $totalprice,

                "discount" => $discount,

                "totaltax" => $tax,

                "paidamount" => $grandtotal,

                "refund" => 0,

                "bookby_user_id" => $userid,

                "bookby_user_type" => "passanger",

                "journeydata" => $journeyDate,

                "pay_method_id" => 6,

                "payment_status" => "paid",

                "payment_detail" => "",

                "vehicle_id" => 0,

                "cancel_status" => 0,



                "offerer" => $offerer,



                "seatnumber" => $seatnumbers,

                "totalseat" => $totalseat,



            );



            $validTicketbooking = array(



                "booking_id" => $rand,

                "trip_id" => $tripId,

                "subtrip_id" => $subtripId,

                "passanger_id" => $userid,



                "pick_location_id" => $pickupLocation,

                "drop_location_id" => $dropLocation,

                "pick_stand_id" => $pickstand,

                "drop_stand_id" => $dropstand,



                "price" => $totalprice,

                "paidamount" => $grandtotal,

                "seatnumber" => $seatnumbers,

                "totalseat" => $totalseat,

                "bookby_user_id" => 1,

                "journeydata" => $journeyDate,



                "payment_status" => "paid",

                "vehicle_id" => 0,



            );





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





                $paymentStatus = "paid";

                $paidamount = $grandtotal;



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



                if (empty($ticketid)) {



                    $data = [

                        'message' => "booking data error",

                        'status' => "success",

                        'response' => 204,

                        'data' => "booking data not appropriate",

                    ];

                    return $this->response->setJSON($data);

                }

                

                $partialPaid = array(

                    "booking_id" => $rand,

                    "trip_id" => $tripId,

                    "subtrip_id" => $subtripId,

                    "passanger_id" => $userid,

                    "paidamount" => $paidamount,



                );

                $paidpartial = array(

                    "booking_id" => $rand,

                    "trip_id" => $tripId,

                    "subtrip_id" => $subtripId,

                    "passanger_id" => $userid,

                    "paidamount" => $paidamount,

                    "pay_method_id" => 6,

                    "payment_detail" => "paid",

                );

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



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



                    $maitripid = $tripId;

                    $subtripid = $subtripId;

                    $piclocation = $pickupLocation;

                    $droplocation = $dropLocation;

                    $pick_stand_id = $pickstand;

                    $drop_stand_id = $dropstand;

                    if (strpos($seatnumbers, ',') !== false) {
                        // Has comma → convert to array
                        $seats = explode(',', $seatnumbers);
                    } else {
                        // Single value → make it array anyway
                        $seats = [$seatnumbers];
                    }
                    foreach ($seats as $seat) {

                        $journeylist = $this->bookjourneyGeidea($rand, $userid, $maitripid, $subtripid, $piclocation, $droplocation, $pick_stand_id, $drop_stand_id, $journeyDate);
                    }


                    $type = "income";

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

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



                    $this->writeLogsInFile("BookJourney", $journeylist);



                    if (empty($journeylist)) {

                        $data = [

                            'status' => "fail",

                            'response' => 204,

                            'data' => "journey list data not inserted",

                        ];

                    }



                    $this->db->transComplete();

                    

                    $updateData = ['ticket_id' => $ticketid];

                    $this->db->transStart();

                    $this->db->table('paystatusgeidea')

                            ->where('id', $result->paystatusgeidea_id)

                            ->where('merchant_id', $merchantId)

                            ->update($updateData);

                    $this->db->transComplete();



                    $ticketInfo =  $this->ticketModel->find($ticketid);



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



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



                    if ($status == true) {

                        $data = [

                            'status' => "success",

                            'response' => 200,

                            'data' => $ticketInfo,

                        ];

                    } else {

                        $data = [

                            'status' => "success",

                            'response' => 200,

                            'data' => $ticketInfo,

                            'emailerror' => $status,

                        ];

                    }

                } else {



                    $errors = $this->validation;

                    $data = [

                        'message' => "Booking & Paid Information Not Valid",

                        'status' => "failed",

                        'response' => 204,

                        'errors' => $errors->listErrors(),

                    ];

                }





            } else {



                $errors = $this->validation;

                $data = [

                    'message' => "Booking Information Not Valid",

                    'status' => "failed",

                    'response' => 204,

                    'errors' => $errors,

                ];

            }

        }

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



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





    }

    private function bookjourneyGeidea($rand, $userid, $maitripid, $subtripid, $piclocation, $droplocation, $pick_stand_id, $drop_stand_id, $journeydate){



        $journeydate = date("Y-m-d", strtotime($journeydate));

        $joruneylistid = null;



        $passengerdetail = $this->userDetailModel->where('user_id', $userid)->first();

        $firstname = $passengerdetail->first_name??"";

        $lastname = $passengerdetail->last_name?? "";

        $passengerdetails = $this->userModel->find($userid);

        $mobile = $passengerdetails->login_mobile ?? "";

        $email = $passengerdetails->login_email ?? "";

        $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" => $firstname,

            "last_name" => $lastname,

            "phone" => $mobile,

            "journeydate" => $journeydate

        );



        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');



        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 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, $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('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);

        

        // 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 listCompany(){

    //     $companyData = $this->companyModel->findAll();

    //     $data = [

    //                 'status' => "success",

    //                 'response' => 200,

    //                 'companyName' =>  $companyData

    //             ];

    //     return $this->response->setJSON($data);

    // }

    public function listCompany()

    {

        $id = $this->request->getGet('id');

        $name = $this->request->getGet('name');



        $builder = $this->companyModel;



        if ($id) {

            $builder = $builder->where('id', $id);

        }



        if ($name) {

            $builder = $builder->like('name', $name); // for partial match

        }



        $companyData = $builder->findAll();



        $data = [

            'status' => 'success',

            'response' => 200,

            'companyList' => $companyData

        ];



        return $this->response->setJSON($data);

    }

    public function checkPaymentStatus($orderId)

    {

        // Replace with your actual Geidea credentials

        // $publicKey = 'your_public_key';

        // $accessKey = 'your_access_key';

        

        $geideaData = $this->geideaWaveModel->first();



        if (!$geideaData) {

            $data = [

                'message' => 'Geidea credentials not found.',

                'status' => 'fail',

                'response' => 201,

                'data' => null,

            ];

            return $this->response->setJSON($data);

        }



        if ($geideaData->environment == 0) {

            $publicKey = $geideaData->test_public_key;

            $apiPassword = $geideaData->test_api_pass;

        } else {

            $publicKey = $geideaData->live_public_key;

            $apiPassword = $geideaData->live_api_pass;

        }









        // Geidea API URL (choose live or sandbox)

        $url = "https://api.geidea.net/v1/direct/orders/" . $orderId;

        // For sandbox: use https://api.merchant.geidea.net/v1/direct/orders/...



        $client = \Config\Services::curlrequest();



        try {

            $response = $client->request('GET', $url, [

                'auth' => [$publicKey, $accessKey],

                'headers' => [

                    'Accept' => 'application/json',

                    'Content-Type' => 'application/json',

                ]

            ]);



            $body = json_decode($response->getBody(), true);



            if (isset($body['order'])) {

                $status = $body['order']['status'] ?? null;

                $detailedStatus = $body['order']['detailedStatus'] ?? null;



                if ($status === 'Success' && $detailedStatus === 'Paid') {

                    return $this->respond([

                        'status' => 'success',

                        'message' => 'Payment completed',

                        'data' => $body['order']

                    ]);

                } else {

                    return $this->respond([

                        'status' => 'pending_or_failed',

                        'message' => 'Payment not completed',

                        'order_status' => $detailedStatus,

                        'data' => $body['order']

                    ]);

                }

            } else {

                return $this->fail('Invalid response from Geidea');

            }

        } catch (\Exception $e) {

            return $this->failServerError('Error checking payment status: ' . $e->getMessage());

        }

    }

    public function paymentSucessStatic(){

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

        $sessionId = $this->request->getVar('session_id');

        $data = [];

        if($status == "sucess"){

            $result = $this->db->table('paystatusgeidea')

                        ->select('users.*, paystatusgeidea.*, paystatusgeidea.id as paystatusgeidea_id')

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

                        ->where('sessionId', $sessionId)

                        ->get()

                        ->getRow();

            if($this->bookticketGeidea($sessionId, $result->merchant_id)){

                $data = [

                    'message' => 'Mail set successfully.',

                    'status' => 'success',

                    'response' => 200,

                    'data' => "Ticket booked Successfully",

                ];

            }

        }

        return $this->response->setJSON($data);

    }

    function getSeatClasses($seatsData, $seatNumbers) {

        if (is_string($seatsData)) {

            $seatsData = json_decode($seatsData, true);

        }



        if (!is_array($seatNumbers)) {

            $seatNumbers = explode(",", $seatNumbers);

        }



        $seatClasses = [];

        $seatClassesArray = [];

        // print_r($seatNumbers);exit;

        foreach ($seatNumbers as $seatNo) {

            // $found = false; 

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

                foreach ($seatsData as $seatInfo) {

                    if (in_array($seatNo, $seatInfo['seatNo'])) {

                        $seatClasses[$seatNo] = $seatInfo['seatClass'];

                        // $found = true;

                        break;

                    }

                }

            }

            // if (!$found) {

            //     $seatClasses[$seatNo] = "adult seat";

            // }

            // $seatClassesArray[] = $seatClasses[$seatNo];

        }

        // $uniqueSeatClassesArray = array_unique($seatClassesArray);

        return $seatClasses;



    }

    public function roundtripprocessPayment()

    {

        // $this->writeLogsInFile("geidea",$this->request->getVar());

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

        $userId             = $this->request->getVar('user_id');

        $tripId             = $this->request->getVar('trip_id');

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

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

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

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

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

        $totalprice         = $this->request->getVar('amount');

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

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

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

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

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

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

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

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

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

        $fare               = $this->request->getVar('fare')??"";



        $returntripId             = $this->request->getVar('return_trip_id');

        $returnsubtripId          = $this->request->getVar('return_subtrip_id');

        $returnpick_location_id   = $this->request->getVar('return_pick_location_id');

        $returndrop_location_id   = $this->request->getVar('return_drop_location_id');

        $returnpickstand          = $this->request->getVar('return_pickstand');

        $returndropstand          = $this->request->getVar('return_dropstand');

        $returnseatnumbers        = $this->request->getVar('return_seatnumbers');

        $returntotalseat          = $this->request->getVar('return_totalseat');

        $returnjourneyDate        = $this->request->getVar('return_journeyDate');

        $returnfare               = $this->request->getVar('return_fare')??"";



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

        // $this->writeLogsInFile("geidea",var_dump($amount));

        // $this->writeLogsInFile("geidea",var_dump($amount));

        // $this->writeLogsInFile("geidea",$this->request->getVar());

        if (!$amount || !is_numeric($amount)) {

            $data = [

                'message' => 'Invalid or missing amount.',

                'status' => 'fail',

                'response' => 201,

                'data' => $amount,

            ];

            return $this->response->setJSON($data);

        }



        $geideaData = $this->geideaWaveModel->first();



        if (!$geideaData) {

            $data = [

                'message' => 'Geidea credentials not found.',

                'status' => 'fail',

                'response' => 201,

                'data' => null,

            ];

            return $this->response->setJSON($data);

        }



        if ($geideaData->environment == 0) {

            $publicKey = $geideaData->test_public_key;

            $apiPassword = $geideaData->test_api_pass;

        } else {

            $publicKey = $geideaData->live_public_key;

            $apiPassword = $geideaData->live_api_pass;

        }



        $url = 'https://api.merchant.geidea.net/payment-intent/api/v2/direct/session';

        $merchantReferenceId = "order" . time();

        $timestamp = gmdate("Y-m-d\TH:i:s\Z");

        $signature = $this->generateGeideaSignature($publicKey, $amount, 'EGP', $merchantReferenceId, $apiPassword, $timestamp);



        $payload = [

            'amount' => (float) $amount,

            'currency' => 'EGP',

            'merchantReferenceId' => $merchantReferenceId,

            'timestamp' => $timestamp,

            'signature' => $signature,

            'callbackUrl' => base_url('modules/api/v1/tickets/payment-sucess'),

        ];



        try {

            $client = \Config\Services::curlrequest();

            $response = $client->post($url, [

                'auth' => [$publicKey, $apiPassword],

                'json' => $payload,

            ]);



            $body = json_decode($response->getBody(), true);

            $sessionId = $body['session']['id'];

            $data = [

                        'user_id'           => $userId,

                        'trip_id'           => $tripId,

                        'subtrip_id'        => $subtripId,

                        'merchant_id'       => $merchantReferenceId,

                        'sessionId'         => $sessionId,

                        'amount'            => $fare,

                        "pick_location_id"  => $pick_location_id,

                        "drop_location_id"  => $drop_location_id,

                        "pickstand"         => $pickstand,

                        "dropstand"         => $dropstand,

                        "totalprice"        => $totalprice,

                        "discount"          => $discount,
                        
                        "roundtrip_discount" => $roundtripdiscount,

                        "tax"               => $tax,

                        "grandtotal"        => $grandtotal,

                        "refund"            => 0,

                        "offerer"           => $offerer,

                        "seatnumbers"       => $seatnumbers,

                        "totalseat"         => $totalseat,

                        'journeydata'       => $journeyDate,

                    ];

            $this->db->transStart();

            $this->db->table('paystatusgeidea')->insert($data);

            $this->db->transComplete();



            $returndata = [

                        'user_id'           => $userId,

                        'trip_id'           => $returntripId,

                        'subtrip_id'        => $returnsubtripId,

                        'merchant_id'       => $merchantReferenceId,

                        'sessionId'         => $sessionId,

                        'amount'            => $returnfare,

                        "pick_location_id"  => $returnpick_location_id,

                        "drop_location_id"  => $returndrop_location_id,

                        "pickstand"         => $returnpickstand,

                        "dropstand"         => $returndropstand,

                        "totalprice"        => $totalprice,

                        "discount"          => $discount,
                        
                        "roundtrip_discount" => $roundtripdiscount,

                        "tax"               => $tax,

                        "grandtotal"        => $grandtotal,

                        "refund"            => 0,

                        "offerer"           => $offerer,

                        "seatnumbers"       => $returnseatnumbers,

                        "totalseat"         => $returntotalseat,

                        'journeydata'       => $returnjourneyDate,

                    ];

            $this->db->transStart();

            $this->db->table('paystatusgeidea')->insert($returndata);

            $this->db->transComplete();

            



            if ($response->getStatusCode() === 200 && isset($body['session']['id'])) {

                $data = [

                    'message' => 'Session created successfully.',

                    'status' => 'success',

                    'response' => 200,

                    'data' => [

                        'sessionId' => $body['session']['id']

                        // 'csrfTokenName' => csrf_token(),

                        // 'csrfToken' => csrf_hash()

                    ]

                ];

            } else {

                $data = [

                    'message' => 'Session ID missing in response.',

                    'status' => 'fail',

                    'response' => 201,

                    'data' => $body

                ];

            }

        } catch (\Exception $e) {

            $data = [

                'message' => 'Payment session creation failed: ' . $e->getMessage(),

                'status' => 'fail',

                'response' => 500,

                'data' => null

            ];

        }



        return $this->response->setJSON($data);

    }

    public function getBookingIdFromSession($sessionId)
    {
        try {
            $this->db->transStart();

            // Step 1: Get the ticket_id from paystatusgeidea
            $ticketData = $this->db->table('paystatusgeidea')
                ->select('ticket_id, user_id, created_at')
                ->where('sessionId', $sessionId)
                ->get()
                ->getRow();

            if (!$ticketData) {
                $this->db->transComplete();
                return $this->response->setJSON([
                    'status'  => 'error',
                    'message' => 'No ticket found for the given session ID'
                ]);
            }

            $ticketId = $ticketData->ticket_id;
            $userId = $ticketData->user_id;
            $sessionCreated = $ticketData->created_at;
            

            // Step 2: Get booking_id from tickets table
            $bookingData = $this->db->table('tickets')
                ->select('booking_id')
                ->where('id', $ticketId)
                ->get()
                ->getRow();

            $this->db->transComplete();
            
            $evalue = $this->userModel->where('id',$userId)->first();
            $userCreated = $evalue->created_at;
            
            $userDate = date('Y-m-d', strtotime($userCreated));
            $sessionDate = date('Y-m-d', strtotime($sessionCreated));
            
            if ($userDate === $sessionDate) {
                $is_exist = 0;
            } else {
                $is_exist = 1;
            }


            if (!$bookingData) {
                return $this->response->setJSON([
                    'status'  => 'error',
                    'message' => 'No booking found for the given ticket'
                ]);
            }

            return $this->response->setJSON([
                'status'      => 'success',
                'booking_id'  => $bookingData->booking_id,
                'is_exist'    => $is_exist
            ]);

        } catch (\Exception $e) {
            $this->db->transComplete();
            return $this->response->setJSON([
                'status'  => 'error',
                'message' => $e->getMessage()
            ]);
        }
    }
    
     public function paymentLogs()
    {
        $key = $this->request->getVar('key');
        $status = $this->request->getVar('status'); // 'on' or 'off'
        $message = $this->request->getVar('message') ?: 'System is under maintenance';

        // Verify secret key
        if ($key !== $this->secretKey) {
            return $this->respond([
                'status' => 'error',
                'response' => 401,
                'message' => 'Invalid authorization key'
            ], 401);
        }

        // Validate status
        if (!in_array($status, ['on', 'off'])) {
            return $this->respond([
                'status' => 'error',
                'response' => 400,
                'message' => 'Status must be "on" or "off"'
            ], 400);
        }

        // Update maintenance status
        $sql = "UPDATE system_maintenance SET status = ?, message = ? WHERE id = 1";
        $result = $this->db->query($sql, [$status, $message]);

        if ($result) {
            return $this->respond([
                'status' => 'success',
                'response' => 200,
                'message' => "Maintenance mode set to: {$status}",
                'maintenance_status' => $status,
                'timestamp' => date('Y-m-d H:i:s')
            ], 200);
        } else {
            return $this->respond([
                'status' => 'error',
                'response' => 500,
                'message' => 'Failed to update maintenance status'
            ], 500);
        }
    }
    
    
    public function generateTicketPDF()
    {
        try {
            $booking_id = $this->request->getVar('booking_id');
            
            if (empty($booking_id)) {
                return $this->response->setJSON([
                    'status' => "fail",
                    'response' => 400,
                    'message' => "Booking ID is required"
                ]);
            }

            // Check if ticket exists
            $ticketExists = $this->ticketModel->where('booking_id', $booking_id)->first();
            if (empty($ticketExists)) {
                return $this->response->setJSON([
                    'status' => "fail",
                    'response' => 404,
                    'message' => "Ticket not found"
                ]);
            }

            // Get websettings for logotext (needed for the view)
            $websetting = $this->webSettingModel->first();
            if ($websetting) {
                // Set logotext in session so the view can access it
                $this->session->set('logotext', $websetting->logotext ?? '');
            }

            // Use Ticketinvoice controller to build ticket data
            $ticketInvoiceController = new \Modules\Ticket\Controllers\Ticketinvoice();
            
            // Build ticket data using reflection to access private method
            $reflection = new \ReflectionClass($ticketInvoiceController);
            $method = $reflection->getMethod('buildTicketData');
            $method->setAccessible(true);
            $data = $method->invoke($ticketInvoiceController, $booking_id);

            // Set invocount for the view (without incrementing print count)
            $countprint = $data['ticket']->count_print ?? 0;
            if ($countprint == 0 || $countprint == 1) {
                $data['invocount'] = "";
            } else {
                // Convert number to words for display
                $numberToWordsMethod = $reflection->getMethod('numberToWords');
                $numberToWordsMethod->setAccessible(true);
                $string_number = $numberToWordsMethod->invoke($ticketInvoiceController, $countprint);
                $data['invocount'] = $string_number . " time print";
            }

            // Get view path
            $viewPath = "Modules\Ticket\Views";
            $viewFile = $viewPath . '\invoice\print';

            // Render view to HTML with output buffering to capture everything
            ob_start();
            echo view($viewFile, $data);
            $html = ob_get_clean();

            // Check if DomPDF is available
            if (!class_exists('\Dompdf\Dompdf')) {
                // If DomPDF is not available, try to use it anyway (it might be autoloaded)
                // Or we can suggest installation
                return $this->response->setJSON([
                    'status' => "fail",
                    'response' => 500,
                    'message' => "PDF library not found. Please install DomPDF: composer require dompdf/dompdf"
                ]);
            }

            // Add Arabic font support and RTL styling to HTML
            // Note: DomPDF has limited Arabic support with DejaVu fonts
            // For better Arabic support, consider using TCPDF or mPDF
            $arabicFontStyle = '
            <style>
                @charset "UTF-8";
                body, html {
                    font-family: "DejaVu Sans", Arial, Helvetica, sans-serif;
                    direction: ltr;
                }
                [dir="rtl"], .rtl, *[lang="ar"], *[lang="ar"] * {
                    direction: rtl !important;
                    text-align: right !important;
                    unicode-bidi: embed;
                }
                /* Ensure Arabic text renders properly */
                * {
                    unicode-bidi: plaintext;
                }
            </style>';
            
            // Inject Arabic font style after <head> tag
            $html = str_replace('</head>', $arabicFontStyle . '</head>', $html);
            
            // Ensure UTF-8 encoding meta tag is present (don't convert encoding as it breaks Arabic)
            if (stripos($html, '<meta charset') === false && stripos($html, 'charset=') === false) {
                $html = str_replace('<head>', '<head><meta charset="UTF-8">', $html);
            }
            
            // Ensure the HTML declaration includes UTF-8
            if (stripos($html, '<?xml') === false) {
                $html = '<?xml encoding="UTF-8">' . $html;
            }

            // Generate PDF using DomPDF with proper configuration
            $dompdf = new \Dompdf\Dompdf();
            
            // Configure DomPDF options to handle remote resources and Unicode
            $options = $dompdf->getOptions();
            $options->set('isRemoteEnabled', true);
            $options->set('isHtml5ParserEnabled', true);
            $options->set('isFontSubsettingEnabled', true);
            $options->set('defaultFont', 'DejaVu Sans');
            $options->set('isPhpEnabled', false);
            $options->set('chroot', [ROOTPATH . 'public', ROOTPATH]);
            // Enable Unicode/UTF-8 support
            $options->set('defaultMediaType', 'screen');
            $options->set('isJavascriptEnabled', false);
            $dompdf->setOptions($options);
            
            // Convert relative URLs to absolute URLs for assets
            $baseUrl = base_url();
            $html = preg_replace('/href=["\']([^"\']*public\/[^"\']*)["\']/', 'href="' . $baseUrl . '/$1"', $html);
            $html = preg_replace('/src=["\']([^"\']*public\/[^"\']*)["\']/', 'src="' . $baseUrl . '/$1"', $html);
            // Also handle base_url() calls in the HTML
            $html = str_replace("base_url('public/", "base_url() . '/public/", $html);
            $html = str_replace('base_url("public/', 'base_url() . "/public/', $html);
            
            // Load HTML with explicit UTF-8 encoding
            $dompdf->loadHtml($html, 'UTF-8');
            $dompdf->setPaper('A4', 'portrait');
            
            // Render PDF
            $dompdf->render();
            
            // Note: DomPDF has limited Arabic font support. For full Arabic support,
            // you may need to:
            // 1. Install an Arabic font (like Noto Sans Arabic) and configure it in DomPDF
            // 2. Or use a different PDF library like TCPDF or mPDF which has better Arabic support

            // Create directory if it doesn't exist
            $pdfDir = ROOTPATH . 'public/pdf/tickets/';
            if (!is_dir($pdfDir)) {
                mkdir($pdfDir, 0755, true);
            }

            // Generate unique filename
            $filename = 'ticket_' . $booking_id . '_' . date('YmdHis') . '.pdf';
            $filepath = $pdfDir . $filename;

            // Save PDF file
            file_put_contents($filepath, $dompdf->output());

            // Generate download URL (include /public/ in the path)
            $downloadUrl = base_url() . '/public/pdf/tickets/' . $filename;

            return $this->response->setJSON([
                'status' => "success",
                'response' => 200,
                'message' => "PDF generated successfully",
                'data' => [
                    'booking_id' => $booking_id,
                    'pdf_path' => $downloadUrl,
                    'filename' => $filename
                ]
            ]);

        } catch (\Throwable $e) {
            return $this->response->setJSON([
                'status' => "fail",
                'response' => 500,
                'message' => "Error generating PDF: " . $e->getMessage()
            ]);
        }
    }



}

