<?php

namespace Modules\Ticket\Controllers;

use App\Controllers\BaseController;

use Modules\Fleet\Models\FleetModel;
use Modules\Fleet\Models\VehicleModel;
use Modules\Location\Models\LocationModel;
use Modules\Location\Models\StandModel;
use Modules\Schedule\Models\ScheduleModel;
use Modules\Tax\Models\TaxModel;
use Modules\Ticket\Models\TicketModel;
use Modules\Ticket\Models\PartialpaidModel;
use Modules\Trip\Models\FacilityModel;
use Modules\Trip\Models\PickdropModel;
use Modules\Trip\Models\SubtripModel;
use Modules\Trip\Models\TripModel;
use Modules\User\Models\UserDetailModel;
use Modules\User\Models\UserModel;
use Modules\Page\Models\TermsModel;
use Modules\Term\Models\TermModel;


class Ticketinvoice extends BaseController
{
    protected $Viewpath;
    protected $ticketModel;
    protected $partialPaidModel;
    protected $tripModel;
    protected $subtripModel;
    protected $locationModel;
    protected $fleetTypeModel;
    protected $scheduleeModel;
    protected $vehicleModel;
    protected $standModel;
    protected $picdropModel;
    protected $facilitypModel;
    protected $taxModel;
    protected $db;
    protected $userModel;
    protected $userDetailModel;

    protected $termsModel;



    public function __construct()
    {

        $this->Viewpath = "Modules\Ticket\Views";
        $this->ticketModel = new TicketModel();
        $this->tripModel = new TripModel();
        $this->subtripModel = new SubtripModel();
        $this->locationModel = new LocationModel();
        $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->userModel = new UserModel();
        $this->userDetailModel = new UserDetailModel();

        $this->partialPaidModel = new PartialpaidModel();

        $this->termsModel = new TermsModel();
    }

    public function show($ticketbookingid)
    {   
        $data = $this->buildTicketData($ticketbookingid);
        return view($this->Viewpath . '\invoice\show', $data);
    }

    public function print($ticketbookingid)
    {
        
        $db = \Config\Database::connect();
        
        $query = "SELECT * FROM tickets WHERE booking_id=?";
        $ticketdata = $db->query($query, [$ticketbookingid]);
        // print_r($ticketdata->getRow()->count_print);die;
        $countprint = $ticketdata->getRow()->count_print;
        
        $newcountprint = $countprint +1;
        
        $sqlquery = "UPDATE tickets SET count_print = ? WHERE booking_id = ?";
        $db->query($sqlquery, [$newcountprint, $ticketbookingid]);
        
        $data = $this->buildTicketData($ticketbookingid);
        
        $number = $data['ticket']->count_print;
        
        $string_number = $this->numberToWords($number);
        
        if($number == 1){
            $data['invocount'] = "";
        }else{
            $data['invocount'] = $string_number." time print";
        }
        
        return view($this->Viewpath . '\invoice\print', $data);
    }

    public function posinvoice($ticketbookingid)
    {
        $db = \Config\Database::connect();
        
        
        // print_r($data);die;
        
        $query = "SELECT * FROM tickets WHERE booking_id=?";
        $ticketdata = $db->query($query, [$ticketbookingid]);
        // print_r($ticketdata->getRow()->count_print);die;
        $countprint = $ticketdata->getRow()->count_print;
        
        $newcountprint = $countprint +1;
        
        $sqlquery = "UPDATE tickets SET count_print = ? WHERE booking_id = ?";
        $db->query($sqlquery, [$newcountprint, $ticketbookingid]);
        
        
        $data = $this->buildTicketData($ticketbookingid);
        
        // print_r($data['ticket']->count_print);die;
        
        // Example usage
        $number = $data['ticket']->count_print;
        
        $string_number = $this->numberToWords($number);
        
        if($number == 1){
            $data['invocount'] = "";
        }else{
            $data['invocount'] = $string_number." time print";
        }
        
        // print_r($data['ticket']->count_print);die;
        
        return view($this->Viewpath . '\invoice\posinvoice', $data);
    }   
    
