<?php

namespace App\Controllers;

use CodeIgniter\RESTful\ResourceController;
use CodeIgniter\Files\File;
use DateTime;

use App\Models\UserModel;
use App\Models\PlanModel;
use App\Models\FlightModel;
use App\Models\FlightTripsModel;
use App\Models\AccomodationModel;
use App\Models\BusModel;
use App\Models\InsuranceModel;
use App\Models\MiscellaneousModel;
use App\Models\TaxiModel;
use App\Models\TrainModel;
use App\Models\VisaModel;
use App\Models\ForexModel;
use App\Models\ForexPerdiemModel;
use App\Models\PlanStatusModel;
use App\Models\OrganizationModel;
use App\Models\PlanRemarkModel;
use App\Models\UserVisaDetailsModel;
use App\Models\MailTemplateModel;
use App\Models\ReportsModel;
use App\Models\GroupModel;
use App\Models\PolicyModel;
use App\Models\TravellerModel;
use Mpdf\Mpdf;

class PlanController extends ResourceController
{
    protected $format    = 'json';
    protected $myLogger;
    protected $userModel;
    protected $planModel;
    protected $flightModel;
    protected $flightTripsModel;
    protected $accomodationModel;
    protected $busModel;
    protected $insuranceModel;
    protected $miscellaneousModel;
    protected $taxiModel;
    protected $trainModel;
    protected $visaModel;
    protected $forexModel;
    protected $forexPerdiemModel;
    protected $planStatusModel;
    protected $organizationModel;
    protected $planRemarkModel;
    protected $userVisaDetailsModel;
    protected $mailTemplateModel;
    protected $reportsModel;
    protected $groupModel;
    protected $policyModel;
    protected $travellerModel;

    public function __construct()
    {
       
        $this->myLogger = \Config\Services::mylogger();
        $this->userModel = new UserModel();
        $this->planModel = new PlanModel();
        $this->flightModel = new FlightModel();
        $this->flightTripsModel = new FlightTripsModel();
        $this->accomodationModel = new AccomodationModel();
        $this->busModel = new BusModel();
        $this->insuranceModel = new InsuranceModel();
        $this->miscellaneousModel = new MiscellaneousModel();
        $this->taxiModel = new TaxiModel();
        $this->trainModel = new TrainModel();
        $this->visaModel = new VisaModel();
        $this->forexModel = new ForexModel();
        $this->forexPerdiemModel = new ForexPerdiemModel();
        $this->planStatusModel = new PlanStatusModel();
        $this->organizationModel = new OrganizationModel();
        $this->planRemarkModel = new PlanRemarkModel();
        $this->userVisaDetailsModel = new UserVisaDetailsModel();
        $this->mailTemplateModel = new MailTemplateModel();
        $this->reportsModel      = new ReportsModel();
        $this->groupModel = new GroupModel();
        $this->policyModel      = new PolicyModel();
        $this->travellerModel      = new TravellerModel();

    }


    public function userPlans()
    {

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

        $plans = $this->planModel->getActivePlan($org_id, 'USER', $user_id);

        if (!$plans) {
            return $this->respond(['status' => 200,'message' => 'failed','data' => 'No Plans found']);
        }

        return $this->respond(['status' => 200,'message' => 'success','data' => $plans]);
       
    }


    public function allPlans()
    {

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

        $plans = $this->planModel->getActivePlan($org_id);
        
        if (!$plans) {
            return $this->respond(['status' => 200,'message' => 'failed','data' => 'No Plans found']);
        }

        return $this->respond(['status' => 200,'message' => 'success','data' => $plans]);
       
    }

    public function findApprovalList()
    {
        
        $org_id = $this->request->getGet('org_id');
        $user_id = $this->request->getVar('user_id');

        $userData = $this->userModel->where('user_id',$user_id)->first();
        $userName = $userData['first_name'].' '.$userData['last_name'];


        $a1Data = $this->planStatusModel->select('plan_id')->where('a1_id',$user_id)->where('a1_action','Approval')->where('is_active',1)->findAll();
        $a2Data = $this->planStatusModel->select('plan_id')->where('a2_id',$user_id)->where('a2_action','Approval')->where('is_active',1)->findAll();
        $a3Data = $this->planStatusModel->select('plan_id')->where('a3_id',$user_id)->where('a3_action','Approval')->where('is_active',1)->findAll();
        $a4Data = $this->planStatusModel->select('plan_id')->where('a4_id',$user_id)->where('a4_action','Approval')->where('is_active',1)->findAll();

        $mergedArray = array_merge($a1Data, $a2Data, $a3Data, $a4Data);
        $planIds = array_unique(array_column($mergedArray, "plan_id"));
        $plans = [];
        if (count($planIds)) {
            $plans = $this->planModel->getActivePlan($org_id, 'APPROVAL', $user_id , $planIds);
       
            if (!$plans) {
                return $this->respond(['status' => 200,'message' => 'failed','data' => 'No Plans found']);
            }
            
            foreach ($plans as &$plan) {
                $plan['approver_id'] = $user_id;
                $plan['approver_name'] = 'Self';
                $plan['delegater_id'] = 0;
                $plan['approver_status'] = getApproverCurrentAction( $plan['plan_id'], $user_id );
            }
            unset($plan);
        }

       

        $delecatedPlans = getDelegatedPlans($org_id, $user_id);

        $mergedArray = array_merge($plans , $delecatedPlans);

        if(empty($mergedArray)){
            return $this->respond(['status' => 200,'message' => 'success','data' => []]);
        }

        return $this->respond(['status' => 200,'message' => 'success','data' => $mergedArray]);
       
    }

    public function findTravelAgentPlanList()
    {
        
        $org_id = $this->request->getGet('org_id');
        $user_id = $this->request->getVar('user_id');

        $userData = $this->userModel->where('user_id', $user_id)->first();
        // var_dump($userData['agent_supported_service_ids']);
        // dd(json_decode($userData['agent_supported_service_ids']));
        if($userData['agent_supported_service_ids'] != null)
        {

            $S1Data = $S2Data = $S3Data = $S4Data = $S5Data = $S6Data = $S7Data = $S8Data = $S9Data = [];
            foreach (json_decode($userData['agent_supported_service_ids'],true) as $Servicekey => $Servicevalue) 
            {
                if($Servicevalue['service_id'] == 1)
                {
                    $S1Data = $this->flightModel->select('plan_id')->distinct()->where('is_active',1)->findAll();
                }else if($Servicevalue['service_id'] == 2)
                {
                    $S2Data = $this->trainModel->select('plan_id')->distinct()->where('is_active',1)->findAll();

                }else if($Servicevalue['service_id'] == 3)
                {
                    $S3Data = $this->busModel->select('plan_id')->distinct()->where('is_active',1)->findAll();

                }else if($Servicevalue['service_id'] == 4)
                {
                    $S4Data = $this->taxiModel->select('plan_id')->distinct()->where('is_active',1)->findAll();

                }else if($Servicevalue['service_id'] == 5)
                {
                    $S5Data = $this->accomodationModel->select('plan_id')->distinct()->where('is_active',1)->findAll();

                }else if($Servicevalue['service_id'] == 6)
                {
                    $S6Data = $this->forexModel->select('plan_id')->distinct()->where('is_active',1)->findAll();

                }else if($Servicevalue['service_id'] == 7)
                {
                    $S7Data = $this->insuranceModel->select('plan_id')->distinct()->where('is_active',1)->findAll();

                }else if($Servicevalue['service_id'] == 8)
                {
                    $S8Data = $this->visaModel->select('plan_id')->distinct()->where('is_active',1)->findAll();

                }else if($Servicevalue['service_id'] == 9)
                {
                    $S9Data = $this->miscellaneousModel->select('plan_id')->distinct()->where('is_active',1)->findAll();

                }

            }

            $mergedArray = array_merge($S1Data, $S2Data, $S3Data, $S4Data, $S5Data, $S6Data, $S7Data, $S8Data, $S9Data);
            $planIds = array_unique(array_column($mergedArray, "plan_id"));

            if (empty($planIds)) {
                return $this->respond(['status' => 200,'message' => 'failed','data' => 'No Plans found']);
            }
    
            $plans = $this->planModel->getActivePlan($org_id, 'AGENT', $user_id , $planIds);
           
            if (!$plans) {
                return $this->respond(['status' => 200,'message' => 'failed','data' => 'No Plans found']);
            }
    
            return $this->respond(['status' => 200,'message' => 'success','data' => $plans]);

        }else{
            return $this->respond(['status' => 200,'message' => 'failed','data' => 'Service not mapped to the agent.']);
        }
       
    }

