<?php

use App\Models\OrganizationModel;
use App\Models\UserModel;
use App\Models\GroupModel;
use App\Models\PolicyModel;
use App\Models\PolicyDetailsModel;
use App\Models\ServiceModel;
use App\Models\PlanStatusModel;
use App\Models\PlanModel;

if (!function_exists('getUserByEmail')) {
    function getUserByEmail($email)
    {
        $userModel = new UserModel();
        $user = $userModel->where('email', $email)->first();

        return $user ? $user : false;
    }
}

if (!function_exists('checkUserExist')) {
    function checkUserExist($first_name, $email)
    {
        $userModel = new UserModel();

        // Check if email already exists
        $user = $userModel->where('email', $email)->first();
        if ($user) {
            return ['status' => true,'data' => $user ,'message' => 'User already exists'];
        }

        // Insert new user
        $userId = $userModel->insert([
            'first_name' => $first_name,
            'email' => $email,
            'org_id' => env('ORG_id')
        ]);

        if($userId){
            $user = $userModel->where('user_id', $userId)->first();
            return ['status' => true,'data' => $user ,'message' => 'User created successfully'];
        }else{
            return ['status' => false, 'message' => 'Something wend wrong'];
        }

       
    }
}

if (!function_exists('getUserPlanCreationRestrictionStatus')) {
    function getUserPlanCreationRestrictionStatus($user)
    {
        if($user['group_id'] != null)
        {
            $groupModel = new GroupModel();
            $groupData = $groupModel->find($user['group_id']);
            log_message('info',  sprintf("LoginToken - User has group , ID : %s | Name : %s", $groupData['group_id'] , $groupData['name'] ));
            if($groupData)
            {
                $domesticPolicyId = $groupData['domestic_policy_id'];
                $internationalPolicyId = $groupData['international_policy_id'];
                $policyDetailsModel = new PolicyDetailsModel();

                if($domesticPolicyId != null && $internationalPolicyId != null)
                {
                    $domesticPolicy = $policyDetailsModel->where('policy_id',$domesticPolicyId)->where('service_id', 1)->find();
                    $domesticCheck =  checkApproverSetOrNotBasedOnPolicy($domesticPolicy,$user);
                    $internationalPolicy = $policyDetailsModel->where('policy_id',$internationalPolicyId)->where('service_id', 1)->find();
                    $internationalCheck =  checkApproverSetOrNotBasedOnPolicy($internationalPolicy,$user);

                    log_message('info',  sprintf("LoginToken - User has domesticPolicy , ID : %s ", $domesticPolicy[0]['policy_id']  ));
                    log_message('info',  sprintf("LoginToken - User has internationalPolicy , ID : %s ", $internationalPolicy[0]['policy_id']  ));

                    if($domesticCheck == true && $internationalCheck == true)
                        return 'Both Type Plan Creation Allowed';
                    else
                        return 'Plan Creation Not Allowed'; 

                }
                else if($domesticPolicyId != null)
                {
                    $domesticPolicy = $policyDetailsModel->where('policy_id',$domesticPolicyId)->where('service_id', 1)->find();
                    $check =  checkApproverSetOrNotBasedOnPolicy($domesticPolicy,$user);
                    $internationalPolicy = $policyDetailsModel->where('policy_id',$domesticPolicyId)->where('service_id', 1)->find();
                    $check =  checkApproverSetOrNotBasedOnPolicy($internationalPolicy,$user);

                    log_message('info',  sprintf("LoginToken - User has domesticPolicy , ID : %s ", $domesticPolicy[0]['policy_id']  ));

                    if($check == true)
                        return 'Only Domestic Plan Creation Allowed';
                    else
                        return 'Plan Creation Not Allowed'; 
                    
                }
                else if($internationalPolicyId != null)
                {

                    $internationalPolicy = $policyDetailsModel->where('policy_id',$internationalPolicyId)->where('service_id', 1)->find();
                    $check = checkApproverSetOrNotBasedOnPolicy($internationalPolicy,$user);

                    log_message('info',  sprintf("LoginToken - User has internationalPolicy , ID : %s ", $internationalPolicy[0]['policy_id']  ));

                    if($check == true)
                        return 'Only International Plan Creation Allowed';
                    else
                        return 'Plan Creation Not Allowed'; 
                   
                }
   

            }else{ 
                return 'Plan Creation Not Allowed'; 
            }

        }else{ 
            return 'Plan Creation Not Allowed';
         }

       
    }
}

