<?php

namespace App\Http\Controllers\api\v1;

use App\Http\Controllers\API\v1\EmployeeAttendanceController;
use App\Http\Controllers\Controller;
use App\Models\Approver;
use Illuminate\Http\Request;
use App\Models\Employee;
use App\Models\EmployeeProfilePicture;
use App\Models\Payroll;
use App\Models\Role;
use App\Models\RoleCompanyAccess;
use App\Models\SalaryAndWages;
use App\Models\User;
use App\Models\UserRole;
use DateTime;
use Exception;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Throwable;

class EmployeeController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(Request $request)
    {
        $user = Auth::user();

        $keyword = $request->input('keyword', '');
        $perPage = $request->input('per_page', PHP_INT_MAX);
        $sortBy = $request->input('sortBy', '');
        $sortType = $request->input('sortType', '');

        $keyword = str_replace(" ", "%", $keyword);
        $dealership = $request->input('dealership', '');
        
        // relationships to load
        $employeeRelations = [
            'section:id,code,name',
            'position:id,code,name',
            'company:id,code,name',
            'classification:id,name',
            'dealership:id,code,name',
            'salary_grade:id,name',
            'employment_type:id,code,name',
            'group:id,code,name',
            'division:id,code,name',
            'department:id,code,name',
            'office:id,code,name',
            'locality:id,code,province,locality',
            'chargeTo:id,code,name',
            'salary_and_wages:id,salary_rate,position_exclusive_date,salary_effectivity_date,payroll_rate,payment_type,payroll_mode,bank_account,tax_exemption,fixed_pagibig_contribution,pagibig_ee,pagibig_er,charge_salary,cola,shields'
        ];

        if ($user->roles[0]->group_id == 1 || $user->roles[0]->group_id == 2) {
            $data = Employee::with($employeeRelations)
                ->select(
                    DB::raw("CONCAT(firstname, ' ', lastname) as full_name"),
                    'employees.id', 'employees.employee_id', 'employees.asa_user_id', 'employees.time_keeping_id',
                    'employees.firstname', 'employees.lastname', 'employees.middlename', 'employees.date_hired',
                    'employees.date_resign', 'employees.email', 'employees.mobile', 'employees.position_id',
                    'employees.company_id', 'employees.classification_id', 'employees.dealer_id', 'employees.job_grade_id',
                    'employees.office_id', 'employees.employment_status_id', 'employees.group_id', 'employees.division_id',
                    'employees.department_id', 'employees.section_id', 'employees.office_id', 'employees.flexible', 'employees.work_location_id', 'employees.confidential', 'employees.direct_manager_approval', 'employees.acting_manager'
                )
                ->where('employees.enabled', '=', '1')
                ->where('employees.employee_id', '!=', '')
                ->whereNull('employees.date_resign')
                ->where(function ($query) use ($keyword) {
                    $query->where('employee_id', 'like', '%' . $keyword . '%')
                        ->orWhere('firstname', 'like', '%' . $keyword . '%')
                        ->orWhere('lastname', 'like', '%' . $keyword . '%');
                });

        } else {
            $approverHierarchy = Approver::where('approvers', 'like', '%"'.$user->employee_id.'"%')->get()
                ->groupBy('type')->map(fn($group) => $group->pluck('type_id')->toArray());

            if($approverHierarchy->isNotEmpty()){
                $data = Employee::with($employeeRelations)
                ->select(
                    DB::raw("CONCAT(firstname, ' ', lastname) as full_name"),
                    'employees.id', 'employees.employee_id', 'employees.asa_user_id', 'employees.time_keeping_id',
                    'employees.firstname', 'employees.lastname', 'employees.middlename', 'employees.date_hired',
                    'employees.date_resign', 'employees.email', 'employees.mobile', 'employees.position_id',
                    'employees.company_id', 'employees.classification_id', 'employees.dealer_id', 'employees.job_grade_id',
                    'employees.office_id', 'employees.employment_status_id', 'employees.group_id', 'employees.division_id',
                    'employees.department_id', 'employees.section_id', 'employees.office_id', 'employees.flexible', 'employees.work_location_id', 'employees.confidential', 'employees.direct_manager_approval', 'employees.acting_manager'
                )
                ->where('employees.dealer_id', $dealership)
                ->where('employees.classification_id', '<', $user->employees->classification_id)
                ->where('employees.enabled', '=', '1')
                ->whereNull('employees.date_resign')
                ->where(function ($query) use ($keyword) {
                    $query->where('employee_id', 'like', '%' . $keyword . '%')
                        ->orWhere('firstname', 'like', '%' . $keyword . '%')
                        ->orWhere('lastname', 'like', '%' . $keyword . '%');
                })
                ->where(function ($query) use ($approverHierarchy) {
                    $firstIteration = true;
                    foreach ($approverHierarchy as $type => $ids) {
                        $column = $type === 'dealership' ? 'dealer_id' : $type . '_id';
                        if ($firstIteration) {
                            $query->whereIn('employees.' . $column, $ids);
                            $firstIteration = false;
                        } else {
                            $query->orWhereIn('employees.' . $column, $ids);
                        }
                    }
                });
            } else {
                $data = Employee::query()->whereRaw('1 = 0');
            }
        }

        $sortMappings = [
            'company.name' => ['table' => 'companies', 'column' => 'name', 'key' => 'company_id'],
            'dealership.name' => ['table' => 'dealerships', 'column' => 'name', 'key' => 'dealer_id'],
            'position.name' => ['table' => 'job_titles', 'column' => 'name', 'key' => 'position_id'],
        ];

        if (array_key_exists($sortBy, $sortMappings)) {
            $mapping = $sortMappings[$sortBy];
            $data = $data->join($mapping['table'], 'employees.' . $mapping['key'], '=', $mapping['table'] . '.id')
                        ->orderBy($mapping['table'] . '.' . $mapping['column'], $sortType);
        } elseif (!empty($sortBy)) {
            $data = $data->orderBy($sortBy, $sortType);
        }
        
        $data->whereNull('employees.date_resign');
        $data = $data->paginate($perPage);

        $data = $data->map(function ($employee) {
            $employee->employee_id_encrypted = encrypt($employee->employee_id);
            return $employee;
        });

        return response()->json($data);
    }

    public function employeeList(Request $request)
    {
        $user = Auth::user();

        $keyword = $request->input('keyword', '');
        $perPage = $request->input('per_page', PHP_INT_MAX);
        $sortBy = $request->input('sortBy', '');
        $sortType = $request->input('sortType', '');

        $keyword = str_replace(" ", "%", $keyword);
        $dealership = $request->input('dealership', '');

        $isResigned = $request->input('is_resigned', '');

        // dd($request->all());

        // relationships to load
        $employeeRelations = [
            'section:id,code,name',
            'position:id,code,name',
            'company:id,code,name',
            'classification:id,name',
            'dealership:id,code,name',
            'salary_grade:id,name',
            'employment_type:id,code,name',
            'group:id,code,name',
            'division:id,code,name',
            'department:id,code,name',
            'office:id,code,name',
            'locality:id,code,province,locality',
            'chargeTo:id,code,name',
            'salary_and_wages:id,salary_rate,position_exclusive_date,salary_effectivity_date,payroll_rate,payment_type,payroll_mode,bank_account,tax_exemption,fixed_pagibig_contribution,pagibig_ee,pagibig_er,charge_salary,cola,shields'
        ];

        if ($user->roles[0]->group_id == 1) {
            $data = Employee::with($employeeRelations)
                ->select(
                    DB::raw("CONCAT(lastname, ' ', firstname) as full_name"),
                    'employees.id', 'employees.employee_id', 'employees.asa_user_id', 'employees.time_keeping_id',
                    'employees.firstname', 'employees.lastname', 'employees.middlename', 'employees.date_hired',
                    'employees.date_resign', 'employees.email', 'employees.mobile', 'employees.position_id',
                    'employees.company_id', 'employees.classification_id', 'employees.dealer_id', 'employees.job_grade_id',
                    'employees.office_id', 'employees.employment_status_id', 'employees.group_id', 'employees.division_id',
                    'employees.department_id', 'employees.section_id', 'employees.office_id', 'employees.work_location_id', 'employees.flexible', 'employees.confidential', 'employees.direct_manager_approval', 'employees.acting_manager'
                )
                ->where('employees.enabled', '=', '1')
                ->where('employees.employee_id', '!=', '')
                ->when(!$isResigned, function ($query) {
                    $query->whereNull('employees.date_resign');
                })
                ->where(function ($query) use ($keyword) {
                    $query->where('employee_id', 'like', '%' . $keyword . '%')
                        ->orWhere('firstname', 'like', '%' . $keyword . '%')
                        ->orWhere('lastname', 'like', '%' . $keyword . '%');
                });
        } else {
            $role_id = array();
            foreach($user->roles as $role){
                $role_id[] = $role->id;
            }

            // $dealers = RoleCompanyAccess::where('role_id', $user->roles[0]->id)->pluck('dealership_id')->toArray();
            $dealers = RoleCompanyAccess::whereIn('role_id', $role_id)->pluck('dealership_id')->toArray();
            // dd($dealers);
            $data = Employee::with($employeeRelations)
                ->select(
                    DB::raw("CONCAT(lastname, ', ', firstname) as full_name"),
                    'employees.id', 'employees.employee_id', 'employees.asa_user_id', 'employees.time_keeping_id',
                    'employees.firstname', 'employees.lastname', 'employees.middlename', 'employees.date_hired',
                    'employees.date_resign', 'employees.email', 'employees.mobile', 'employees.position_id',
                    'employees.company_id', 'employees.classification_id', 'employees.dealer_id', 'employees.job_grade_id',
                    'employees.office_id', 'employees.employment_status_id', 'employees.group_id', 'employees.division_id',
                    'employees.department_id', 'employees.section_id', 'employees.office_id', 'employees.work_location_id', 'employees.flexible', 'employees.confidential', 'employees.direct_manager_approval', 'employees.acting_manager'
                )
                ->where('employees.enabled', '=', '1')
                ->where('employees.employee_id', '!=', '')
                ->when(!$isResigned, function ($query) {
                    $query->whereNull('employees.date_resign');
                })
                ->where(function ($query) use ($keyword, $dealership) {
                    $query->where('employee_id', 'like', '%' . $keyword . '%')
                        ->orWhere('firstname', 'like', '%' . $keyword . '%')
                        ->orWhere('lastname', 'like', '%' . $keyword . '%');
                })
                ->whereIn('employees.dealer_id', $dealers);
        }

        $sortMappings = [
            'company.name' => ['table' => 'companies', 'column' => 'name', 'key' => 'company_id'],
            'dealership.name' => ['table' => 'dealerships', 'column' => 'name', 'key' => 'dealer_id'],
            'position.name' => ['table' => 'job_titles', 'column' => 'name', 'key' => 'position_id'],
        ];

        if (array_key_exists($sortBy, $sortMappings)) {
            $mapping = $sortMappings[$sortBy];
            $data = $data->join($mapping['table'], 'employees.' . $mapping['key'], '=', $mapping['table'] . '.id')
                        ->orderBy($mapping['table'] . '.' . $mapping['column'], $sortType);
        } elseif (!empty($sortBy)) {
            $data = $data->orderBy($sortBy, $sortType);
        }

        $data = $data->get();

        $data = $data->map(function ($employee) {
            $employee->employee_id_encrypted = encrypt($employee->employee_id);
            return $employee;
        });

        return response()->json($data);
    }

    public function store(Request $request)
    {

        DB::connection()->beginTransaction();

        try {
            // dd($request->all());
            $requestData = $request->all(); // Extract first item from array

            // Validate incoming data
            $validated = Validator::make($requestData, [
                'basic.employee_id'       => 'required|unique:users,employee_id',
                'basic.firstname'         => 'required|string|max:255',
                'basic.lastname'          => 'required|string|max:255',
                'basic.email' => [
                    'required',
                    function ($attribute, $value, $fail) {
                        $exists = \App\Models\Employee::where('email', $value)->whereNull('date_resign')->exists();
                        if ($exists) {
                            $fail('The email has already been taken by an active employee.');
                        }
                    },
                ],
                'salary.salary_rate'      => 'required|numeric',
                'basic.classification_id' => 'required|integer',
            ])->validate();

            // Create User
            $firstnameForUser = str_replace(' ', '', $requestData['basic']['firstname']);
            $getFirstLetter = str_split($firstnameForUser)[0];
            $username = strtolower($getFirstLetter.str_replace(' ', '', ($requestData['basic']['lastname'])));

            $baseUsername = $username; // Store the original username
            $count = 1;

            // Check if the original username exists
            if (User::where('username', $username)->exists()) {
                do {
                    $newUsername = $baseUsername . $count;
                    $count++;
                } while (User::where('username', $newUsername)->exists());

                $username = $newUsername; // Assign the unique username
            }

            $user = User::create([
                'employee_id' => $requestData['basic']['employee_id'],
                'first_name'  => $requestData['basic']['firstname'],
                'last_name'   => $requestData['basic']['lastname'],
                'name'        => $requestData['basic']['firstname'] . ' ' . $requestData['basic']['lastname'],
                'username'    => $username,
                'email'       => $requestData['basic']['email'],
                'password'    => Hash::make('password'),
            ]);

            if (!$user) {
                throw new Exception('Failed to create user.');
            }

            // Assign Role
            $userRole = UserRole::create([
                'role_id' => match ($requestData['basic']['classification_id']) {
                    1 => '12',
                    2 => '12',
                    3 => '12',
                    default => '12',
                },
                'user_id' => $user->id,
            ]);

            // Create Salary Record
            $salary = SalaryAndWages::create([
                'employee_id'  => $requestData['basic']['employee_id'],
                'salary_rate'  => $requestData['salary']['salary_rate'],
            ]);

            // Add `date_hired` if missing
            $requestData['basic']['date_hired'] = $requestData['basic']['date_hired'] ?? date('Y-m-d');

            // Create Employee Record
            $employee = Employee::create($requestData['basic']);

            DB::connection()->commit();

            return response()->json([
                'message' => 'Record Successfully added!',
                'status' => 'success',
            ], 201);

        } catch (Exception $e) {
            DB::connection()->rollback();
            Log::error($e->getMessage());

            return response()->json([
                'status' => false,
                'message' => 'Unable to process request. Please try again.',
                'error'   => $e->getMessage(),
            ], 422);
        }
    }

    public function getAllEmployeesWithoutResign(Request $request){

        $company_id = $request->input('company_id', null);
        $dealership_id = $request->input('dealership_id', null);
        $department_id = $request->input('department_id', null);
        $start_date = $request->input('start_date',null);
        $end_date = $request->input('end_date',null);
        $data = Employee::where('enabled', '=', '1')->whereNull('date_resign');

        // if($company_id) $data = $data->where('company_id', '=', $company_id);
        // if($dealership_id) $data = $data->where('dealer_id', '=', $dealership_id);
        // $data = $data->orderBy('lastname')->orderBy('firstname')->orderBy('middlename');
        $data = $data->get();

        // dd($data);
        return response()->json($data);
    }

    public function getAllEmployees(Request $request){

        $company_id = $request->input('company_id', null);
        $dealership_id = $request->input('dealership_id', null);
        $department_id = $request->input('department_id', null);
        $start_date = $request->input('start_date',null);
        $end_date = $request->input('end_date',null);
        $data = Employee::with('salary_and_wages:employee_id,always_present')->where('enabled', '=', '1')
        ->when($end_date, fn($q) => $q
        ->where(fn($q2) => $q2->where('date_hired', '<=', $end_date)->orWhereNull('date_hired'))
        ->where(fn($q2) => $q2->where('date_resign','>=',$end_date)->orWhereNull('date_resign'))
        )
        // ->whereNull('date_resign')
        ;
        if($company_id) $data = $data->where('company_id', '=', $company_id);
        if($dealership_id) $data = $data->where('dealer_id', '=', $dealership_id);
        $data = $data->orderBy('lastname')->orderBy('firstname')->orderBy('middlename');
        $data = $data->get();

        return response()->json($data);
    }

    public function getAllEmployeesForPayrollAccess(){
        $user = Auth::user();
        
        $rolesWithSystemId3 = $user->roles->filter(function($role) {
            return $role->group && $role->group->system_id === 3;
        });

        // Get dealers for ALL roles with system_id 3
        $dealers = [];
        if ($rolesWithSystemId3->isNotEmpty()) {
            $roleIds = $rolesWithSystemId3->pluck('id')->toArray();
            
            $dealers = RoleCompanyAccess::whereIn('role_id', $roleIds)
                ->pluck('dealership_id')
                ->unique()
                ->toArray();
        }

        $data = Employee::with('salary_and_wages:employee_id,always_present')
            ->where('enabled', '=', '1')
            ->whereNull('date_resign')
            ->whereIn('dealer_id', $dealers)
            ->orderBy('lastname')
            ->orderBy('firstname')
            ->orderBy('middlename')
            ->get();

        return response()->json($data);
    }

    public function getEmployeesBasedOnDepartment(Request $request)
    {
        
        $user = Auth::user();
        $rolesWithSystemId3 = $user->roles->filter(function($role) {
            return $role->group && $role->group->system_id === 3;
        });

        // Get dealers for ALL roles with system_id 3
        $dealers = [];
        if ($rolesWithSystemId3->isNotEmpty()) {
            $roleIds = $rolesWithSystemId3->pluck('id')->toArray();
            
            $dealers = RoleCompanyAccess::whereIn('role_id', $roleIds)
                ->pluck('dealership_id')
                ->unique()
                ->toArray();
        }

        $data = Employee::where('enabled', '=', '1')->whereNull('date_resign')->whereIn('dealer_id', $dealers)->whereIn('department_id', $request);
        $data = $data->get();

        return response()->json($data);
    }
    /**
     * Display the specified resource.
     */
    public function show(string $id)
    {
        DB::enableQueryLog();

        try {
            $id = Crypt::decrypt($id);
        } catch (\Illuminate\Contracts\Encryption\DecryptException $e) {
            $id = $id;
        }

        $data = Employee::with([
            'section' => fn($section) =>
                    $section->select('sections.id', 'sections.code', 'sections.name')
                ,
                'position' => fn($position) =>
                    $position->select('job_titles.id', 'job_titles.code', 'job_titles.name')
                ,
                'company' => fn($company) =>
                    $company->select('companies.id', 'companies.code', 'companies.name')
                ,
                'classification' => fn($classification) =>
                    $classification->select('job_classifications.id', 'job_classifications.name')
                ,
                'dealership' => fn($dealership) =>
                    $dealership->select('dealerships.id', 'dealerships.code', 'dealerships.name')
                ,
                'salary_grade' => fn($salary_grade) =>
                    $salary_grade->select('salary_grades.id', 'salary_grades.name')
                ,
                'employment_type' => fn($employment_type) =>
                    $employment_type->select('employment_types.id', 'employment_types.code', 'employment_types.name')
                ,
                'group' => fn($group) =>
                    $group->select('groups.id', 'groups.code', 'groups.name')
                ,
                'division' => fn($division) =>
                    $division->select('divisions.id', 'divisions.code', 'divisions.name')
                ,
                'department' => fn($department) =>
                    $department->select('departments.id', 'departments.code', 'departments.name')
                ,
                'office' => fn($office) =>
                    $office->select('offices.id', 'offices.code', 'offices.name')
                ,
                'locality' => fn($locality) =>
                    $locality->select('localities.id', 'localities.code', 'localities.province', 'localities.locality')
                ,
                'salary_and_wages' => fn($salary_and_wages) =>
                    $salary_and_wages->select('salary_and_wages.id', 'salary_and_wages.employee_id', 'salary_and_wages.salary_rate','salary_and_wages.position_exclusive_date', 'salary_and_wages.salary_effectivity_date', 'salary_and_wages.payroll_rate',
                    'salary_and_wages.payroll_rate', 'salary_and_wages.payment_type', 'salary_and_wages.payroll_mode', 'salary_and_wages.bank_account', 'salary_and_wages.tax_exemption', 'salary_and_wages.fixed_pagibig_contribution',
                    'salary_and_wages.pagibig_ee', 'salary_and_wages.pagibig_er', 'salary_and_wages.charge_salary', 'salary_and_wages.cola', 'salary_and_wages.shields', 'salary_and_wages.tax_application')
                ,
                'employee_profile' => fn($employee_profile) =>
                    $employee_profile->select('employee_profile_pictures.id','employee_profile_pictures.employee_id','employee_profile_pictures.attachment')
            ])
            ->select(DB::raw("CONCAT(firstname, ' ', lastname) as full_name"),
                'employees.id', 'employees.employee_id', 'employees.asa_user_id', 'employees.time_keeping_id', 'employees.firstname',
                'employees.lastname', 'employees.middlename', 'employees.date_hired', 'employees.date_resign',
                'employees.email', 'employees.mobile', 'employees.position_id', 'employees.company_id', 'employees.classification_id', 'employees.dealer_id', 'employees.job_grade_id',
                'employees.office_id', 'employees.employment_status_id', 'employees.group_id', 'employees.division_id', 'employees.department_id', 'employees.section_id',
                'employees.office_id', 'employees.work_location_id', 'employees.flexible', 'employees.confidential', 'employees.direct_manager_approval', 'employees.acting_manager')
            ->where('employees.employee_id', '=', $id)
            ->first();

            if($data->employee_profile)
                $data->employee_profile['attachment'] = asset('storage/employee-profile/' . $data->employee_profile['attachment']);

            // dd(DB::getQueryLog());
            // dd($data);
        return response()->json($data);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, int $id)
    {
        $request['position'] = '';

        $data = Employee::where('id', $id)->first();

        if (!$data) {
            return response()->json(['messages' => 'No data found.'], 404);
        }

        $validator = Validator::make($request->all(), [
            'firstname' => [
                'required',
                'min:1',
            ],
            'lastname' => [
                'required',
                'min:1',
            ],
            'employee_id' => [
                'required',
                'min:1',
                Rule::unique('employees')->ignore($id)->whereNull('deleted_at')
            ],
            // 'time_keeping_id' => [
            //     'required',
            //     'min:1',
            //     Rule::unique('employees')->ignore($id)->whereNull('deleted_at')
            // ],
            'company_id' => [
                'required',
                'min:1',
            ]
        ]);

        // if($request->date_resign != null){
        //     dd($request->all());
        // }

        /** If validation fails return with error message */
        if ($validator->fails()) {
            $errors = $validator->errors();
            $first = $errors->getMessages();

            return response()->json([
                'status'  => false,
                'message' => (reset($first))[0],
                'errors'  => $errors
            ], Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        DB::connection()->beginTransaction();

        try {

            try {
                $user = User::where('employee_id', $request->employee_id)->first();

                $user['email'] = $request->email;
                $user->save();

                $user->touch();

                DB::connection()->commit();

                // dd($user);
            } catch (Exception $e) {
                DB::connection()->rollback();
                return response()->json([
                    'status'  => false,
                    'message' => 'Unable to process request. Please try again.',
                    'data'    => $e->getMessage()
                ]);
            }

            $data->fill($request->all());
            $data->save();

            $data->touch();

            DB::connection()->commit();

            return response()->json([
                'message' => 'Record Successfully updated!',
                'status' => 'success',
                'data' => $data,
            ],201);

        } catch (Throwable $e) {
            DB::connection()->rollback();
            return response()->json([
                'status'  => false,
                'message' => 'Unable to process request. Please try again.',
                'data'    => $e->getMessage()
            ]);
        }
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(string $id)
    {
        //
    }

    public function getHrManager(string $company_id)
    {
        $data = Employee::where([
            'company_id' => $company_id,
            'position_id' => 540,
            'enabled' => 1
        ])
        ->select(DB::raw("CONCAT(firstname, ' ', lastname) as full_name"), 'employee_id')
        ->first();

        if (!$data) {
            $data = [
                'full_name' => 'Margarita Adeva',
                'employee_id' => '60298'
            ];
        }

        return response()->json($data);
    }

    public function imageUpload(Request $request)
    {
        // dd(Crypt::decrypt($request->id));
        try {
            $employee_id = Crypt::decrypt($request->id);
            $request['employee_id'] = $employee_id;
        } catch (\Illuminate\Contracts\Encryption\DecryptException $e) {
            $employee_id = $request->employee_id;
        }

        // dd($employee_id);
        $data = Employee::where('employee_id', $employee_id)->first();

        $attachment_name = $request->attachment;

        if($request->hasFile('attachment')) {
            $image      = $request->file('attachment');
            $attachment_name  = time().'_'.$image->getClientOriginalName();
            $path       = "/public/employee-profile/".$attachment_name;
            if(!Storage::disk('local')->put($path, file_get_contents($image)))
            {
                return response()->json(['message'=> "Failed to upload attachment"],304);
            }
        }
        else
        {
            $attachment_name = null;
        }


        DB::connection()->beginTransaction();
        // dd($id);
        $employee_profile = EmployeeProfilePicture::where('employee_id', $data->employee_id)->first();

        if(!empty($employee_profile)){

            $attachment_file_path = '/public/employee-profile/' . $employee_profile->attachment;
            if(Storage::exists($attachment_file_path))
            {
                Storage::delete($attachment_file_path);
            }

            try {
                $employee_profile->employee_id = $data->employee_id;
                $employee_profile->attachment = $attachment_name;
                $employee_profile->save();


                // dd($employee_profile);
                DB::commit();

                return response()->json([
                    'status'  => true,
                    'message' => 'Saved successfully!',
                    'data'    => $employee_profile
                ],201);

            } catch (Throwable $e) {

                DB::connection()->rollback();
                return response()->json([
                    'status'  => false,
                    'message' => 'Unable to process request. Please try again.',
                    'data'    => $e->getMessage()
                ]);
            }
        } else {
            try {

                $status = EmployeeProfilePicture::create([
                    'employee_id' => $data->employee_id,
                    'attachment' => $attachment_name,
                ]);

                DB::commit();

                return response()->json([
                    'status'  => true,
                    'message' => 'Saved successfully!',
                    'data'    => $employee_profile
                ],201);
            } catch (Throwable $e) {

                DB::connection()->rollback();
                return response()->json([
                    'status'  => false,
                    'message' => 'Unable to process request. Please try again.',
                    'data'    => $e->getMessage()
                ]);
            }
        }
    }

    public function countDuplicatedEmail(Request $request){
        $count = DB::table('employees')
                ->where('email', 'like', '%'.$request->email.'%')
                ->whereNull('date_resign')
                ->count();

        return $count;
    }

    public function checkEmailExisted(Request $request){
        $count = DB::table('employees')
                ->where('email', 'like', '%'.$request->email.'%')
                ->whereNull('date_resign')
                ->count();

        return $count;
    }

    public function checkEmailEmployeeIdSame(Request $request){
        // dd($request->all());
        $count = DB::table('employees')
                ->where('email', 'like', '%'.$request->email.'%')
                ->where('employee_id', '=', $request->employee_id)
                ->whereNull('date_resign')
                ->count();

        return $count;
    }

    public function countDuplicatedEmployeeId(Request $request){
        $count = DB::table('employees')
                ->where('employee_id', $request->employee_id)
                ->count();

        return $count;
    }

    public function getCurrentScheduleProfile(Request $request){
        try {
            $request['employee_id'] = Crypt::decrypt($request->employee_id);
        } catch (\Illuminate\Contracts\Encryption\DecryptException $e) {
            $request['employee_id'] = $request->employee_id;
        }

        $schedule = new EmployeeAttendanceController();

        $scheduleData = $schedule->getSchedule(date('Y-m-d'), $request->employee_id);

        // dd($scheduleData);
        return response()->json($scheduleData);
    }

    public function getCurrentSchedule(Request $request){

        $schedule = new EmployeeAttendanceController();

        $time_keeping_id = Employee::where('employee_id', $request->employee_id)->pluck('time_keeping_id');

        $scheduleData = $schedule->getSchedule($request->date_from, $request->employee_id);
        $timelogs = $schedule->getTimelog($request->date_from, $time_keeping_id);

        $timeIn = "";
        $timeOut = "";

        foreach($timelogs as $timelog){
            if($timelog->in_out == "I"){
                $timeIn = date('H:i:s', strtotime($timelog->datetimelog));
            }

            if($timelog->in_out == "O"){
                $timeOut = date('H:i:s', strtotime($timelog->datetimelog));
            }
        }

        $timelogData = [
            'time_in' => $timeIn,
            'time_out' => $timeOut
        ];

        $scheduleDataFinal = [
            'from_time' => $scheduleData->schedule->from_time,
            'to_time' => $scheduleData->schedule->to_time,
            'day_off' => $scheduleData->schedule->day_off,
            'wfh' => $scheduleData->schedule->wfh,
            'cws_from_time' => $scheduleData->schedule->cws_from_time,
            'cws_to_time' => $scheduleData->schedule->cws_to_time,
            'cws_day' => $scheduleData->schedule->cws_day_off
        ];

        return response()->json([
            'timelogs' => $timelogData,
            'schedule' => $scheduleDataFinal
        ]);
    }

    public function passwordChecker(Request $request){

        $password = $request->password;

        $user = Auth::user();

        if(Hash::check($password, $user->password)){
            return response()->json([
                'status' => true,
                'message' => 'Password matched!'
            ]);
        } else {
            return response()->json([
                'status' => false,
                'message' => 'Password does not match!'
            ]);
        }
    }

    public function updatePassword(Request $request)
    {
        $params = $request->input('params');

        $validated = Validator::make($params, [
            'employee_id' => 'required',
            'currentPassword' => 'required|string',
            'newPassword' => 'required|string',
            'confirmPassword' => 'required|string|same:newPassword',
        ])->validate();

        // Use Eloquent to retrieve the user
        $user = \App\Models\User::whereHas('employees', function ($query) use ($validated) {
            $query->where('employee_id', $validated['employee_id'])
                ->whereNull('date_resign');
        })->first();

        if (!$user) {
            return response()->json([
                'status' => false,
                'message' => 'User not found or no active employee linked.',
            ], 404);
        }

        // Update the password
        $user->password = Hash::make($validated['newPassword']);
        $user->last_password_change = now();

        $user->save();

        return response()->json([
            'message' => 'Record Successfully updated!',
            'status' => 'success'
        ],201);

    }

    public function getRecordByEmployee(Request $request)
    {
        $employee = Auth::user();

        //
        $keyword = $request->input('keyword', '');
        $perPage = $request->input('per_page',PHP_INT_MAX);
        $sortBy = $request->input('sortBy', '');
        $sortType = $request->input('sortType', '');

        $data = Payroll::with(['company','dealership', 'summary' => fn($q) =>$q->where('employee_id', $employee->employee_id)->with(['employee'])])
            ->whereHas('summary', fn($q) => $q->where('employee_id',$employee->employee_id))
            ->whereNotNull('released_at')
            ->when($keyword, fn($q) => $q->whereHas('company', fn($qc) => $qc->where('name', 'like', '%'.$keyword.'%'))->orWhereHas('dealership', fn($qc) => $qc->where('name', 'like', '%'.$keyword.'%'))->orWhere('payroll_date', 'like', $keyword.'%')->orWhere('cut_off', 'like', $keyword.'%'))
            ->when($sortBy, fn ($q) => $q->orderBy($sortBy, $sortType))
            ->paginate($perPage);

        // dd($data);

        return response()->json($data);
    }

}