    public function find($planId = null , $callFrom = 'client')
    {
        
        
        // Fetch the plan
        $plan = $this->planModel->select(  'm_plan.*, 
                                            CONCAT_WS(U.first_name," ",U.last_name) as user_name,
                                            CONCAT_WS(C.first_name," ",C.last_name) as plan_created_by,
                                            CONCAT_WS(T.first_name," ",T.last_name) as traveller_name,
                                            TS.status_value,
                                            TT.dropdown_value as trip_type_value, 
                                            IB.dropdown_value as is_billable_value, 
                                            POT.dropdown_value as purpose_of_travel_value,
                                            FD.dropdown_value as functional_department_value,
                                            Dep.name as cost_center_value'
                                        )
                                    ->join('m_users U', 'U.user_id = m_plan.user_id ', 'left')
                                    ->join('m_users C', 'C.user_id = m_plan.created_by ', 'left')
                                    ->join('m_traveller T', 'T.traveller_id = m_plan.traveller_id ', 'left')
                                    ->join('m_travel_statuses TS', 'TS.id = m_plan.status ', 'left')
                                    ->join('m_dropdown TT', 'TT.dropdown_key = m_plan.trip_type AND TT.dropdown = "plan_trip_type"', 'left')
                                    ->join('m_dropdown IB', 'IB.dropdown_key = m_plan.is_billable AND IB.dropdown = "plan_is_billable"', 'left')
                                    ->join('m_dropdown POT', 'POT.dropdown_key = m_plan.purpose_of_travel AND POT.dropdown = "plan_purpose_of_travel"', 'left')
                                    ->join('m_dropdown FD', 'FD.dropdown_key = m_plan.functional_department AND FD.dropdown = "plan_functional_department"', 'left')
                                    ->join('m_department Dep', 'Dep.department_id = m_plan.cost_center_id ', 'left')
                                    ->where('m_plan.is_active', 1)
                                    ->find($planId);

        if ($plan) {
            
            //get flight details
            $flights = $this->flightModel->where('plan_id', $planId)->where('is_active', 1)->findAll();
            foreach ($flights as &$flight) {
                $flight['trips'] = $this->flightTripsModel->where('flight_id', $flight['flight_id'])->where('is_active', 1)->findAll();
                foreach ($flight['trips'] as &$item) {
                    if (isset($item['date'])) {
                        $item['date'] = format_date_for_client($item['date']);
                    }
                }
            }
            $plan['flight'] = $flights;

            //get accomodation details
            $plan['accomodation'] = $this->accomodationModel->where('plan_id', $planId)->where('is_active', 1)->findAll();
            foreach ($plan['accomodation'] as &$item) {
                if (isset($item['checkin_date'])) {
                    $item['checkin_date'] = format_date_for_client($item['checkin_date']);
                }
                if (isset($item['checkout_date'])) {
                    $item['checkout_date'] = format_date_for_client($item['checkout_date']);
                }
            }
            

            //get bus details
            $plan['bus'] = $this->busModel->where('plan_id', $planId)->where('is_active', 1)->findAll();
            foreach ($plan['bus'] as &$item) {
                if (isset($item['date'])) {
                    $item['date'] = format_date_for_client($item['date']);
                }
            }


            //get insurance details
            $plan['insurance'] = $this->insuranceModel->where('plan_id', $planId)->where('is_active', 1)->findAll();
            foreach ($plan['insurance'] as &$item) {
                if (isset($item['start_date'])) {
                    $item['start_date'] = format_date_for_client($item['start_date']);
                }
                if (isset($item['end_date'])) {
                    $item['end_date'] = format_date_for_client($item['end_date']);
                }
                if (isset($item['nominee_dob'])) {
                    $item['nominee_dob'] = format_date_for_client($item['nominee_dob']);
                }
            }

            //get miscellaneous details
            $plan['miscellaneous'] = $this->miscellaneousModel->where('plan_id', $planId)->where('is_active', 1)->findAll();

            //get taxi details
            $plan['taxi'] = $this->taxiModel->where('plan_id', $planId)->where('is_active', 1)->findAll();
            foreach ($plan['taxi'] as &$item) {
                if (isset($item['date'])) {
                    $item['date'] = format_date_for_client($item['date']);
                }
            }

            //get train details
            $plan['train'] = $this->trainModel->where('plan_id', $planId)->where('is_active', 1)->findAll();
            foreach ($plan['train'] as &$item) {
                if (isset($item['date'])) {
                    $item['date'] = format_date_for_client($item['date']);
                }
            }

            //get visa details
            $plan['visa'] = $this->visaModel->where('plan_id', $planId)->where('is_active', 1)->findAll();
            foreach ($plan['visa'] as &$item) {
                if (isset($item['start_date'])) {
                    $item['start_date'] = format_date_for_client($item['start_date']);
                }
            }

            //get visa details
            $plan['forex'] = $this->forexModel->where('plan_id', $planId)->where('is_active', 1)->findAll();
            foreach ($plan['forex'] as &$item) {
                if (isset($item['start_date'])) {
                    $item['start_date'] = format_date_for_client($item['start_date']);
                }
                if (isset($item['end_date'])) {
                    $item['end_date'] = format_date_for_client($item['end_date']);
                }

                $forexPerdiem = $this->forexPerdiemModel->where('country_code',$item['country_code'])->find();
                $item['cash_percentage'] = 15;
                $item['card_percentage'] = 85;
               
                if($forexPerdiem)
                {
                    $item['card_percentage'] = $forexPerdiem[0]['card_percentage'];
                    $item['cash_percentage'] = $forexPerdiem[0]['cash_percentage'];
                }
            }

            //get plan status and it's approver 
            $plan['plan_status'] = getCurrentPlanStatus($planId); 

           
            if($callFrom == 'client')
            {
                return $this->respond(['status' => 200,'message' => 'success','data' => $plan]);
            }else{
                return $plan;
            }
            
            
           
           

        }else{
            return $this->respond(['status' => 200,'message' => 'failed','data' => []]);
        }

        
    }

    public function createOrEditPlan()
    {
        try {

            $json = $this->request->getJSON(true);
        
            
            // Check if plan_id exists
            if (!empty($json['plan_id'])) {
                $plan = $this->planModel->find($json['plan_id']);
            }

            if (isset($plan)) {
                // Update existing plan
                $this->planModel->update($json['plan_id'], $json);
                $planId = $json['plan_id'];
                $updatedBy = $json['updated_by'];
            } else {
                // Insert new plan
                $planId = $this->planModel->insert($json, true);
                $updatedBy = $json['created_by'];
            }

            $sendMailForEdit = false;

            
            if (!empty($json['flight'])) {

                //check data changed while edit form submit
                if (!empty($json['plan_id'])) {
                    if (isFlightTripDataChanged($this->flightTripsModel, $planId,  $json['flight'])) {
                        $sendMailForEdit = true;
                    }
                }

                $this->saveFlights($json['flight'], $planId);
            }


            if (!empty($json['accomodation'])) {

                //check data changed while edit form submit
                if (!empty($json['plan_id'])) {
                    if (isDataChanged($this->accomodationModel, $planId,  $json['accomodation'])) {
                        $sendMailForEdit = true;
                    }
                }

                $this->saveAccomodations($json['accomodation'], $planId);
            }

            
            if (!empty($json['bus'])) {

                //check data changed while edit form submit
                if (!empty($json['plan_id'])) {
                    if (isDataChanged($this->busModel, $planId,  $json['bus'])) {
                        $sendMailForEdit = true;
                    }
                }

                $this->saveBuses($json['bus'], $planId);
            }


            if (!empty($json['insurance'])) {

                $this->saveInsurance($json['insurance'], $planId);
            }


            if (!empty($json['miscellaneous'])) {

                $this->saveMiscellaneous($json['miscellaneous'], $planId);
            }


            if (!empty($json['taxi'])) {

                //check data changed while edit form submit
                if (!empty($json['plan_id'])) {
                    if (isDataChanged($this->taxiModel, $planId,  $json['taxi'])) {
                        $sendMailForEdit = true;
                    }
                }

                $this->saveTaxi($json['taxi'], $planId);
            }


            if (!empty($json['train'])) {

                //check data changed while edit form submit
                if (!empty($json['plan_id'])) {
                    if (isDataChanged($this->trainModel, $planId,  $json['train'])) {
                        $sendMailForEdit = true;
                    }
                }

                $this->saveTrain($json['train'], $planId);
            }


            if (!empty($json['visa'])) {

                //check data changed while edit form submit
                if (!empty($json['plan_id'])) {
                    if (isDataChanged($this->visaModel, $planId,  $json['visa'])) {
                        $sendMailForEdit = true;
                    }
                }

                $this->saveVisa($json['visa'], $planId);
            }


            if (!empty($json['forex'])) {

                //check data changed while edit form submit
                if (!empty($json['plan_id'])) {
                    if (isDataChanged($this->forexModel, $planId,  $json['forex'])) {
                        $sendMailForEdit = true;
                    }
                }

                $this->saveForex($json['forex'], $planId);
            }


            //status handler
            palnStatusHandler($planId , $sendMailForEdit);

            //update plan status if all action null
            updatePlanStatus($planId,$updatedBy);

            //generate pdf for creation and every updation on the plan
            $this->generatePlanPdf($planId,false);

            //send creation mail
            if (empty($json['plan_id'])) {
                sendPlanCreationMail($planId);
            }

            //send updation mail
            if (!empty($json['plan_id']) && $sendMailForEdit == true) {
                sendPlanUpdationMail($planId);
            }

            // Send mail to agent if plan status is 3
            $plan = $this->planModel->where('plan_id', $planId)->where('status', 3)->first();
            if ($plan) {
                send_email_agent(env('ORG_id'), $planId);
            }

            return $this->respond(['status' => 'success', 'plan_id' => $planId]);

        } catch (\Exception $e) {

            // Log detailed error
            log_message('error', sprintf("%s Exception caught in %s (line %d): %s\nTrace:\n%s",
                'createOrUpdatePlan - ',
                $e->getFile(),
                $e->getLine(),
                $e->getMessage(),
                $e->getTraceAsString()
            ));

            return $this->failServerError('Failed to create : ' . $e->getMessage());
        }
    }