    public function numberToWords($number) {
    // Array of words for numbers
    $words = array(
        '',
        'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine',
        'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen',
        'twenty', 30 => 'thirty', 40 => 'forty', 50 => 'fifty', 60 => 'sixty', 70 => 'seventy', 80 => 'eighty', 90 => 'ninety'
    );

    // Array of powers
    $powers = array('', 'thousand', 'million', 'billion', 'trillion');

    // Convert the number to an array of digits
    $digits = array_reverse(str_split(str_pad($number, ceil(strlen($number) / 3) * 3, '0', STR_PAD_LEFT), 3));

    // Initialize an empty array to store the words
    $result = array();

    // Iterate over each group of three digits
    foreach ($digits as $key => $value) {
        // Convert the three-digit number to words
        $chunk = array();

        if ($value != '000') {
            if ($value[0] != '0') {
                $chunk[] = $words[$value[0]] . ' hundred';
            }

            if ($value[1] != '0') {
                if ($value[1] == '1') {
                    $chunk[] = $words[$value[1] . $value[2]];
                } else {
                    $chunk[] = $words[$value[1] * 10];
                }
            }

            if ($value[2] != '0' && $value[1] != '1') {
                $chunk[] = $words[$value[2]];
            }
        }

        // Append the appropriate power
        if (!empty($chunk)) {
            $result[] = implode(' ', $chunk) . ' ' . $powers[$key];
        }
    }

    // Return the result
    return implode(' ', array_reverse($result)) ?: 'zero';
}