function checkApproverSetOrNotBasedOnPolicy($Policy,$user)
{
    // Step 1: Determine required approver levels (a1 to a4)
    $requiredApprovers = [];

    foreach (['', '_exceptional', '_amendment'] as $type) {
        for ($i = 1; $i <= 4; $i++) {
            $key = "a{$i}{$type}_action";
            if (isset($Policy[0][$key]) && $Policy[0][$key] === 'Approval') {
                $requiredApprovers[] = $i; // add level (1 to 4)
            }
        }
    }


    // Remove duplicates (in case multiple types require same level)
    $requiredApprovers = array_unique($requiredApprovers);

    // print_r($requiredApprovers);

    // Step 2: Check user profile for each required approver level
    $missingApprovers = [];

    foreach ($requiredApprovers as $level) {
        $profileKey = match ($level) {
            1 => 'first_approver',
            2 => 'second_approver',
            3 => 'third_approver',
            4 => 'fourth_approver',
        };

        if (empty($user[$profileKey]) || $user[$profileKey] == 0) {
            $missingApprovers[] = $profileKey;
        }
    }

    // print_r($missingApprovers);

    if (count($missingApprovers)) {
        // echo "All required approvers are set in user profile.";
        log_message('info', "All required approvers are set in user profile.");
        return true;
    } else {
        // One or more approvers missing
        // echo "Missing approvers in user profile: " . implode(', ', $missingApprovers);
        log_message('info', "Missing approvers in user profile");
        return false;
        
    }

    // Step 3: Final check
    // if (!empty($missingApprovers)) {
    //     // One or more approvers missing
    //     // echo "Missing approvers in user profile: " . implode(', ', $missingApprovers);
    //     log_message('info', "Missing approvers in user profile");
    //     return false;
    // } else {
    //     // echo "All required approvers are set in user profile.";
    //     log_message('info', "All required approvers are set in user profile.");
    //     return true;
    // }

}

if (!function_exists('isDataChanged')) {
    function isDataChanged($model, $id, array $newData): bool
    {
        // Step 1: Fetch old data from the model
        $oldData = $model->where('plan_id', $id)->where('is_active', 1)->findAll();
       
        if (!$oldData) {
            return true;
        }
    
        // Step 2: Define keys to exclude
        $excludeKeys = ['created_by', 'updated_by', 'created_on', 'updated_on'];
    
        // Step 3: Clean both old and new data arrays
        $cleanOldData = array_map(function($item) use ($excludeKeys) {
            foreach ($excludeKeys as $key) {
                unset($item[$key]);
            }
            return $item;
        }, $oldData);
    
        $cleanNewData = array_map(function($item) use ($excludeKeys) {
            foreach ($excludeKeys as $key) {
                unset($item[$key]);
            }
            return $item;
        }, $newData);

    
        // Step 4: Compare count
        if (count($cleanOldData) !== count($cleanNewData)) {
            return true;
        }
    
        // Step 5: Check if there's any difference
        return $cleanOldData !== $cleanNewData;
    }
    
}

if (!function_exists('isFlightTripDataChanged')) {
    function isFlightTripDataChanged($model, $id, array $newData): bool
    {

        $newTripData = [];
        $flightIds = array_column($newData, 'flight_id');
        foreach ($newData as $key1 => $value1) {
            foreach ($value1['trips'] as $key => $value) {
                array_push($newTripData , $value);
            }
        }

        // Step 1: Fetch old data from the model
        if(!empty($flightIds))
            $oldData = $model->whereIn('flight_id', $flightIds)->where('is_active', 1)->findAll();
        else
            $oldData = [];

       
        if (!$oldData) {
            return true;
        }
    
        // Step 2: Define keys to exclude
        $excludeKeys = ['created_by', 'updated_by', 'created_on', 'updated_on'];
    
        // Step 3: Clean both old and new data arrays
        $cleanOldData = array_map(function($item) use ($excludeKeys) {
            foreach ($excludeKeys as $key) {
                unset($item[$key]);
            }
            return $item;
        }, $oldData);
    
        $cleanNewData = array_map(function($item) use ($excludeKeys) {
            foreach ($excludeKeys as $key) {
                unset($item[$key]);
            }
            return $item;
        }, $newTripData);

    
        // Step 4: Compare count
        if (count($cleanOldData) !== count($cleanNewData)) {
            return true;
        }
    
        // Step 5: Check if there's any difference
        return $cleanOldData !== $cleanNewData;
    }
    
}