    private function saveFlights($flights, $planId)
    {

        foreach ($flights as $flight) {
            $flight['plan_id'] = $planId;

            if (!empty($flight['flight_id'])) {
                $existingFlight = $this->flightModel->find($flight['flight_id']);
                if ($existingFlight) {
                    $this->flightModel->update($flight['flight_id'], $flight);
                    $flightId = $flight['flight_id'];
                }
            } else {
                $flightId = $this->flightModel->insert($flight, true);
            }

            if (!empty($flight['trips'])) {
                foreach ($flight['trips'] as $trip) {
                    $trip['flight_id'] = $flightId;
                    $trip['date'] = normalize_date($trip['date']);

                
                    if (!empty($trip['flight_trip_id'])) {
                        $existingTrip = $this->flightTripsModel->find($trip['flight_trip_id']);
                        if ($existingTrip) {
                            $this->flightTripsModel->update($trip['flight_trip_id'], $trip);
                        }
                    } else {
                        $this->flightTripsModel->insert($trip);
                    }
                }
            }
        }
    }

    private function saveAccomodations($accomodations, $planId)
    {
        
        foreach ($accomodations as $data) {
            $data['plan_id'] = $planId;
            $data['checkin_date'] = normalize_date($data['checkin_date']);
            $data['checkout_date'] = normalize_date($data['checkout_date']);
            if (!empty($data['accomodation_id'])) {
                $this->accomodationModel->update($data['accomodation_id'], $data);
            } else {
                $this->accomodationModel->insert($data);
            }
        }
    }

    private function saveBuses($buses, $planId)
    {
        
        foreach ($buses as $data) {
            $data['plan_id'] = $planId;
            $data['date'] = normalize_date($data['date']);
            if (!empty($data['bus_id'])) {
                $this->busModel->update($data['bus_id'], $data);
            } else {
                $this->busModel->insert($data);
            }
        }
    }

    private function saveInsurance($insurance, $planId)
    {
       
        foreach ($insurance as $data) {
            $data['plan_id'] = $planId;
            $data['start_date'] = normalize_date($data['start_date']);
            $data['end_date'] = normalize_date($data['end_date']);
            $data['nominee_dob'] = normalize_date($data['nominee_dob']);
            if (!empty($data['insurance_id'])) {
                $this->insuranceModel->update($data['insurance_id'], $data);
            } else {
                $this->insuranceModel->insert($data);
            }
        }
    }

    private function saveMiscellaneous($miscellaneous, $planId)
    {
        
        foreach ($miscellaneous as $data) {
            $data['plan_id'] = $planId;
            if (!empty($data['miscellaneous_id'])) {
                $this->miscellaneousModel->update($data['miscellaneous_id'], $data);
            } else {
                $this->miscellaneousModel->insert($data);
            }
        }
    }

    private function saveTaxi($taxis, $planId)
    {
        
        foreach ($taxis as $data) {
            $data['plan_id'] = $planId;
            $data['date'] = normalize_date($data['date']);
            if (!empty($data['taxi_id'])) {
                $this->taxiModel->update($data['taxi_id'], $data);
            } else {
                $this->taxiModel->insert($data);
            }
        }
    }

    private function saveTrain($trains, $planId)
    {
        
        foreach ($trains as $data) {
            $data['plan_id'] = $planId;
            $data['date'] = normalize_date($data['date']);
            if (!empty($data['train_id'])) {
                $this->trainModel->update($data['train_id'], $data);
            } else {
                $this->trainModel->insert($data);
            }
        }
    }

    private function saveVisa($visas, $planId)
    {
        
        foreach ($visas as $data) {
            $data['plan_id'] = $planId;
            $data['start_date'] = normalize_date($data['start_date']);
            if (!empty($data['visa_id'])) {
                $this->visaModel->update($data['visa_id'], $data);
            } else {
                $this->visaModel->insert($data);
            }
        }
    }

    private function saveForex($forex, $planId)
    {
        
        foreach ($forex as $data) {
            $data['plan_id'] = $planId;
            $data['start_date'] = normalize_date($data['start_date']);
            $data['end_date'] = normalize_date($data['end_date']);
            if (!empty($data['forex_id'])) {
                $this->forexModel->update($data['forex_id'], $data);
            } else {
                $this->forexModel->insert($data);
            }
        }
    }

   
    public function getForexPerdiem()
    {
        try {

        $json = $this->request->getJSON(true);

        $country_code =  $json['country_code'];
        $start_date =  $json['start_date'];
        $end_date =  $json['end_date'];
        $user_id = $json['user_id'];

        $forexCardNo = $this->userModel->where('user_id',$user_id)->get()->getRow()->forex_pre_paid_card_number;

        // Convert to DateTime objects
        $start = \DateTime::createFromFormat('d-m-Y', $start_date);
        $end = \DateTime::createFromFormat('d-m-Y', $end_date);

        // Calculate difference
        $interval = $start->diff($end);
        $duration = $interval->days; // Add 1 to include the start date

        if($duration == 0){ return $this->respond(['status' => 'failed', 'perdiem_amount' => 0 , 'currency' => '' , 'duration'=> $duration,'cash_percentage'=> 0,'card_percentage'=> 0, 'forex_card_no'=> null ]); }
        
        $forexPerdiem = $this->forexPerdiemModel->where('country_code',$country_code)->find();

        $res = 0;
        if($forexPerdiem)
        {
            $perdiem_amount =  $forexPerdiem[0]['perdiem_amount'];
            $currency = $forexPerdiem[0]['currency'];
            $card_percentage = $forexPerdiem[0]['card_percentage'];
            $cash_percentage = $forexPerdiem[0]['cash_percentage'];

            $res = $perdiem_amount * $duration;


            return $this->respond(['status' => 'success', 'perdiem_amount' => $res , 'currency' => $currency , 'duration'=> $duration, 'cash_percentage'=> $cash_percentage,'card_percentage'=> $card_percentage , 'forex_card_no'=>$forexCardNo  ]);
        }else{
            return $this->respond(['status' => 'failed', 'perdiem_amount' => 0 , 'currency' => '' , 'duration'=> $duration,'cash_percentage'=> 0,'card_percentage'=> 0, 'forex_card_no'=> null ]);
        }
        

       

        } catch (\Exception $e) {
            return $this->failServerError('Failed to create : ' . $e->getMessage());
        }
    }

