<?php

namespace App\Controllers;

use CodeIgniter\RESTful\ResourceController;
use App\Models\UserModel;
use App\Models\MailTemplateModel;
use App\Models\UserFrequentFlierInformationModel;
use App\Models\UserHotelMembershipModel;
use App\Models\UserVisaDetailsModel;

use PhpOffice\PhpSpreadsheet\IOFactory;

class UserController extends ResourceController
{
    protected $format    = 'json';
    protected $myLogger;
    protected $userModel;
    protected $mailTemplateModel;
    protected $userFrequentFlierInformationModel;
    protected $userHotelMembershipModel;
    protected $userVisaDetailsModel;

    public function __construct()
    {
        $this->myLogger = \Config\Services::mylogger();
        $this->userModel = new UserModel();
        $this->mailTemplateModel = new MailTemplateModel();
        $this->userFrequentFlierInformationModel = new UserFrequentFlierInformationModel();
        $this->userHotelMembershipModel = new UserHotelMembershipModel();
        $this->userVisaDetailsModel = new UserVisaDetailsModel();
    }


    public function index()
    {
        $orgId = $this->request->getGet('org_id');
        $for = $this->request->getGet('for');
        if(isset($for)){ $active = [0,1]; }else{ $active = [1]; }

        $users = $this->userModel->getUsers($orgId,$active,[1,2,3,4]);

        if (!$users) {
            return $this->failNotFound('No users found');
        }

        return $this->respond([
            'status' => 200,
            'message' => 'Users retrieved successfully',
            'data' => $users
        ]);
    }

    public function agentList()
    {
        $orgId = $this->request->getGet('org_id');
        $for = $this->request->getGet('for');
        if(isset($for)){ $active = [0,1]; }else{ $active = [1]; }

        $users = $this->userModel->getUsers($orgId,$active,[5]);

        if (!$users) {
            return $this->failNotFound('No users found');
        }

        return $this->respond([
            'status' => 200,
            'message' => 'Users retrieved successfully',
            'data' => $users
        ]);
    }