function getDelegatedPlans($org_id, $id)
{
    $userModel = new UserModel();
    $planModel = new PlanModel();
    $planStatusModel = new PlanStatusModel();
    $delegatedUsers = $userModel->where('delegated_to_user_id', $id)
                                        ->where('is_active', 1)
                                        ->where('delegation_start_date <=',  date('Y-m-d'))
                                        ->where('delegation_end_date >=',  date('Y-m-d'))
                                        ->findAll();
    $allPlanData = [];
    foreach ($delegatedUsers as $user) {

        $userId = $user['user_id'];
        $startDate = $user['delegation_start_date'];
        $endDate   = $user['delegation_end_date'];

        $a1Data = $planStatusModel->select('plan_id,a1_id as user_id')
                                  ->where('a1_id',$userId)
                                  ->where('a1_action','Approval') 
                                  ->where('created_on >=', $startDate)
                                  ->where('created_on <=', $endDate)
                                  ->where('is_active',1)
                                  ->findAll();

        $a2Data = $planStatusModel->select('plan_id,a2_id as user_id')
                                  ->where('a2_id',$userId)
                                  ->where('a2_action','Approval') 
                                  ->where('created_on >=', $startDate)
                                  ->where('created_on <=', $endDate)
                                  ->where('is_active',1)
                                  ->findAll();

        $a3Data = $planStatusModel->select('plan_id,a3_id as user_id')
                                  ->where('a3_id',$userId)
                                  ->where('a3_action','Approval')
                                  ->where('is_active',1)
                                  ->where('created_on >=', $startDate)
                                  ->where('created_on <=', $endDate)
                                  ->findAll();

        $a4Data = $planStatusModel->select('plan_id,a4_id as user_id')
                                  ->where('a4_id',$userId)
                                  ->where('a4_action','Approval')
                                  ->where('is_active',1)
                                  ->where('created_on >=', $startDate)
                                  ->where('created_on <=', $endDate)
                                  ->findAll();
        
       // Merge results (each record has plan_id + user_id)
       $merged = array_merge($a1Data, $a2Data, $a3Data, $a4Data);

       // Merge into final array
       $allPlanData = array_merge($allPlanData, $merged);

    }
   
    //get already approved data in delegated flow
    // $a1 = $planStatusModel->select('plan_id,a1_id as user_id')->where('a1_action_done_by',$id)->where('a1_action','Approval')->where('is_active',1)->findAll();
    // $a2 = $planStatusModel->select('plan_id,a2_id as user_id')->where('a2_action_done_by',$id)->where('a2_action','Approval')->where('is_active',1)->findAll();
    // $a3 = $planStatusModel->select('plan_id,a3_id as user_id')->where('a3_action_done_by',$id)->where('a3_action','Approval')->where('is_active',1)->findAll();

    //need to discuss with sir
    // $mergedApprovedArray = array_merge($a1, $a2, $a3);
    $mergedApprovedArray = [];
   
    // Merge into main list
    $allPlanData = array_merge($allPlanData, $mergedApprovedArray);

    // Remove duplicate associative arrays
    $allPlanData = array_map('unserialize', array_unique(array_map('serialize', $allPlanData)));
    
    $plansWithUser = [];

    foreach ($allPlanData as $item) {
        $planId  = $item['plan_id'];
        $userId  = $item['user_id'];
        $userData = $userModel->where('user_id',$userId)->first();
        $userName = $userData['first_name'].' '.$userData['last_name'];

        $planData = $planModel->getActivePlan($org_id, 'PLAN', null , $planId); 

        if ($planData) {
            $planData['approver_id'] = $userId;
            $planData['approver_name'] = $userName;
            $planData['delegater_id'] = $id;
            $planData['approver_status'] = getApproverCurrentAction( $planData['plan_id'], $userId );
            $plansWithUser[] = $planData;
        }
    }

    return $plansWithUser;                                    

}