    public function approvePlan()
    {
        try {

        $json = $this->request->getJSON(true);

        $plan_id =  $json['plan_id'];
        $user_id =  $json['user_id'];
        log_message('info', "Plan Approval triggered by user_id : {$user_id}, plan_id: {$plan_id}");
        $delegation_user_id =  $json['delegation_user_id'] ?? 0;

        if ((int)$delegation_user_id == 0)
        {
            $actionDoneBy = $user_id;
        } else {
            $actionDoneBy = $delegation_user_id;
        }
       
        $status = false;
        //approver 1
        $a1Data = $this->planStatusModel->where('plan_id',$plan_id)->where('a1_id',$user_id)->where('a1_action','Approval')->where('is_active',1)->findAll();
        if($a1Data){
            $this->planStatusModel->set(['is_a1_action_done'=>1,'a1_action_done_on'=>date('Y-m-d H:i:s'),'a1_reject_reason'=>null,'a1_action_done_by'=>$actionDoneBy])
                                    ->where('plan_id',$plan_id)
                                    ->where('a1_id',$user_id)
                                    ->where('a1_action','Approval')
                                    ->where('is_active',1)
                                    ->update();
            $status = true;
        }

        //approver 2
        $a2Data = $this->planStatusModel->where('plan_id',$plan_id)->where('a2_id',$user_id)->where('a2_action','Approval')->where('is_active',1)->findAll();
        if($a2Data){
            $this->planStatusModel->set(['is_a2_action_done'=>1,'a2_action_done_on'=>date('Y-m-d H:i:s'),'a2_reject_reason'=>null,'a2_action_done_by'=>$actionDoneBy])
                                    ->where('plan_id',$plan_id)
                                    ->where('a2_id',$user_id)
                                    ->where('a2_action','Approval')
                                    ->where('is_active',1)
                                    ->update();
            $status = true;
        }

        //approver 3
        $a3Data = $this->planStatusModel->where('plan_id',$plan_id)->where('a3_id',$user_id)->where('a3_action','Approval')->where('is_active',1)->findAll();
        if($a3Data){
            $this->planStatusModel->set(['is_a3_action_done'=>1,'a3_action_done_on'=>date('Y-m-d H:i:s'),'a3_reject_reason'=>null,'a3_action_done_by'=>$actionDoneBy])
                                    ->where('plan_id',$plan_id)
                                    ->where('a3_id',$user_id)
                                    ->where('a3_action','Approval')
                                    ->where('is_active',1)
                                    ->update();
            $status = true;
        }

        //approver 4
        $a4Data = $this->planStatusModel->where('plan_id',$plan_id)->where('a4_id',$user_id)->where('a4_action','Approval')->where('is_active',1)->findAll();
        if($a4Data){
            $this->planStatusModel->set(['is_a4_action_done'=>1,'a4_action_done_on'=>date('Y-m-d H:i:s'),'a4_reject_reason'=>null,'a4_action_done_by'=>$actionDoneBy])
                                    ->where('plan_id',$plan_id)
                                    ->where('a4_id',$user_id)
                                    ->where('a4_action','Approval')
                                    ->where('is_active',1)
                                    ->update();
            $status = true;
        }


        //response
        if($status)
        {
            //update plan status
            updatePlanStatus($plan_id,$user_id);

            //update pdf content
            $this->generatePlanPdf($plan_id);
            
            //send approval mail
            sendPlanApprovalOrRejectMail($plan_id,'A');
            
            //send parallel or Sequential mail
            sendPlanCreationMail($plan_id, 'send_mail_to_only_approver');

            // Send mail to agent if plan status is 3
            $plan = $this->planModel->where('plan_id', $plan_id)->where('status', 3)->first();
            if ($plan) {
                send_email_agent(env('ORG_id'), $plan_id);
            }


            return $this->respond(['status' => 200, 'message' => 'success' ]);
        }else{
            return $this->respond(['status' => 404, 'message' => 'failed' ]);
        }
       

       

        } catch (\Exception $e) {
            return $this->failServerError('Failed to create : ' . $e->getMessage());
        }
    }

    public function rejectPlan()
    {
        try {

        $json = $this->request->getJSON(true);

        $plan_id =  $json['plan_id'];
        $user_id =  $json['user_id'];
        log_message('info', "Plan Rejection triggered by user_id : {$user_id}, plan_id: {$plan_id}");
        $reason =  $json['reason'];
        $delegation_user_id =  $json['delegation_user_id'] ?? 0;

        if ($delegation_user_id == 0)
        {
            $actionDoneBy = $user_id;
        } else {
            $actionDoneBy = $delegation_user_id;
        }

        $status = false;
        //approver 1
        $a1Data = $this->planStatusModel->where('plan_id',$plan_id)->where('a1_id',$user_id)->where('a1_action','Approval')->where('is_active',1)->findAll();
        if($a1Data){
            $this->planStatusModel->set(['is_a1_action_done'=>0,'a1_reject_reason'=>$reason,'a1_action_done_on'=>date('Y-m-d H:i:s'),'a1_action_done_by'=>$actionDoneBy])
                                    ->where('plan_id',$plan_id)
                                    ->where('a1_id',$user_id)
                                    ->where('a1_action','Approval')
                                    ->where('is_active',1)
                                    ->update();
            $status = true;
        }

        //approver 2
        $a2Data = $this->planStatusModel->where('plan_id',$plan_id)->where('a2_id',$user_id)->where('a2_action','Approval')->where('is_active',1)->findAll();
        if($a2Data){
            $this->planStatusModel->set(['is_a2_action_done'=>0,'a2_reject_reason'=>$reason,'a2_action_done_on'=>date('Y-m-d H:i:s'),'a2_action_done_by'=>$actionDoneBy])
                                    ->where('plan_id',$plan_id)
                                    ->where('a2_id',$user_id)
                                    ->where('a2_action','Approval')
                                    ->where('is_active',1)
                                    ->update();
            $status = true;
        }

        //approver 3
        $a3Data = $this->planStatusModel->where('plan_id',$plan_id)->where('a3_id',$user_id)->where('a3_action','Approval')->where('is_active',1)->findAll();
        if($a3Data){
            $this->planStatusModel->set(['is_a3_action_done'=>0, 'a3_reject_reason'=>$reason, 'a3_action_done_on'=>date('Y-m-d H:i:s'),'a3_action_done_by'=>$actionDoneBy])
                                    ->where('plan_id',$plan_id)
                                    ->where('a3_id',$user_id)
                                    ->where('a3_action','Approval')
                                    ->where('is_active',1)
                                    ->update();
            $status = true;
        }

        //approver 4
        $a4Data = $this->planStatusModel->where('plan_id',$plan_id)->where('a4_id',$user_id)->where('a4_action','Approval')->where('is_active',1)->findAll();
        if($a4Data){
            $this->planStatusModel->set(['is_a4_action_done'=>0, 'a4_reject_reason'=>$reason, 'a4_action_done_on'=>date('Y-m-d H:i:s'),'a4_action_done_by'=>$actionDoneBy])
                                    ->where('plan_id',$plan_id)
                                    ->where('a4_id',$user_id)
                                    ->where('a4_action','Approval')
                                    ->where('is_active',1)
                                    ->update();
            $status = true;
        }


        //response
        if($status)
        {
            //update plan status
            $this->planModel->set(['status'=>4])->where('plan_id',$plan_id)->update();
            //update pdf content
            $this->generatePlanPdf($plan_id);
            //send reject mail
            sendPlanApprovalOrRejectMail($plan_id,'R');

            return $this->respond(['status' => 200, 'message' => 'success' ]);
        }else{
            return $this->respond(['status' => 404, 'message' => 'failed' ]);
        }
       

       

        } catch (\Exception $e) {
            return $this->failServerError('Failed to create : ' . $e->getMessage());
        }
    }

    public function getRemarksByPlanId()
    {
        $planId = $this->request->getGet('plan_id');
        $userId = $this->request->getGet('user_id');

        $this->planRemarkModel
            ->select('c_plan_remark.*, CONCAT(U.first_name, " ", U.last_name) AS created_by_name, R.value AS created_by_role')
            ->join('m_users U', 'U.user_id = c_plan_remark.created_by', 'left')
            ->join('m_role R', 'U.role_id = R.id', 'left')
            ->where('c_plan_remark.plan_id', $planId)
            ->where('c_plan_remark.is_active', 1);

        if (!empty($userId)) {
            $this->planRemarkModel->where('c_plan_remark.created_by', $userId);
        }

        $remarks = $this->planRemarkModel
            ->orderBy('c_plan_remark.created_on', 'DESC')
            ->findAll();

        if (empty($remarks)) {
            return $this->failNotFound('No remarks found for this plan.');
        }

        return $this->respond([
            'status' => 200,
            'message' => 'Remarks fetched successfully.',
            'data' => $remarks
        ]);
    }