    public function create()
    {
        $rules = [
            'first_name' => 'required',
            'email'      => 'required|valid_email|is_unique[m_users.email]',
        ];

        

        $postData = $this->request->getPost(); 

        //mailcontent data
        $mailData = [
            'first_name' => $postData['first_name'],
            'last_name'  => $postData['last_name'],
            'email'      => $postData['email'],
            'password'   => $postData['password'],
            'org_id'     => env('ORG_id'),
            'site_url'   => env('FE_URL'),
            'template'   => 'user_creation_notification',
        ];
       


        if (!$this->validate($rules)) {
            return $this->failValidationErrors($this->validator->getErrors());
        }

        // $postData = $this->request->getJSON(true); 
        $data = $this->formatUserData($postData);

        
        // Hash password before inserting into the database
        if (isset($data['password'])) {
            $data['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
        }

        $data['org_id']  = env('ORG_id');

        // Handle file upload
        $file = $this->request->getFile('passport_document');
        if ($file && $file->isValid() && !$file->hasMoved()) {
            $newName = $file->getRandomName(); // Generate a unique name
            $uploadPath = FCPATH.'assets/images/passport';
            
            // Move file to the specified directory
            $file->move($uploadPath, $newName);

            // Save file path in database
            $data['passport_document'] = $uploadPath . '/' . $newName;
        } else {
            // return $this->failValidationErrors(['passport_document' => 'Invalid file upload']);
        }

        try {
            $insert_id = $this->userModel->insert($data);
             //insert other user data ( hotal membership, visa details, frequent filler )
            $this->createOrUpdateUserOtherDetails($insert_id, $data);
            //trigger Mail
            sendUserCreationMail($mailData);
            return $this->respondCreated([
                'status'  => 201,
                'message' => 'User created successfully',
                'data'    => $postData
            ]);
        } catch (\Exception $e) {
            return $this->failServerError('Failed to create user: ' . $e->getMessage());
        }
    }

    public function find($id = null)
    {
        if (!$id) {
            return $this->failNotFound('User ID is required');
        }

        // Fetch user by ID
        $user = $this->userModel->find($id);

        if (!$user) {
            return $this->failNotFound('User not found');
        }

        $user = $this->formatUserDataForEdit($user);
        $frequentFlierInformation = $this->userFrequentFlierInformationModel->where('user_id', $id)->findAll() ?? [];
        $hotelMembership = $this->userHotelMembershipModel->where('user_id', $id)->findAll() ?? [];
        $visaDetails = $this->userVisaDetailsModel->where('user_id', $id)->findAll() ?? [];

        $user['travel_details']['frequent_flier_information'] = $frequentFlierInformation;
        $user['travel_details']['hotel_membership'] = $hotelMembership;
        $user['travel_details']['visa_details'] = $visaDetails;

        
        //formate the date to the indian date format
        $user = $this->convertDateToDBFormat($user, 'd-m-Y');



        return $this->respond([
            'status' => 200,
            'message' => 'User retrieved successfully',
            'data' => $user
        ]);
    }

    public function update($id = null)
    {
        if (!$id) {
            return $this->failNotFound('User ID is required');
        }

        $postData = $this->request->getPost(); 
        // $postData = $this->request->getJSON(true); 
        $data = $this->formatUserData($postData);

        if (empty($data)) {
            return $this->failValidationErrors('No data provided for update');
        }

        // Check if user exists
        $user = $this->userModel->find($id);
        if (!$user) {
            return $this->failNotFound('User not found');
        }

         // Handle file upload
        $file = $this->request->getFile('passport_document');
        if ($file && $file->isValid() && !$file->hasMoved()) {
            $newName = $file->getRandomName(); // Generate a unique file name
            $uploadPath = FCPATH.'assets/images/passport';
            
            // Move file to the directory
            $file->move($uploadPath, $newName);

            // Delete the old file if it exists
            if (!empty($user['passport_document']) && file_exists($user['passport_document'])) {
                unlink($user['passport_document']); // Remove old file
            }

            // Save the new file path
            $data['passport_document'] = $uploadPath . '/' . $newName;
        }

        // Update user details
        try {
            unset($data['password']);
            $this->userModel->update($id, $data);
            //update other user data ( hotal membership, visa details, frequent filler )
            $this->createOrUpdateUserOtherDetails($id, $data);
            return $this->respond([
                'status'  => 200,
                'message' => 'User updated successfully',
                'data'    => $postData
            ]);
        } catch (\Exception $e) {
            return $this->failServerError('Failed to update user: ' . $e->getMessage());
        }
    }

    public function changePassword($id = null)
    {
        if (!$id) {
            return $this->failNotFound('User ID is required');
        }

        $data = $this->request->getJSON(true);
        
        // Fetch user details
        $user = $this->userModel->find($id);
        if (!$user) {
            return $this->failNotFound('User not found');
        }

        // Hash new password
        $newPasswordHash = password_hash($data['password'], PASSWORD_DEFAULT);

        // Update password
        try {
            $this->userModel->update($id, ['password' => $newPasswordHash]);
            return $this->respond([
                'status' => 200,
                'message' => 'Password changed successfully'
            ]);
        } catch (\Exception $e) {
            return $this->failServerError('Failed to change password: ' . $e->getMessage());
        }
    }

    public function updateUserStatus($id)
    {
        // Fetch user by ID
        $user = $this->userModel->find($id);

        if (!$user) {
            return $this->failNotFound('User not found');
        }

        // Toggle the is_active status
        $newStatus = $user['is_active'] == 1 ? 0 : 1;

        // Update user status
        $this->userModel->update($id, ['is_active' => $newStatus]);

        return $this->respond([
            'status' => 200,
            'message' => $newStatus ? 'User activated successfully' : 'User deactivated successfully',
            'is_active' => $newStatus
        ]);
    }

    public function roleList()
    {
        // Fetch all roles
        $roles = db_connect()->table('m_role')->orderBy('id', 'asc')->get()->getResultArray();
    
        // Check  roles exist
        if (!$roles) {
            log_message('error', 'No roles found in roleList()');
            return $this->failNotFound('No roles found');
        }
    
        log_message('error', 'Roles retrieved successfully in roleList()');
    
        return $this->respond([
            'status'  => 200,
            'message' => 'Roles retrieved successfully',
            'data'    => $roles
        ]);
    }

    public function verifyUser()
    {
        $data = $this->request->getJSON(true);

        if (empty($data)) {
            log_message('error', "No data provided for user verification");
            return $this->failValidationErrors('No data provided for verification');
        }
        
        if (!isset($data['email']) || empty($data['email'])) {
            log_message('error', "Email is missing or empty for user verification");
            return $this->failValidationErrors('Email is required for user verification');
        }

        //featch user data for the give email
        $userData = $this->userModel->where('email', $data['email'])->first();

        if(empty($userData)){
            log_message('error', "User not found");
            return $this->failNotFound('User not found');
        }  
        
        if ($userData['is_active'] == 0) {
            log_message('error', "User found but not active");
            return $this->failNotFound('User found but not active, no further action to be made');
        }
        
        //generate random number for OTP
        $temp_password = random_int(100000, 999999);
        $userData['otp'] = $temp_password;
        log_message('error', "Generated temp password : ".$temp_password ?? "-");

        //update otp to the given email user
        $return_value = $this->userModel->where('email', $data['email'])->set('temp_password', $temp_password)->update();
        log_message('error', "Temp password updated successfully aginst the user email");

        //mail send function
        $mail_response = send_email($userData['org_id'], $data['email'], 'forgot_password_otp', $userData);
        // print_r($mail_response);
        
        $data = [
           "request_data" => $data,
           "mail_response" => $mail_response,
        ];

        return $this->respond([
            'status'  => 200,
            'message' => 'User verified successfully. Mail send to the given mail-id',
            'data' => $data,
        ]);
        
    }

    public function forgotChangePassword()
    {
        $data = $this->request->getJSON(true);

        if (empty($data)) {
            log_message('error', "No data provided for forgot change password");
            return $this->failValidationErrors('No data provided for change password');
        }
        
        if (!isset($data['email']) || empty($data['email'])) {
            log_message('error', "email is missing or empty for forgot change password");
            return $this->failValidationErrors('Email id is required for change password');
        }
        
        if (!isset($data['otp']) || empty($data['otp'])) {
            log_message('error', "Temp password is missing or empty for forgot change password");
            return $this->failValidationErrors('OTP is required for change password');
        }

        if (!isset($data['new_password']) || empty($data['new_password'])) {
            log_message('error', "New password is missing or empty for forgot change password");
            return $this->failValidationErrors('New password is required for change password');
        }

        if (!isset($data['confirm_password']) || empty($data['confirm_password'])) {
            log_message('error', "Confirm password is missing or empty for forgot change password");
            return $this->failValidationErrors('Confirm password is required for change password');
        }

        if (!isset($data['confirm_password']) || empty($data['confirm_password'])) {
            log_message('error', "Confirm password is missing or empty for forgot change password");
            return $this->failValidationErrors('Confirm password is required for change password');
        }

        //featch user data for the give email
        $userData = $this->userModel->where('email', $data['email'])->first();

        if(empty($userData)){
            log_message('error', "User not found");
            return $this->failNotFound('User not found');
        }  
        
        if ($userData['is_active'] == 0) {
            log_message('error', "User found but not active");
            return $this->failNotFound('User found but not active, no further action to be made');
        }

        if($userData['temp_password'] !== $data['otp']){
            log_message('error', "Invalid OTP");
            return $this->failValidationErrors('Invalid OTP');
        }

        if($data['new_password'] !== $data['confirm_password']){
            log_message('error', "New password as not same as the confirm password");
            return $this->failValidationErrors('New password as not same as the confirm password');
        }
        
        //construct the updated data
        $update_data = [
            'password' => password_hash($data['new_password'], PASSWORD_DEFAULT),
            'temp_password' => null
        ];

        $return_value = $this->userModel->where('user_id', $userData['user_id'])->set($update_data)->update();
        log_message('error', "Password changed successfully and Temp password reseted successfully aginst the user id");

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

    public function createOrUpdateUserOtherDetails($user_id, $data)
    {

        //insert or update frequent flier information
        if(!empty($data) && isset($data['frequent_flier_information']) && !empty($data['frequent_flier_information'])){
            foreach ($data['frequent_flier_information'] as $key => $value) {
               $value['user_id'] = $user_id;
               if(isset($value['id']) && !empty($value['id'])){
                    $this->userFrequentFlierInformationModel->update($value['id'], $value);
               }else{
                    $this->userFrequentFlierInformationModel->insert($value);
               }
            }
        }

        //insert or update hotel membership
        if(!empty($data) && isset($data['hotel_membership']) && !empty($data['hotel_membership'])){
            foreach ($data['hotel_membership'] as $key => $value) {
               $value['user_id'] = $user_id;
                if(isset($value['id']) && !empty($value['id'])){
                    $this->userHotelMembershipModel->update($value['id'], $value);
                }else{
                    $this->userHotelMembershipModel->insert($value);
                }
            }
        }

        //insert or update visa details
        if(!empty($data) && isset($data['visa_details']) && !empty($data['visa_details'])){
            foreach ($data['visa_details'] as $key => $value) {
               $value['user_id'] = $user_id;
                if(isset($value['id']) && !empty($value['id'])){
                    $this->userVisaDetailsModel->update($value['id'], $value);
                }else{
                    $this->userVisaDetailsModel->insert($value);
                }
            }
        }
        
        return true;
    }

    public function formatUserData($data)
    {
        if (empty($data)) {
            return $data;
        }

        if (isset($data['travel_details'])) {

            if (!is_array($data['travel_details'])) {
                $decoded = json_decode($data['travel_details'], true);
                if (json_last_error() === JSON_ERROR_NONE) {
                    $data['travel_details'] = $decoded;

                    //format the date to the database format
                    $data = $this->convertDateToDBFormat($data);

                } else {
                    return $data;
                }
            }

            $data = array_merge($data, $data['travel_details']);
            unset($data['travel_details']);
        }

        return $data;
    }

    public function formatUserDataForEdit($data)
    {
        if (!empty($data)) {

            $travelKeys = [
                'passport_firstname',
                'passport_middlename',
                'passport_lastname',
                'nationality',
                'passport_number',
                'place_of_issue',
                'passport_document',
                'date_of_expiry',
                'd_meal_preference',
                'd_seat_preference',
                'd_additonalInfo',
                'i_meal_preference',
                'i_seat_preference',
                'i_additonalInfo',
                'emergency_contact_number',
                'date_of_issue',
                'forex_pre_paid_card_number',
                'forex_expiry_date',
            ];

            $data['travel_details'] = [];

            foreach ($travelKeys as $key) {
                if (array_key_exists($key, $data)) {
                    $data['travel_details'][$key] = $data[$key]; 
                    unset($data[$key]);
                } else {
                    $data['travel_details'][$key] = null;
                }
            }

            
        }

        return $data;
    }

    //Function for date conversion
    public function convertDateToDBFormat($data, $format = 'Y-m-d')
    {
        if (!empty($data)) {

            // Handle date_of_birth
            if (isset($data['date_of_birth'])) {
                $dob = trim($data['date_of_birth']);
                $timestamp = ($dob && $dob !== '0000-00-00' && $dob !== '0000-00-00 00:00:00') ? strtotime($dob) : false;
                $data['date_of_birth'] = ($timestamp) ? date($format, $timestamp) : null;
            }

            // Handle delegation_start_date
            if (isset($data['delegation_start_date'])) {
                $dob = trim($data['delegation_start_date']);
                $timestamp = ($dob && $dob !== '0000-00-00' && $dob !== '0000-00-00 00:00:00') ? strtotime($dob) : false;
                $data['delegation_start_date'] = ($timestamp) ? date($format, $timestamp) : null;
            }
            
            // Handle delegation_end_date
            if (isset($data['delegation_end_date'])) {
                $dob = trim($data['delegation_end_date']);
                $timestamp = ($dob && $dob !== '0000-00-00' && $dob !== '0000-00-00 00:00:00') ? strtotime($dob) : false;
                $data['delegation_end_date'] = ($timestamp) ? date($format, $timestamp) : null;
            }

            if (!empty($data['travel_details']) && is_array($data['travel_details'])) {

                // Handle date_of_issue
                if (isset($data['travel_details']['date_of_issue'])) {
                    $doi = trim($data['travel_details']['date_of_issue']);
                    $timestamp = ($doi && $doi !== '0000-00-00' && $doi !== '0000-00-00 00:00:00') ? strtotime($doi) : false;
                    $data['travel_details']['date_of_issue'] = ($timestamp) ? date($format, $timestamp) : null;
                }

                // Handle date_of_expiry
                if (isset($data['travel_details']['date_of_expiry'])) {
                    $doe = trim($data['travel_details']['date_of_expiry']);
                    $timestamp = ($doe && $doe !== '0000-00-00' && $doe !== '0000-00-00 00:00:00') ? strtotime($doe) : false;
                    $data['travel_details']['date_of_expiry'] = ($timestamp) ? date($format, $timestamp) : null;
                }

                // Handle forex_expiry_date
                if (isset($data['travel_details']['forex_expiry_date'])) {
                    $fed = trim($data['travel_details']['forex_expiry_date']);
                    $timestamp = ($fed && $fed !== '0000-00-00' && $fed !== '0000-00-00 00:00:00') ? strtotime($fed) : false;
                    $data['travel_details']['forex_expiry_date'] = ($timestamp) ? date($format, $timestamp) : null;
                }

                // Handle visa_details
                if (!empty($data['travel_details']['visa_details']) && is_array($data['travel_details']['visa_details'])) {
                    foreach ($data['travel_details']['visa_details'] as $key => &$value) {

                        // valid_from
                        $from = trim($value['valid_from'] ?? '');
                        $timestamp1 = ($from && $from !== '0000-00-00' && $from !== '0000-00-00 00:00:00') ? strtotime($from) : false;
                        $value['valid_from'] = ($timestamp1) ? date($format, $timestamp1) : null;

                        // valid_upto
                        $upto = trim($value['valid_upto'] ?? '');
                        $timestamp2 = ($upto && $upto !== '0000-00-00' && $upto !== '0000-00-00 00:00:00') ? strtotime($upto) : false;
                        $value['valid_upto'] = ($timestamp2) ? date($format, $timestamp2) : null;
                    }
                    unset($value);
                }
            }
        }

        return $data;
    }


    public function checkDuplicate()
    {
        $request = $this->request->getGet();
 
        // Define supported fields
        $validFields = ['email', 'mobile_no', 'forex_pre_paid_card_number', 'employee_code', 'passport_number'];
    
        $conditions = [];
        $fieldName = null;
    
        // Determine which field is provided
        foreach ($validFields as $field) {
            if (!empty($request[$field])) {
                $conditions[$field] = $request[$field];
                $fieldName = $field;
                break; // only one field allowed at a time
            }
        }
    
        if (!$fieldName) {
            return $this->response->setJSON([
                'status' => 'error',
                'message' => 'One of the following is required: email, mobile_no, forex_pre_paid_card_number, employee_code'
            ])->setStatusCode(400);
        }
    
        $builder = $this->userModel->where($fieldName, $conditions[$fieldName]);
    
        // Optional: exclude user_id
        if (!empty($request['user_id'])) {
            $builder->where('user_id !=', $request['user_id']);
        }
    
        $user = $builder->first();
    
        if ($user) {
            return $this->response->setJSON(['status' => 'exists', 'field' => $fieldName]);
        } else {
            return $this->response->setJSON(['status' => 'not', 'field' => $fieldName]);
        }
    }


public function userUpload()
{
    
    $predefinedHeaders = ['First Name', 'Last Name', 'Email', 'Mobile Number', 'Password' , 'Role' ,'Employee Code','Group Name',
    'First Approver Email','Second Approver Email','Third Approver Email','Fourth Approver Email'];

    $uploadDir = WRITEPATH . 'uploads/userUploadFiles/';

    // Create folder if not exists
    createDirectoryWith0777Permission($uploadDir);
 

    $file = $this->request->getFile('user_file');

    if (!isValidUploadedFile($file)) {
        return $this->response->setJSON([
            'status' => 'failed',
            'message' => "Invalid file or file not uploaded.",
            'data'    => ['successfulUsers' => [],'failedUsers'     => [] ]
        ]);
    }

    if (!isAllowedExtension($file, ['xlsx', 'xls'])) {
        return $this->response->setJSON([
            'status' => 'failed',
            'message' => "Only Excel files are allowed.",
            'data'    => ['successfulUsers' => [],'failedUsers'     => [] ]
        ]);
    }

    // Move file temporarily
    $randomName = $file->getRandomName();
    $file->move($uploadDir, $randomName);
    $filePath = $uploadDir . $randomName;

    // Load Excel
    $spreadsheet = IOFactory::load($filePath);
    $sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, true);

    $maxColumns = 12;

    $trimmedData = array_map(function ($row) use ($maxColumns) {
        return array_slice($row, 0, $maxColumns); 
    }, $sheetData);

    if (!isExcelNotEmpty($sheetData)) {
        // before return remove the empty file
        return $this->response->setJSON([
            'status' => 'failed',
            'message' => "Excel sheet is empty or has no data.",
            'data'    => ['successfulUsers' => [],'failedUsers'     => [] ]
        ]);
    }

    // Validate headers
    // Sanitize headers: remove spaces/special characters and convert to lowercase
    $rawHeaders = array_values($trimmedData[1]);

    $headers = array_map(function ($header) {
        return strtolower(preg_replace('/[^a-zA-Z0-9]/', '', trim($header)));
    }, $rawHeaders);

    $predefinedHeaders = array_map(function ($header) {
        return strtolower(preg_replace('/[^a-zA-Z0-9]/', '', $header));
    }, $predefinedHeaders);


    unset($trimmedData[1]); // Remove header row

    $success = 0 ;
    $fail    = 0 ;
    $successfulUsers = [];
    $failedUsers     = [];
    $insertUsers     = [];

    $dbHeaders = ['first_name','last_name','email','mobile_no','password','role_id','employee_code','group_id',
    'first_approver_email','second_approver_email','third_approver_email','fourth_approver_email'];

    $rolesList = $this->userModel->getRolesList();

    $groupsList = $this->userModel->getgroupsList();


    foreach ($trimmedData as $row) {

        $user = array_combine($dbHeaders, array_values($row));
        $email = $user['email'] ?? 'N/A';
    
        // Email validation
        if (!isset($user['email']) || empty($user['email'])) {
            $fail++;
            $failedUsers[] = ['data' => $user['first_name'].' '.$user['last_name'], 'reason' => 'Email is missing'];
            continue;
        }
    
        if (!filter_var($user['email'], FILTER_VALIDATE_EMAIL)) {
            $fail++;
            $failedUsers[] = ['data' => $email, 'reason' => 'Invalid email format'];
            continue;
        }
    
        // Check duplicate
        $userExists = $this->userModel->userExists($user['email']);
        if ($userExists) {
            $fail++;
            $failedUsers[] = ['data' => $email, 'reason' => 'User already exists'];
            continue;
        }
    
        // Check approver mail valid
        if (!empty($user['first_approver_email']) && !filter_var($user['first_approver_email'], FILTER_VALIDATE_EMAIL)) {
            $fail++;
            $failedUsers[] = ['data'  => $user['first_name'].' '.$user['last_name'], 'reason' => 'Invalid first approver email format' ];
            continue;
        }

        if (!empty($user['second_approver_email']) && !filter_var($user['second_approver_email'], FILTER_VALIDATE_EMAIL)) {
            $fail++;
            $failedUsers[] = ['data'  => $user['first_name'].' '.$user['last_name'], 'reason' => 'Invalid second_approver_email format' ];
            continue;
        }

        if (!empty($user['third_approver_email']) && !filter_var($user['third_approver_email'], FILTER_VALIDATE_EMAIL)) {
            $fail++;
            $failedUsers[] = ['data'  => $user['first_name'].' '.$user['last_name'], 'reason' => 'Invalid third_approver_email format' ];
            continue;
        }


        if (!empty($user['fourth_approver_email']) && !filter_var($user['fourth_approver_email'], FILTER_VALIDATE_EMAIL)) {
            $fail++;
            $failedUsers[] = ['data'  => $user['first_name'].' '.$user['last_name'], 'reason' => 'Invalid fourth_approver_email format' ];
            continue;
        }

        

        $role    = strtolower(preg_replace('/[^A-Za-z0-9]/', '', $user['role_id']));
        $group   = strtolower(preg_replace('/[^A-Za-z0-9]/', '', $user['group_id']));
    
        // Sanitize and prepare for insert
        $user['password_string'] = $user['password'];
        $user['password'] = password_hash($user['password'], PASSWORD_DEFAULT);
        $user['email'] = filter_var($user['email'], FILTER_SANITIZE_EMAIL);
        $user['first_approver_email'] = filter_var($user['first_approver_email'], FILTER_SANITIZE_EMAIL);
        $user['second_approver_email'] = filter_var($user['second_approver_email'], FILTER_SANITIZE_EMAIL);
        $user['third_approver_email'] = filter_var($user['third_approver_email'], FILTER_SANITIZE_EMAIL);
        $user['fourth_approver_email'] = filter_var($user['fourth_approver_email'], FILTER_SANITIZE_EMAIL);
        $user['role_id'] = $rolesList[$role] ?? 4;
        $user['group_id'] = $groupsList[$group] ?? null;
        $user['org_id'] = env('ORG_id');
    
        $insertUsers[] = $user;
        $success++;
        $successfulUsers[] = $user['email'];
    }
    

    $insertedIds = [];

    foreach ($insertUsers as $user) {
        $insertSuccess = $this->userModel->insert($user);
    
        if ($insertSuccess) {
            $insertedIds[] = $this->userModel->getInsertID();
    
            // Prepare mail content
            $mailData = [
                'first_name' => $user['first_name'],
                'last_name'  => $user['last_name'],
                'email'      => $user['email'],
                'password'   => $user['password_string'],
                'org_id'     => env('ORG_id'),
                'site_url'   => env('FE_URL'),
                'template'   => 'user_creation_notification',
            ];
    
            // Trigger mail
            sendUserCreationMail($mailData);
        }
    }



    //since email id directly stored in first_approver_email need to update in first_approver with id

    $this->userModel->updateApprover('first', $insertedIds);
    $this->userModel->updateApprover('second', $insertedIds);
    $this->userModel->updateApprover('third', $insertedIds);
    $this->userModel->updateApprover('fourth', $insertedIds);


    return $this->response->setJSON([
        'status' => 'success',
        'message' => "$success users processed successfully, $fail failed.",
        'data'    => [
            'successfulUsers' => $successfulUsers,
            'failedUsers'     => $failedUsers
        ]
    ]);
}

public function userUploadTemplate()
{
    $uploadDir = WRITEPATH . 'uploads/template';

     createDirectoryWith0777Permission($uploadDir);

    $filePath = WRITEPATH . 'uploads/template/user_file.xlsx';

    if (!file_exists($filePath)) {
        return $this->response->setStatusCode(404)->setJSON(['error' => 'Template file not found.']);
    }

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

}


public function downloadPassport()
{
    $user_id = $this->request->getGet('user_id');



    // Get user data
    $user = $this->userModel->select('passport_document')->where('user_id', $user_id)->first();

    if (!$user || empty($user['passport_document'])) {
        return $this->respond([
            'status'  => 404,
            'message' => 'Passport document not found'
        ], 404);
    }

    // Full path from DB
    $filePath = $user['passport_document'];

    // If file path stored includes domain or base path, extract only the actual file path
    // Example: /home3/venbaehn/apitest.tripapprovaltool.com/tstat_be/assets/images/passport/filename.pdf
    if (!file_exists($filePath)) {
        return $this->respond([
            'status'  => 404,
            'message' => 'File not found on server'
        ], 404);
    }

    // Extract just the filename (for download name)
    $fileName = basename($filePath);

    // Return file as downloadable response
    return $this->response->download($filePath, null)->setFileName($fileName);
}



    

































































}