function normalize_date(string $date): ?string
{
    $date = trim($date);

    // If already valid Y-m-d (e.g., 2025-03-20), return it as-is
    $yFormat = DateTime::createFromFormat('Y-m-d', $date);
    if ($yFormat && $yFormat->format('Y-m-d') === $date) {
        return $date;
    }

    // Try to convert from d-m-Y (e.g., 20-03-2025)
    $dFormat = DateTime::createFromFormat('d-m-Y', $date);
    if ($dFormat) {
        return $dFormat->format('Y-m-d');
    }

    // Try from d/m/Y (optional)
    $slashFormat = DateTime::createFromFormat('d/m/Y', $date);
    if ($slashFormat) {
        return $slashFormat->format('Y-m-d');
    }

    // Unknown format
    return null;
}

if (!function_exists('format_date_for_client')) {
    /**
     * Converts a date from 'Y-m-d' to 'd-m-Y'.
     *
     * @param string $date
     * @return string|null
     */
    function format_date_for_client(string $date): ?string
    {
        $dt = DateTime::createFromFormat('Y-m-d', $date);
        if ($dt) {
            return $dt->format('d-m-Y');
        }

        return null;
    }
}

if (!function_exists('isValidUploadedFile')) {
    function isValidUploadedFile($file): bool
    {
        return $file && $file->isValid();
    }
}

if (!function_exists('isAllowedExtension')) {
    function isAllowedExtension($file, array $allowedExtensions = [] ): bool
    {
        $ext = strtolower($file->getClientExtension());

        $result = in_array($ext, $allowedExtensions);

        $result = empty($allowedExtensions) ? true : $result ;

        return $result;
    }
}

if (!function_exists('isExcelNotEmpty')) {
    function isExcelNotEmpty(array $sheetData): bool
    {
        return !empty($sheetData) && count($sheetData) >= 2;
    }
}

if(!function_exists('createDirectoryWith0777Permission')){

    function createDirectoryWith0777Permission( $uploadDir)
    {
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0777, true); // recursive creation with full permission
        }

    }

}

function getAllowedClassForUser($trip_type,$user_id)
{

    $userModel = new UserModel();
    $groupModel = new GroupModel();
    $policyDetailsModel = new PolicyDetailsModel();
    $policyDetailsModel = new PolicyDetailsModel();

    $user = $userModel->where('user_id', $user_id)->first();
    $groupData = $groupModel->find($user['group_id']);
    
    if($groupData)
    {
        if($trip_type == 1) { $policyId = $groupData['domestic_policy_id'];}else{ $policyId = $groupData['international_policy_id'];}
        if($policyId != null)
        {
            $allowedFlightClass = $policyDetailsModel->select('c_policy_details.class, m_dropdown.dropdown_value as allowed_class')
                                ->join('m_dropdown', 'dropdown_key = c_policy_details.class AND dropdown = "flight_class"', 'left')
                                    ->where('policy_id',$policyId)
                                    ->where('service_id',1)
                                    ->first();
            $data['flight'] = $allowedFlightClass['allowed_class'] ?? [];

            $allowedTrainClass = $policyDetailsModel->select('c_policy_details.class, m_dropdown.dropdown_value as allowed_class')
                                    ->join('m_dropdown', 'dropdown_key = c_policy_details.class AND dropdown = "train_class"', 'left')
                                    ->where('policy_id',$policyId)
                                    ->where('service_id',2)
                                    ->first();
            $data['train'] = $allowedTrainClass['allowed_class'] ?? [];

            $allowedHotelClass = $policyDetailsModel->select('c_policy_details.class, m_dropdown.dropdown_value as allowed_class')
                                    ->join('m_dropdown', 'dropdown_key = c_policy_details.class AND dropdown = "hotel_class"', 'left')
                                    ->where('policy_id',$policyId)
                                    ->where('service_id',5)
                                    ->first();
            $data['hotel'] = $allowedHotelClass['allowed_class'] ?? [];
        }


        return $data;

    }


    function decryptLoginPayload($payload)
    {
        $key = '1234567890123456'; // same as Flutter key
        $iv  = 'abcdefghijklmnop'; // same IV

        $cipher = 'AES-128-CBC';
        $decrypted = openssl_decrypt(base64_decode($payload), $cipher, $key, OPENSSL_RAW_DATA, $iv);

        return json_decode($decrypted);
    }
    
    

}