    public function addOrEditPlanRemark()
    {
        $input = $this->request->getJSON(true);

        $data = [
            'plan_id'    => $input['plan_id'] ?? null,
            'remarks'    => $input['remarks'] ?? '',
            'is_active'    => $input['is_active'] ?? ''
        ];

        if (!isset($input['id']) || empty($input['id'])) {

            // Create new remark
            $data['created_by'] = $input['created_by'] ?? null;

            if (!$this->planRemarkModel->insert($data)) {
                return $this->failValidationErrors($this->planRemarkModel->errors());
            }

            return $this->respondCreated(['status' => 201, 'message' => 'Remark created successfully.']);
        } else {
            // Update existing remark
            $id = $input['id'];
            $data['updated_by'] = $input['updated_by'] ?? null;

            if (!$this->planRemarkModel->update($id, $data)) {
                return $this->failValidationErrors($this->planRemarkModel->errors());
            }

            return $this->respond(['status' => 200, 'message' => 'Remark updated successfully.']);
        }
    }

    public function statusDashboard()
    {
        try {

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

            $plans = $this->planModel->where('org_id', $org_id)->where('is_active', 1)->findAll();

            // Count occurrences of each status ID
            // $statusCounts = array_count_values(array_column($plans, 'status'));
            $statusValues = array_map('intval', array_filter(array_column($plans, 'status')));
            $statusCounts = array_count_values($statusValues);

            $statusResult = [];
            $statusLabels = [
                1 => 'Pending Approval',
                2 => 'Partially Approved',
                3 => 'Approved',
                4 => 'Rejected',
                5 => 'Processed',
                6 => 'Completed',
                7 => 'Cancelled'
            ];


            // Count occurrences of each type ID
            // $typeCounts = array_count_values(array_column($plans, 'trip_type'));
            $typeValues   = array_map('intval', array_filter(array_column($plans, 'trip_type')));
            $typeCounts   = array_count_values($typeValues);
            $typeResult = [];
            $typeLabels = [
                1 => 'Domestic',
                2 => 'International'
            ];

            $todayStart = date('Y-m-d 00:00:00');
            $todayEnd = date('Y-m-d 23:59:59');
            // $startOfWeek = date('Y-m-d 00:00:00', strtotime('monday this week'));
            // $endOfWeek = date('Y-m-d 23:59:59', strtotime('sunday this week'));
            $startOfWeek = date('Y-m-d 00:00:00', strtotime('-7 days'));
            $endOfWeek = date('Y-m-d 23:59:59'); // today


            $typeResultToday = [];
            $typeResultWeekly = [];

            $todayType = array_filter($plans, function ($plan) use ($todayStart, $todayEnd) {
                return $plan['created_on'] >= $todayStart && $plan['created_on'] <= $todayEnd;
            });

            // $todayTypeCounts = array_count_values(array_column($todayType, 'trip_type'));
            $todayType   = array_map('intval', array_filter(array_column($todayType, 'trip_type')));
            $todayTypeCounts   = array_count_values($todayType);

            $weeklyType = array_filter($plans, function ($plan) use ($startOfWeek, $endOfWeek) {
                return $plan['created_on'] >= $startOfWeek && $plan['created_on'] <= $endOfWeek;
            });

            // $weeklyTypeCounts = array_count_values(array_column($weeklyType, 'trip_type'));
            $weeklyType   = array_map('intval', array_filter(array_column($weeklyType, 'trip_type')));
            $weeklyTypeCounts   = array_count_values($weeklyType);

            for ($i = 1; $i <= 2; $i++) {  // Fixed loop condition
                $typeResult[] = [
                    'value' => $typeLabels[$i],
                    'count' => $typeCounts[$i] ?? 0  // Handle missing values
                ];
                $typeResultToday[] = [
                    'value' => $typeLabels[$i],
                    'count' => $todayTypeCounts[$i] ?? 0  // Handle missing values
                ];
                $typeResultWeekly[] = [
                     'value' => $typeLabels[$i],
                     'count' => $weeklyTypeCounts[$i] ?? 0  // Handle missing values
                ];
            }

            $statusResultToday = [];
            $statusResultWeekly = [];

            $todayStatus = array_filter($plans, function ($plan) use ($todayStart, $todayEnd) {
                 return $plan['created_on'] >= $todayStart && $plan['created_on'] <= $todayEnd;
            });
            $todayStatusCounts  = array_count_values(array_column($todayStatus, 'status'));

            $weeklyStatus = array_filter($plans, function ($plan) use ($startOfWeek, $endOfWeek) {
                  return $plan['created_on'] >= $startOfWeek && $plan['created_on'] <= $endOfWeek;
            });
            $weeklyStatusCounts = array_count_values(array_column($weeklyStatus, 'status'));

            for ($i = 1; $i <= 7; $i++) {  // Fixed loop condition
                  if($i == 5 || $i == 6){ continue; }
                        $statusResult[] = [
                            'value' => $statusLabels[$i],
                            'count' => $statusCounts[$i] ?? 0  // Handle missing values
                        ];
                        $statusResultToday[] = [
                             'value' => $statusLabels[$i],
                             'count' => $todayStatusCounts[$i] ?? 0  // Handle missing values
                        ];
                        $statusResultWeekly[] = [
                              'value' => $statusLabels[$i],
                              'count' => $weeklyStatusCounts[$i] ?? 0  // Handle missing values
                        ];
            }

                    $data['statusBasedCount']   = $statusResult;
                    $data['statusBasedTodayCount']  = $statusResultToday;
                    $data['statusBasedWeeklyCount']  = $statusResultWeekly;
                    $data['typeBasedCount']  = $typeResult;
                    $data['typeBasedTodayCount'] = $typeResultToday;
                    $data['typeBasedWeeklyCount'] = $typeResultWeekly;

            // === Today's Date & Week Range ===
            $today = date('Y-m-d');
            $startOfWeek = date('Y-m-d', strtotime('monday this week'));
            $endOfWeek = date('Y-m-d', strtotime('sunday this week'));

            $todayCounts = ['Domestic' => 0, 'International' => 0];
            $weekCounts = ['Domestic' => 0, 'International' => 0];

            foreach ($plans as $plan) {
                $createdAt = substr($plan['created_on'], 0, 10); // Get 'Y-m-d' part
                $type = $plan['trip_type'] == 1 ? 'Domestic' : 'International';

                if ($createdAt == $today) {
                    $todayCounts[$type]++;
                }

                if ($createdAt >= $startOfWeek && $createdAt <= $endOfWeek) {
                    $weekCounts[$type]++;
                }
            }

            $data['statusBasedCount']   = $statusResult;
            $data['typeBasedCount']     = $typeResult;
            $data['todayTripCounts']    = $this->selectedServiceDashboardDaily();
            $data['weekTripCounts']     = $this->selectedServiceDashboardWeekly();

            return $this->respond(['status' => 200, 'message' => 'success', 'data' => $data ]);

       

        } catch (\Exception $e) {
            return $this->failServerError('Failed : ' . $e->getMessage());
        }
    }

    public function downloadPlan()
    {
        $plan_id = $this->request->getGet('plan_id');

        $filePath = WRITEPATH . 'pdf/trips/trip_' . $plan_id . '.pdf';
        $filename = 'trip_' . $plan_id . '.pdf';
        if (!file_exists($filePath)) {
            return $this->failNotFound('File not found');
        }

        return $this->response->download($filePath, null)->setFileName($filename);
    }

    public function viewPlan()
    {
        $plan_id = $this->request->getGet('plan_id');

        $html = $this->generatePlanPdf($plan_id , true);

        return $this->respond(['status' => 200, 'message' => 'success', 'data' => $html ]);
    }


    public function getTripStartDate($array,$trip_start_date)
    {
        if(count($array) == 0) { return $trip_start_date; }
        foreach ($array as $val) {
            if ($val['date'] < $trip_start_date) {
                $trip_start_date = $val['date'];
            }
        }

        return $trip_start_date;
    }