    private function buildTicketData(string $ticketbookingid)
    {
        // Build ticket info
        $ticketInfo = $this->ticketModel
            ->select('tickets.created_at as bookingdate, tickets.*, users.*, user_details.*')
            ->join('users', 'users.id = tickets.passanger_id')
            ->join('user_details', 'user_details.user_id = users.id')
            ->where('booking_id', $ticketbookingid)
            ->withDeleted()->get()->getRow();

        if ($ticketInfo) {
            $journeyDateHelper = new \App\Libraries\TripJourneyDateHelper();
            $boardingDate = $journeyDateHelper->getPassengerBoardingDateForDisplay(
                (int) $ticketInfo->trip_id,
                (int) $ticketInfo->subtrip_id,
                $ticketInfo->journeydata,
                (int) $ticketInfo->pick_stand_id
            );
            $ticketInfo->journeydata = $boardingDate;
            $ticketInfo->boarding_date = $boardingDate;
        }

        $data['ticket'] = $ticketInfo;

        // Build trip, schedule and subtrip data
        $gettripdata =  $this->tripModel
            ->select('trips.*, l_p.name AS pl_name, l_d.name AS dl_name, sc.start_time, sc.end_time, cs.name AS company_name')
            ->join('locations l_p', 'trips.pick_location_id = l_p.id', 'left')
            ->join('locations l_d', 'trips.drop_location_id = l_d.id', 'left')
            ->join('schedules sc', 'trips.schedule_id = sc.id', 'left')
            ->join('companies cs', 'trips.company_id = cs.id', 'left')
            ->withDeleted()
            ->find($ticketInfo->trip_id);

        $travelartripdata = $this->subtripModel
            ->select('subtrips.*, l_p.name AS pl_name, l_d.name AS dl_name')
            ->join('locations l_p', 'subtrips.pick_location_id = l_p.id')
            ->join('locations l_d', 'subtrips.drop_location_id = l_d.id')
            ->withDeleted()
            ->find($ticketInfo->subtrip_id);

        $seatClass = $travelartripdata->subtrip_seatclass ?? $gettripdata->seatclass;

        if (is_string($seatClass)) {
            $seatClass = json_decode($seatClass, true); // true makes it an associative array
        }
        $seatClassArray = [];
        $bookedSeatArray = $ticketInfo->seatnumber?explode(',', $ticketInfo->seatnumber) :[];
        $this->db->transStart();
        $classData = $this->db->table('seat_class')
                        ->get()
                        ->getResultArray();
        $this->db->transComplete();

        $seatClassData = array_column($classData, 'name', 'id');

        // if (is_array($bookedSeatArray)) {
        //     foreach ($bookedSeatArray as $item) {
        //         $noelse = 1;
        //         foreach ($seatClass as $seatitem) {
        //             if(in_array($item,$seatitem['seatNo'])){
        //                 $seatClassArray[] = $seatClassData[$seatitem['seatClass']]."( ".$seatitem['seatNo']." )";
        //                 $noelse = 0;
        //             }
        //         }
        //         if($noelse){
        //             $seatClassArray[] = "Economy ( ".$item. " )";
        //         }
        //     }
        // }

        $groupedSeats = [];

        if (is_array($bookedSeatArray)) {
            foreach ($bookedSeatArray as $item) {
                $found = false;
                if(is_array($seatClass) && !empty($seatClass)){
                    foreach ($seatClass as $seatitem) {
                        if (in_array($item, $seatitem['seatNo'])) {
                            $classLabel = $seatClassData[$seatitem['seatClass']] ?? 'Unknown';
                            if (!isset($groupedSeats[$classLabel])) {
                                $groupedSeats[$classLabel] = [];
                            }
                            $groupedSeats[$classLabel][] = $item;
                            $found = true;
                            break; // once found, break inner loop
                        }
                    }

                }
                
                if (!$found) {
                    // Default to Economy if seat not found in any seat class
                    if (!isset($groupedSeats['Economy'])) {
                        $groupedSeats['Economy'] = [];
                    }
                    $groupedSeats['Economy'][] = $item;
                }
            }
        }

        // Build final seat class string
        $seatClassArray = [];
        foreach ($groupedSeats as $class => $seats) {
            $seatClassArray[] = $class . ' ( ' . implode(',', $seats) . ' )';
        }


        // foreach ($seatClass as $item) {
        //     $seatClassArray[$item['seatClass']] = $item['seatNo'];
        // }
        // print_r($seatClassArray);
        // exit;

        $data['from'] = $gettripdata->pl_name;
        $data['to'] = $gettripdata->dl_name;
        $data['trip_start_time'] = $gettripdata->start_time;
        $data['trip_end_time'] = $gettripdata->end_time;
        $data['travelerPick'] = $travelartripdata->pl_name;
        $data['travelerDrop'] = $travelartripdata->dl_name;
        $data['company_name'] = $gettripdata->company_name ?? "";
        $data['seat_class'] = $seatClassArray ?? [];

        // Build payment data
        $totalpaid = $this->partialPaidModel
            ->selectSum('paidamount')
            ->where('booking_id', $ticketbookingid)
            ->first();

        $storedGrandTotal = (float) ($ticketInfo->paidamount ?? 0);
        $totalPaidAmount = (float) ($totalpaid->paidamount ?? 0);
        $invoiceGrandTotal = $storedGrandTotal;
        if (($ticketInfo->payment_status ?? '') === 'paid' && $totalPaidAmount > 0) {
            // Paid bookings should reflect the effectively collected amount.
            $invoiceGrandTotal = $totalPaidAmount;
        }
        $data['invoice_grand_total'] = $invoiceGrandTotal;
        $data['total_paid_amount'] = $totalPaidAmount;
        $data['due'] = max(0, $storedGrandTotal - $totalPaidAmount);

        $normalDiscount = (float) ($ticketInfo->discount ?? 0);
        $roundTripDiscount = (float) ($ticketInfo->roundtrip_discount ?? 0);
        $isRoundTripTicket = ($roundTripDiscount > 0);
        if ($isRoundTripTicket) {
            $data['invoice_discount_label'] = lang("Localize.discount_round_trip");
            $data['invoice_discount_amount'] = $normalDiscount > 0 ? $normalDiscount : $roundTripDiscount;
        } else {
            $data['invoice_discount_label'] = lang("Localize.discount");
            $data['invoice_discount_amount'] = $normalDiscount;
        }

        // Build facilities
        $data['facility'] = "no ficility";

        if ($facilities = $gettripdata->facility) {
            // facility exists
            // explode comma separated facilities
            $facilityArr = explode(",", $facilities);
            $facilityNameArr = [];

            foreach ($facilityArr as $facility) {
                $facilityInfo = $this->facilitypModel->select('name')->withDeleted()->find($facility);
                $facilityNameArr[] = $facilityInfo->name;
            }

            $data['facility'] = implode(", ", $facilityNameArr);
        }

        // Buil pickdrop and policy
        $data['pickdrop'] = $this->picdropModel
            ->select('pickdrops.*,stands.*,pickdrops.id as pickdropid, stands.name as stand_name')
            ->join('stands', 'stands.id = pickdrops.stand_id')
            ->withDeleted()
            ->findAll();

        $totalpolicy =  $this->termsModel->first();
        $data['policy'] = $totalpolicy->description;
        $data['policy'] = "";

        $Termmodel = new TermModel();
        $gettripdata->company_id;
        $TermData = $Termmodel->where('company_id', $gettripdata->company_id)->where('status', 1)->first();
        if(!empty($TermData)){
            $data['policy'] = $TermData->description;
        }
        

        $data['pageheading'] = "Invoice";
        $data['pageheading'] = lang("Localize.ticket") . ' ' . lang("Localize.invoice");
        
        return $data;
    }
}