    public function generatePlanPdf($planId = null , $view = false)
    {
        

        // Fetch the plan
        $plan = $this->planModel->select(  'm_plan.*,
                                            CONCAT_WS(U.first_name," ",U.last_name) as user_name,
                                            U.employee_code,U.passport_number,U.date_of_expiry,U.place_of_issue,U.forex_pre_paid_card_number,
                                            CONCAT_WS(C.first_name," ",C.last_name) as plan_created_by,
                                            CONCAT_WS(T.first_name," ",T.last_name) as traveller_name,
                                            TS.status_value,
                                            TT.dropdown_value as trip_type_value, 
                                            IB.dropdown_value as is_billable_value, 
                                            POT.dropdown_value as purpose_of_travel_value,
                                            FD.dropdown_value as functional_department_value,
                                            CC.name as cost_center_value,ORG.logo',
                                            // Dep.name as cost_center_value' // old. don't why dep name used.
                                        )
                                    ->join('m_users U', 'U.user_id = m_plan.user_id ', 'left')
                                    ->join('m_users C', 'C.user_id = m_plan.created_by ', 'left')
                                    ->join('m_traveller T', 'T.traveller_id = m_plan.traveller_id ', 'left')
                                    ->join('m_travel_statuses TS', 'TS.id = m_plan.status ', 'left')
                                    ->join('m_dropdown TT', 'TT.dropdown_key = m_plan.trip_type AND TT.dropdown = "plan_trip_type"', 'left')
                                    ->join('m_dropdown IB', 'IB.dropdown_key = m_plan.is_billable AND IB.dropdown = "plan_is_billable"', 'left')
                                    ->join('m_dropdown POT', 'POT.dropdown_key = m_plan.purpose_of_travel AND POT.dropdown = "plan_purpose_of_travel"', 'left')
                                    ->join('m_dropdown FD', 'FD.dropdown_key = m_plan.functional_department AND FD.dropdown = "plan_functional_department"', 'left')
                                    ->join('m_department Dep', 'Dep.department_id = m_plan.cost_center_id ', 'left')
                                    ->join('m_cost_center CC', 'CC.cost_center_id = m_plan.cost_center_id ', 'left')
                                    ->join('m_organization ORG', 'ORG.org_id = m_plan.org_id ', 'left')
                                    ->where('m_plan.is_active', 1)
                                    ->find($planId);

        $userId = isset($plan['traveller_id']) && !empty($plan['traveller_id']) ? $plan['created_by'] : $plan['user_id'];
        // $orgId = !empty($plan) ? $plan['org_id'] : "";
        $orgLogo = !empty($plan) ? $plan['logo'] : "";
        $tripType = $plan['trip_type'];

        $plan['allowed_class'] = getAllowedClassForUser($tripType,$userId); 
        $plan['trip_start_date'] = '9999-12-31';
        if ($plan) {
            
            //get flight details
            $flights = $this->flightModel->where('plan_id', $planId)->where('is_active', 1)->findAll();
            foreach ($flights as &$flight) {
                $flight['trips'] = $this->flightTripsModel->select('cc_flight_trips.* ,FC.dropdown_value as flight_class , FP.Airport as from_place_name , TP.Airport as to_place_name ')
                                                            ->join('m_dropdown FC', 'FC.dropdown_key = cc_flight_trips.class AND FC.dropdown = "flight_class"', 'left')
                                                            ->join('Airport_Code_State FP', 'FP.Code = cc_flight_trips.from_place', 'left')
                                                            ->join('Airport_Code_State TP', 'TP.Code = cc_flight_trips.to_place', 'left')
                                                            ->where('cc_flight_trips.flight_id', $flight['flight_id'])
                                                            ->where('cc_flight_trips.is_active', 1)
                                                            ->findAll();
                $plan['trip_start_date'] = $this->getTripStartDate($flight['trips'],$plan['trip_start_date']);

            }
            $plan['flight'] = $flights;

            //get accomodation details
            $plan['accomodation'] = $this->accomodationModel->select('c_accomodation.*, C.dropdown_value as hotel_class')
                                                            ->join('m_dropdown C', 'C.dropdown_key = c_accomodation.class AND C.dropdown = "hotel_class"', 'left')
                                                            ->where('c_accomodation.plan_id', $planId)
                                                            ->where('c_accomodation.is_active', 1)->findAll();

            //get bus details
            $plan['bus'] = $this->busModel->where('plan_id', $planId)->where('is_active', 1)->findAll();
            $plan['trip_start_date'] = $this->getTripStartDate($plan['bus'],$plan['trip_start_date']);

            //get insurance details
            $plan['insurance'] = $this->insuranceModel->select('c_insurance.* ,IT.dropdown_value as type_of_insurance_value ')
                                                        ->join('m_dropdown IT', 'IT.dropdown_key = c_insurance.type_of_insurance AND IT.dropdown = "insurance_type_of_insurance"', 'left')
                                                        ->where('c_insurance.plan_id', $planId)->where('c_insurance.is_active', 1)->findAll();

            //get miscellaneous details
            $plan['miscellaneous'] = $this->miscellaneousModel->select('c_miscellaneous.* ,SR.dropdown_value as special_request_value ')
                                                                ->join('m_dropdown SR', 'SR.dropdown_key = c_miscellaneous.special_request AND SR.dropdown = "miscellaneous_special_request"', 'left')
                                                                ->where('c_miscellaneous.plan_id', $planId)->where('c_miscellaneous.is_active', 1)->findAll();

            //get taxi details
            $plan['taxi'] = $this->taxiModel->select('c_taxi.* ,CT.dropdown_value as car_type_value,CRF.dropdown_value as car_required_for_value ')
                                            ->join('m_dropdown CT', 'CT.dropdown_key = c_taxi.car_type AND CT.dropdown = "taxt_car_type"', 'left')
                                            ->join('m_dropdown CRF', 'CRF.dropdown_key = c_taxi.car_required_for AND CRF.dropdown = "taxi_car_required_for"', 'left')
                                            ->where('c_taxi.plan_id', $planId)->where('c_taxi.is_active', 1)
                                            ->findAll();
            $plan['trip_start_date'] = $this->getTripStartDate($plan['taxi'],$plan['trip_start_date']);

            //get train details
            $plan['train'] = $this->trainModel->select('c_train.* ,TC.dropdown_value as train_class, FS.Station_Name as from_station,  TS.Station_Name as to_station')
                                                ->join('m_dropdown TC', 'TC.dropdown_key = c_train.class AND TC.dropdown = "train_class"', 'left')
                                                ->join('Train_Stations FS', 'FS.Station_Code = c_train.from_station', 'left')
                                                ->join('Train_Stations TS', 'TS.Station_Code = c_train.to_station', 'left')
                                                ->where('c_train.plan_id', $planId)->where('c_train.is_active', 1)
                                                ->findAll();
            $plan['trip_start_date'] = $this->getTripStartDate($plan['train'],$plan['trip_start_date']);

        
            //get visa details
            $plan['visa'] = $this->visaModel->select('c_visa.* ,VT.dropdown_value as visa_type_value , C.country_name ')
                                            ->join('m_dropdown VT', 'VT.dropdown_key = c_visa.type_of_visa AND VT.dropdown = "visa_type_of_visa"', 'left')
                                            ->join('m_country C', 'C.country_code = c_visa.country_code', 'left')
                                            ->where('c_visa.plan_id', $planId)->where('c_visa.is_active', 1)->findAll();

            //get visa details
            $plan['forex'] = $this->forexModel->select('c_forex.* ,C.country_name ')
                                                ->join('m_country C', 'C.country_code = c_forex.country_code', 'left')
                                                ->where('c_forex.plan_id', $planId)->where('c_forex.is_active', 1)
                                                ->findAll();
           
            //get org details
            $plan['org_data'] = $this->organizationModel->where('org_id', $plan['org_id'])->where('is_active', 1)->first();

            $plan['visa_data'] = $this->userVisaDetailsModel->select('c_user_visa_details.valid_from ,c_user_visa_details.valid_upto ,C.country_name ,VT.dropdown_value as visa_type_value')
                                                            ->join('m_country C', 'C.country_code = c_user_visa_details.country_code', 'left')
                                                            ->join('m_dropdown VT', 'VT.dropdown_key = c_user_visa_details.visa_type_id AND VT.dropdown = "visa_type_of_visa"', 'left')
                                                            ->where('c_user_visa_details.user_id', $plan['user_id'])
                                                            ->where('c_user_visa_details.is_active', 1)
                                                            ->where('c_user_visa_details.valid_from <=',  date('Y-m-d'))
                                                            ->where('c_user_visa_details.valid_upto >=',  date('Y-m-d'))
                                                            ->findAll();

            $userId = !empty($plan['user_id']) ? $plan['user_id'] : $plan['traveller_id'];


             //current plan status
            $status = getCurrentPlanStatus($planId);

            $plan['status_details'] =  $status;

            //get user data
            if($plan['user_id'] != 0){
                $plan['user_data'] = $this->userModel->where('user_id', $userId)->first();
            }else{
                $plan['user_data'] = $this->travellerModel->select('first_name,last_name,email,mobile as mobile_no')->where('traveller_id', $userId)->first();
            }

            // dd($plan['user_data']);
            
            $plan['view'] = $view;
            $data['data'] = $plan;
            // dd($data);
            // echo view('pdf', $data); die;
            $html = view('pdf', $data); 

            if($view == true){ return $html; }

            // Load mPDF
            $mpdf = new \Mpdf\Mpdf([
                'tempDir' => WRITEPATH . 'mpdf-temp', 
                'mode' => 'utf-8', 
                'format' => 'A4', 
                'margin_left' => 5, 
                'margin_right' => 5, 
                'margin_top' => 30,
                'margin_bottom' => 15 
            ]);
            $mpdf->WriteHTML($html);

            // Output PDF to a temp file
            $filePath = WRITEPATH . 'pdf/trips/trip_' . $planId . '.pdf';

            if (file_exists($filePath)) 
            {
                unlink($filePath);
            }else{ 
                $this->planModel->set(['pdf_file_path'=>$filePath])->where('plan_id',$planId)->update(); 
            }
            $mpdf->Output($filePath, \Mpdf\Output\Destination::FILE);

            return $filePath;
           

        }else{
            return $this->respond(['status' => 200,'message' => 'failed','data' => []]);
        }

        
    }


    public function forexDownload()
    {

        $forexId = $this->request->getGet('forex_id');
        $userId =  $this->request->getGet('user_id');


        $data['forexData'] = $this->forexModel->select('c_forex.* ,
                                                        C.country_name ,
                                                        P.org_id,P.created_on as date,
                                                        U.first_name,U.last_name,U.mobile_no,U.email,U.address,U.passport_number,U.place_of_issue,U.date_of_issue,U.date_of_expiry,
                                                        POT.dropdown_value as purpose_of_visit,  
                                                    ')
                                            ->join('m_country C', 'C.country_code = c_forex.country_code', 'left')
                                            ->join('m_plan P', 'P.plan_id = c_forex.plan_id', 'left')
                                            ->join('m_users U', 'U.user_id = P.user_id ', 'left')
                                            ->join('m_dropdown POT', 'POT.dropdown_key = P.purpose_of_travel AND POT.dropdown = "plan_purpose_of_travel"', 'left')
                                            ->where('c_forex.forex_id', $forexId)->where('c_forex.is_active', 1)
                                            ->first();
        $data['org_data'] = $this->organizationModel->where('org_id', $data['forexData']['org_id'])->where('is_active', 1)->first();
        $templateData = $this->mailTemplateModel->where('org_id',  $data['forexData']['org_id'] )->where('template_name', 'forex' )->first();


        //placeholder data 
        $logoFilename = basename($data['org_data']['logo']);
        $logo = base_url("assets/images/logo/" . $logoFilename);
        $data['forexData']['org_logo'] = '<img src="' . $logo . '" alt="org_logo" style="max-width:100px; max-height:100px;">';
        $data['forexData']['org_name'] = $data['org_data']['name'];
        $data['forexData']['forex_card_number'] = $data['forexData']['card_number'];
        $data['forexData']['passport_place_of_issue'] = $data['forexData']['place_of_issue'];
        $data['forexData']['passport_date_of_issue'] = $data['forexData']['date_of_issue'];
        $data['forexData']['passport_date_of_expiry'] = $data['forexData']['date_of_expiry'];
        $data['forexData']['purpose_of_visit'] = $data['forexData']['purpose_of_visit'];
        $data['forexData']['place_of_visit'] = $data['forexData']['country_name'];
        $data['forexData']['staying_duration'] = $data['forexData']['duration'];
        $data['forexData']['total_forex_exchange_amount'] = $data['forexData']['perdiem_amount'] + $data['forexData']['transport'] + $data['forexData']['accommodation'] + $data['forexData']['telephone'];
        $signatuteFileName = basename($templateData['image_location']); 
        $imageUrl = base_url('public/assets/images/signature/' . $signatuteFileName);
        $data['forexData']['signature_image'] = '<img src="' . $imageUrl . '" alt="Signature" style="max-width:250px;">';

        //replace the placeholder
        foreach ($data['forexData'] as $key => $value) {
            $placeHolder = '%'.$key.'%';
            $templateData['body_html'] = str_replace($placeHolder, $value ?? '', $templateData['body_html']);
        }
        $html =  $templateData['body_html'];

        // echo $html; die;
        
        // $html =  view('forex',$data);

        // Load mPDF
        $mpdf = new \Mpdf\Mpdf([
            'tempDir' => WRITEPATH . 'mpdf-temp', 
            'mode' => 'utf-8', 
            'format' => 'A4', 
            'margin_left' => 5, 
            'margin_right' => 5, 
            'margin_top' => 30,
            'margin_bottom' => 15 
        ]);
        $mpdf->WriteHTML($html);

        // Output PDF to a temp file
        $filePath = WRITEPATH . 'pdf/forex/forex_' . $data['forexData']['plan_id'] . '.pdf';

        if (file_exists($filePath)) {
            unlink($filePath);
        }

        $mpdf->Output($filePath, \Mpdf\Output\Destination::FILE);

       
        $filename = 'forex_' . $data['forexData']['plan_id'] . '.pdf';
        if (!file_exists($filePath)) {
            return $this->failNotFound('File not found');
        }
    
        return $this->response->download($filePath, null)->setFileName($filename);
        
        // $templateData = $this->mailTemplateModel->where('org_id', 1 )->where('template_name', 'forex' )->first();
        // echo $templateData['body_html'];die;
        
           
              
          
    }


    public function protectedPage()
    {
        $plan_id = $this->request->getVar('plan_id');
        $plan = $this->planModel->where('MD5(plan_id)', $plan_id)->first();
        $planId =  $plan['plan_id']; 
        $delegation_user_id = $this->request->getVar('delegation_user_id') ?? null;
        
        $data['html'] =  $this->generatePlanPdf((int)$planId, true);
        $data['plan_id'] = $planId;
        $data['user_id'] = $this->request->getVar('user_id');
        $data['delegation_user_id'] = $delegation_user_id;
        $data['status'] = getApproverCurrentAction( $data['plan_id'], $data['user_id'] );

        echo view('protected_page',$data);
    }


    public function canclePlan()
    {
        $plan_id = $this->request->getGet('plan_id') ?? null;
        $updated_by = $this->request->getGet('updated_by') ?? null;
        log_message('error', "Recived plan_id: {$plan_id} in update()");


        if(empty($plan_id)){
            log_message('error', 'Plan ID missing or empty');
            return $this->failNotFound('Plan ID is required');
        }

        $return = $this->planModel->where('plan_id', $plan_id)->set(['status' => 7,'updated_by'=>$updated_by])->update();

        if($return){

            log_message('error', "Plan status updated successfully for plan_id: {$plan_id} in update()");
            return $this->respond([
                'status'  => 200,
                'message' => 'Plan status updated successfully',
                'data'    => ['plan_id' => $plan_id]
            ]);

        }else{
             log_message('error', "Failed to update plan status for plan_id: {$plan_id} in update()");
            return $this->respond([
                'status'  => 200,
                'message' => 'Failed to updated plan status',
                'data'    => ['plan_id' => $plan_id]
            ]);
        }
    } 

    public function get_plan_approval_status()
    {
        $plan_id = $this->request->getGet('plan_id') ?? null;


        $planData = $this->planModel->where('plan_id', $plan_id)->first();

        $data['model_heading'] = 'Trip ID - '.$planData['plan_id'].', Trip Title - '.$planData['trip_title'];  
      
        //get plan status and it's approver 
        $data['approver_data'] = getCurrentPlanStatus($plan_id);    

        return $this->respond(['status' => 200, 'message' => 'success', 'data' => $data ]);
 
    } 

    public function url()
    {

       
        // echo '<pre>';
        // $user = $this->userModel->where('email', 'pavithrakavi1100@gmail.com')->first();
        // echo getUserPlanCreationRestrictionStatus($user); die;
        // print_r(getPlanApproverAction(126)); die;

        return $this->generatePlanPdf(223, true);
        die;

        // updatePlanStatus(57); die;
        palnStatusHandler(57, false); die;

       
        echo '<pre>';
        // sendPlanCreationMail(39);
        

        // echo '<pre>';
        // print_r(getAllowedClassForUser(2,4)['hotel']); die;

        

        return send_email_agent(env('ORG_id') , 62);
        // return updatePlanStatus(62);

    }


    // faf stands for flight accomodation and forex
    public function selectedServiceDashboardWeekly(){

        $flightResult       = $this->reportsModel->flightServiceDashboardWeekly();

        $accomodationResult = $this->reportsModel->accomodationServiceDashboardWeekly();

        $forexResult        = $this->reportsModel->forexServiceDashboardWeekly();

        $result = [

            "flight"             => $flightResult ,
            "acomodation"        => $accomodationResult ,
            "forex"              => $forexResult

        ];

        return $result = $this->splitResultbasedOnTripType($result);
    }

    public function selectedServiceDashboardDaily(){

        $flightResult       = $this->reportsModel->flightServiceDashboardDaily();

        $accomodationResult = $this->reportsModel->accomodationServiceDashboardDaily();

        $forexResult        = $this->reportsModel->forexServiceDashboardDaily();

        $result = [

            "flight"             => $flightResult ,
            "acomodation"        => $accomodationResult ,
            "forex"              => $forexResult

        ];

        return $result = $this->splitResultbasedOnTripType($result);

    }


    public function splitResultBasedOnTripType(array $result): array
    {
        $finalResult = [];

        $trip_types = ['International', 'Domestic'];
        $statuses   = ['Pending Approval', 'Partially Approved', 'Approved', 'Rejected', 'Cancelled'];

        foreach ($result as $service => $entries) {
            $resultSet = [] ;
            foreach ($trip_types as $trip_type) {
                foreach ($statuses as $status) {
                    $resultSet[$service][$trip_type][$status] = 0;
                }
            }

            foreach ($entries as $entry) {
                $tripType = $entry['trip_type'];
                $status   = $entry['Status'];
                $count    = (int) $entry['count'];

                $resultSet[$service][$tripType][$status] += $count;
            }

            foreach ($statuses as $status) {
                $resultSet[$service]['Both'][$status] =
                    $resultSet[$service]['International'][$status] +
                    $resultSet[$service]['Domestic'][$status];
            }

            $finalResult [] = $resultSet;
        }

        return $finalResult;
    }


    public function plan_policy_action_status($plan_id, $internal = false)
    {
        $plan_id = $this->request->getGet('plan_id') ?? $plan_id;

        $planData = $this->planStatusModel->select('c_plan_status.* ,CONCAT_WS(a1.first_name," ",a1.last_name) as a1_user_name,CONCAT_WS(a2.first_name," ",a2.last_name) as a2_user_name,CONCAT_WS(a3.first_name," ",a3.last_name) as a3_user_name,CONCAT_WS(a4.first_name," ",a4.last_name) as a4_user_name')
        ->join('m_users a1', 'a1.user_id = c_plan_status.a1_id ', 'left')
        ->join('m_users a2', 'a2.user_id = c_plan_status.a2_id ', 'left')
        ->join('m_users a3', 'a3.user_id = c_plan_status.a3_id ', 'left')
        ->join('m_users a4', 'a4.user_id = c_plan_status.a4_id ', 'left')
        ->where('c_plan_status.plan_id', $plan_id)
        ->where('c_plan_status.is_active', 1)
        ->first();

        $data = [];

        if($planData){

            $a1 = [
                    "action" => $planData['a1_action'],
                    "approver" => $planData['a1_user_name'],
                    "is_action_done" => $planData['is_a1_action_done'] == 1 ? 'Done' : 'Not Done',
                    "action_on" => $planData['is_a1_action_done'] == 1 ? $planData['a1_action_done_on'] : '-',
                    "email_status" => $planData['is_a1_mail_send'] == 1 ? 'Success' : 'Not Send'
                  ];
            if($planData['a1_action'] != 'None'){ array_push($data, $a1); }

            $a2 = [
                "action" => $planData['a2_action'],
                "approver" => $planData['a2_user_name'],
                "is_action_done" => $planData['is_a2_action_done'] == 1 ? 'Done' : 'Not Done',
                "action_on" => $planData['is_a2_action_done'] == 1 ? $planData['a2_action_done_on'] : '-',
                "email_status" => $planData['is_a2_mail_send'] == 1 ? 'Success' : 'Not Send'
              ];
            if($planData['a2_action'] != 'None'){ array_push($data, $a2); }

            $a3 = [
                "action" => $planData['a3_action'],
                "approver" => $planData['a3_user_name'],
                "is_action_done" => $planData['is_a3_action_done'] == 1 ? 'Done' : 'Not Done',
                "action_on" => $planData['is_a3_action_done'] == 1 ? $planData['a3_action_done_on'] : '-',
                "email_status" => $planData['is_a3_mail_send'] == 1 ? 'Success' : 'Not Send'
            ];
            if($planData['a3_action'] != 'None'){ array_push($data, $a3); }

            $a4 = [
                "action" => $planData['a4_action'],
                "approver" => $planData['a4_user_name'],
                "is_action_done" => $planData['is_a4_action_done'] == 1 ? 'Done' : 'Not Done',
                "action_on" => $planData['is_a4_action_done'] == 1 ? $planData['a4_action_done_on'] : '-',
                "email_status" => $planData['is_a4_mail_send'] == 1 ? 'Success' : 'Not Send'
            ];
            if($planData['a4_action'] != 'None'){ array_push($data, $a4); }

        }

       
        // If internal call → return raw data
        if ($internal) {
            return $data;
        }

        // If API/browser call → return JSON response
        return $this->respond(['status' => 200, 'message' => 'success', 'data' => $data ]);
 
    } 


    public function planInfo()
    {
        $plan_id = $this->request->getGet('plan_id');

        $planData = $this->find($plan_id, 'internal');
        if (!$planData) {
            log_message('error', "No plan data found for plan_id: {$plan_id}");
            return false;
        }

        // $userId = $planData['user_id'] ?? $planData['traveller_id'];
        $userId = !empty($planData['user_id']) ? $planData['user_id'] : $planData['created_by'];
        $userData = $this->userModel->where('user_id', $userId)->first();
        if (!$userData) {
            log_message('error', "User data not found for user_id: {$userId}");
            return false;
        }

        

        $planStatusData = $this->planStatusModel->where('plan_id', $plan_id)->where('is_active', 1)->first();

        $groupId = $planStatusData['group_id'];
        $groupData = $this->groupModel->where('group_id', $groupId)->first();
        if (!$groupData) {
            log_message('error', "Group data not found for group_id: {$groupId}");
            return false;
        }


        $result['traveller'] = $userData['first_name'].' '.$userData['last_name'];
        $result['group_name'] = $groupData['name'];
        $result['allowed_plan_type'] = getUserPlanCreationRestrictionStatus($userData);
        $result['policy_type'] = $planStatusData['policy_action'];
        switch ($planStatusData['parallel_process_from']) {
            case 1:
                $result['policy_action_flow'] = "A1, A2, A3, A4 all run in parallel";
                break;
            case 2:
                $result['policy_action_flow'] = "A1 → (A2, A3, A4) all run in parallel after A1 is done";
                break;
            case 3:
                $result['policy_action_flow'] = "A1 → A2 (sequential), then A3 and A4 run parallel after A1 and A2 are done";
                break;
            case 4:
                $result['policy_action_flow'] = "A1 → A2 → A3 (sequential), then A4 runs after A3 is done";
                break;
            default:
                $result['policy_action_flow'] = "Unknown flow";
        }
        $result['approval_criteria'] = $this->plan_policy_action_status($plan_id,true);

        return $this->respond([ 'status' => 200, 'message' => 'success', 'data' => $result ]);
       

    }






}
