<?php

namespace App\Http\Controllers\API\v1;

use App\Http\Controllers\Controller;
use App\Models\Approver;
use App\Models\CachedMonthlyAttendance;
use App\Models\Employee;
use App\Models\EmployeeChangeSchedule;
use App\Models\EmployeeLeave;
use App\Models\EmployeeOb;
use App\Models\EmployeeOffset;
use App\Models\EmployeeOvertime;
use App\Models\EmployeeSchedule;
use App\Models\EmployeeWfh;
use App\Models\EmployeeTimeAdjustment;
use App\Models\Holiday;
use App\Models\Timelog;
use App\Models\WfhFloatedTimelog;
use App\Models\ProcessedTimelog;
use App\Models\ProcessedAbsent;
use App\Models\ProcessedLeave;
use App\Models\ProcessedTardiness;
use App\Models\ProcessedUndertime;
use App\Models\ProcessedOvertime;
use App\Models\ProcessedNightDifferential;
use App\Models\ProcessedHolidayRestdayDuty;
use App\Models\ProcessedDailyWorkHours;
use App\Models\ProcessedSchedule;
use App\Models\ProcessedOb;
use App\Models\PremiumOvertimePaySetting;
use App\Models\WorkSuspension;
use Carbon\Carbon;
use App\Models\PayrollSetting;
use App\Models\ProcessedOffsetAvailment;
use App\Models\RoleCompanyAccess;
use App\Models\TimelogEdit;
use App\Models\SalaryAndWages;
use App\Models\User;
use DateInterval;
use DatePeriod;
use DateTime;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Throwable;
use Carbon\CarbonPeriod;

class EmployeeAttendanceController extends Controller
{
    public function index(Request $request)
    {
        $user = Auth::user();
        $start_date = new DateTime($request->start_date);
        $end_date = new DateTime($request->end_date);

        // Get year-month for caching
        $yearMonth = $start_date->format('Y-m');

        // Check if we have cached data
        $cachedData = CachedMonthlyAttendance::forEmployeeAndMonth($user->employee_id, $yearMonth)->first();

        // If cache exists and is valid (less than 1 hour old), return cached data
        if ($cachedData && $cachedData->isValid()) {
            // Get the data (accessor will decode JSON automatically)
            $data = $cachedData->attendance_data;

            // Debug log
            \Log::info('Serving from cache', [
                'employee_id' => $user->employee_id,
                'year_month' => $yearMonth,
                'data_type' => gettype($data),
                'has_schedule' => isset($data['schedule']),
            ]);

            return response()->json(
                $data,
                200,
                ['X-Cache-Status' => 'HIT']
            );
        }

        // Otherwise, compute fresh data
        $result = $this->computeAttendanceData($user, $start_date, $end_date);

        // Debug log
        \Log::info('Computing fresh data', [
            'employee_id' => $user->employee_id,
            'year_month' => $yearMonth,
            'data_keys' => array_keys($result['data']),
        ]);

        // Cache the result
        CachedMonthlyAttendance::updateOrCreate(
            [
                'employee_id' => $user->employee_id,
                'year_month' => $yearMonth,
            ],
            [
                'start_date' => $start_date->format('Y-m-d'),
                'end_date' => $end_date->format('Y-m-d'),
                'attendance_data' => $result['data'], // Mutator will handle JSON encoding
                'present_days' => $result['present_days'],
                'computed_at' => now(),
            ]
        );

        return response()->json(
            $result['data'],
            200,
            ['X-Cache-Status' => 'MISS']
        );
    }

    /**
     * Force recompute and refresh cache
     */
    public function resyncCalendar(Request $request)
    {
        $user = Auth::user();
        $start_date = new DateTime($request->start_date);
        $end_date = new DateTime($request->end_date);
        $yearMonth = $start_date->format('Y-m');

        // Compute fresh data
        $result = $this->computeAttendanceData($user, $start_date, $end_date);

        // Debug log
        \Log::info('Resyncing calendar', [
            'employee_id' => $user->employee_id,
            'year_month' => $yearMonth,
            'data_keys' => array_keys($result['data']),
        ]);

        // Update cache
        CachedMonthlyAttendance::updateOrCreate(
            [
                'employee_id' => $user->employee_id,
                'year_month' => $yearMonth,
            ],
            [
                'start_date' => $start_date->format('Y-m-d'),
                'end_date' => $end_date->format('Y-m-d'),
                'attendance_data' => $result['data'], // Mutator will handle JSON encoding
                'present_days' => $result['present_days'],
                'computed_at' => now(),
            ]
        );

        return response()->json(
            $result['data'],
            200,
            ['X-Cache-Status' => 'RESYNCED']
        );
    }

    /**
     * Compute attendance data (original logic)
     */
    private function computeAttendanceData($user, $start_date, $end_date)
    {
        set_time_limit(500);
        ini_set('memory_limit', '1024M');

        $end_date->modify('+1 day'); // Include the end date in the range

        // Check if employee is always present
        $isAlwaysPresent = $this->alwaysPresent($user->employee_id);

        // Create a DatePeriod object
        $period = new DatePeriod($start_date, new DateInterval('P1D'), $end_date);

        $presentDays = 0;
        $data = [];
        $company_id = $user->employees->company_id;
        foreach ($period as $date) {
            $formattedDate = $date->format('Y-m-d');

            // Get Timelogs
            $timelogs = $this->getTimelog($formattedDate, $user->employees->time_keeping_id);
            $this->addTimelogData($data, $timelogs, $formattedDate);

            // Get Time Adjustment
            $timeAdjustment = $this->getTimeAdjustments($formattedDate, $user->employee_id);
            $this->addTimeAdjustmentData($data, $timeAdjustment, $formattedDate);

            // Get Schedule
            $schedule = $this->getSchedule($formattedDate, $user->employee_id);
            $this->addScheduleData($data, $schedule, $formattedDate, $user->employee_id);

            // Get Holiday
            $holiday = $this->getHoliday($formattedDate, $user->employees, $schedule);
            $this->addHolidayData($data, $holiday, $formattedDate);

            // Get Work Suspension
            $workSuspension = $this->getWorkSuspension($formattedDate);
            $this->addWorkSuspensionData($data, $workSuspension, $formattedDate);

            // GET WFH
            $wfhRecord = EmployeeWfh::whereNotNull('attachment')
                ->where(['employee_id'=> $user->employee_id, 'date'=>$formattedDate, 'status'=>2, 'validated'=>1])
                ->first();

            $this->addWfhData($data, $wfhRecord, $formattedDate);
            $validWFH = $wfhRecord !== null;

            // Get Leave
            $leave = $this->getLeave($formattedDate, $user->employee_id);
            if(!$holiday){
                $this->addLeaveData($data, $leave, $formattedDate);
            }

            // Get OB
            $ob = $this->getOB($formattedDate, $user->employee_id);
            $this->addOBData($data, $ob, $formattedDate);

            // Get Offset Availment
            $offsetAvailment = $this->getOffsetAvailment($formattedDate, $user->employee_id);
            $this->addOffsetAvailmentData($data, $offsetAvailment, $formattedDate);

            // Get Overtime
            $overtime = $this->getOvertime($formattedDate, $user->employee_id, $start_date, $end_date);
            $this->addOvertimeData($data, $overtime, $formattedDate);

            if(!$isAlwaysPresent){
                // Check Tardiness
                $halfDayLeave = $leave && ($leave->half_day == 1 || $leave->half_day == 2);
                $wholeDayLeave = $leave && $leave->hours >= 8;

                if(!$holiday){
                    $tardiness = $this->getTardiness($timelogs, $schedule, $halfDayLeave, $ob, $offsetAvailment,
                    $user->employees->classification_id, $wholeDayLeave,$company_id);
                    $this->addTardinessData($data, $tardiness, $formattedDate);
                }

                // Get Undertime
                if(!$holiday){
                    $undertime = $this->getUndertime($timelogs, $schedule, $workSuspension, $formattedDate, $ob, $offsetAvailment, $wfhRecord, $halfDayLeave);
                    $this->addUndertimeData($data, $undertime, $formattedDate);
                }

                if(!$ob && !$offsetAvailment){
                    $this->addAbsenceData($data, $timelogs, $leave, $holiday, $schedule, $formattedDate);
                }
            }

            // Check if present
            if ($this->isPresent($timelogs, $leave, $holiday, $ob, $validWFH, $schedule, $formattedDate)) {
                $presentDays++;
            }
        }

        return [
            'data' => $data,
            'present_days' => $presentDays,
        ];
    }

    public function getDailyAttedance()
    {
        $user = Auth::user();

        $day = date('d');
        $start_date = '';
        $end_date = '';

        // dd($day);
        if($day >= 6 && $day <= 20){
            $start_date = new DateTime(date('Y-m-6'));
            $end_date = new DateTime(date('Y-m-20'));
        } else if ($day >= 21 && $day >= 5){
            $start_date = new DateTime(date('Y-m-21'));
            $end_date = new DateTime(date('Y-m-5'));
            $end_date->modify('+1 month');
        }

        // Create a DatePeriod object
        $period = new DatePeriod($start_date, new DateInterval('P1D'), $end_date);

        $presentDays = 0;

        $data = [];

        foreach ($period as $date) {
            $formattedDate = $date->format('Y-m-d');
            // Get Timelogs
            $timelogs = $this->getTimelog($formattedDate, $user->employee_id);
            $this->addTimelogData($data, $timelogs, $formattedDate);
        }

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

    public function addTimelogData(&$data, $timelogs, $date)
    {
        if ($timelogs) {
            foreach ($timelogs as $timelog) {
                $data['timelog'][] = [
                    'title' => $timelog->in_out
                        ? ($timelog->in_out == "I"
                            ? date('H:ia', strtotime($timelog->datetimelog)) . " In"
                            : date('H:ia', strtotime($timelog->datetimelog)) . " Out")
                        : "",
                    'date' => $date,
                    'className' => (!empty($timelog->adjustment)
                        ? "bg-time-adjustment text-white text-[15px]"
                        : ($timelog->in_out
                            ? ($timelog->in_out == "I"
                                ? 'bg-time-in text-white text-[15px]'
                                : 'bg-time-out text-white text-[15px]')
                            : ""))
                ];
            }
        }

    }

    public function addScheduleData(&$data, $schedule, $date, $employee_id)
    {
        $dayoff = EmployeeChangeSchedule::where('dayoff_date', $date)->where('status', 2)->where('employee_id', $employee_id)->where('validated', 1)->first();
        $employee_change_schedule = EmployeeChangeSchedule::where(fn($q) =>
            $q->whereNull('date_to')
                ->where('date', $date)
                ->orWhere(fn($q) =>
                    $q->whereNotNull('date_to')
                        ->where('date', '<=', $date)
                        ->where('date_to', '>=', $date)
                )
                ->where('status', 2)
                ->where('validated', 1)
        )->where('status', 2)
        ->where('validated', 1)
        ->where('employee_id', $employee_id)->first();

        if(!empty($dayoff)){
            $data['schedule'][] = [
                'id' => $date,
                'date' => $date,
                'title' => "Day Off",
                'className' => 'bg-dayoff text-white',
            ];
        }
        else if(!empty($employee_change_schedule)){
            $data['schedule'][] = [
                'id' => $date,
                'date' => $date,
                'title' => date('H:i', strtotime($employee_change_schedule->from_time)) . '-' . date('H:i', strtotime($employee_change_schedule->to_time)),
                'className' => 'bg-schedule text-white',
            ];
        }

        if ($schedule && empty($dayoff) && empty($employee_change_schedule)) {
            $dayOfWeek = date('l', strtotime($date));
            $daysArray = explode(',', $schedule->schedule->day_off);
            $daysShiftingArray = explode(',', $schedule->schedule->shifting_day);

            $daysWFHArray = explode(',', $schedule->schedule->wfh);
            $daysCWSArray = explode(',', $schedule->schedule->cws_day);

            $data['schedule'][] = [
                'id' => $date,
                'date' => $date,
                'title' => in_array($dayOfWeek, $daysArray)
                    ? "Day Off"
                    : (
                        in_array($dayOfWeek, $daysWFHArray)
                            ? date('H:i', strtotime($schedule->schedule->from_time)) . '-' . date('H:i', strtotime($schedule->schedule->to_time)) . ' (WFH)'
                            : (
                                in_array($dayOfWeek, $daysCWSArray)
                                    ? date('H:i', strtotime($schedule->schedule->cws_from_time)) . '-' . date('H:i', strtotime($schedule->schedule->cws_to_time))
                                    : (
                                        in_array($dayOfWeek, $daysShiftingArray)
                                            ? date('H:i', strtotime($schedule->schedule->shifting_from_time)) . '-' . date('H:i', strtotime($schedule->schedule->shifting_to_time))
                                            : date('H:i', strtotime($schedule->schedule->from_time)) . '-' . date('H:i', strtotime($schedule->schedule->to_time))
                                    )
                            )
                    ),
                'start' => $date,
                'className' => in_array($dayOfWeek, $daysArray) ? 'bg-dayoff text-white' : 'bg-schedule text-white',
            ];

        }
    }

    public function addTimeAdjustmentData(&$data, $timeAdjustments, $date)
    {
        if ($timeAdjustments->isNotEmpty()) {
            foreach($timeAdjustments as $timeAdjustment){
                $inOrOut = '';

                if($timeAdjustment->in_out == 0){
                    $inOrOut = " In";
                } else {
                    $inOrOut = " Out";
                }

                $data['timeAdjustment'][] = [
                    'title' => date('H:ia', strtotime($timeAdjustment->time)).$inOrOut,
                    'date' => $date,
                    'className' => 'bg-time-adjustment text-white',
                ];
            }
            // dd($timeAdjustment[0]);
            // $data['timeAdjustment'][] = [
            //     'title' => $timeAdjustment->time .' '. $timeAdjustment->in_out == 1 ? "IN" : "OUT",
            //     'date' => $date,
            //     'className' => 'bg-time-adjustment text-white',
            // ];
        }
    }

    public function addHolidayData(&$data, $holiday, $date)
    {
        if ($holiday) {
            $data['holiday'][] = [
                'title' => $holiday->name,
                'from_date' => $holiday->from_date,
                'to_date' => $holiday->to_date,
                'date' => $date,
                'recurring' => $holiday->recurring,
                'className' => 'bg-holiday text-white',
            ];
        }
    }

    public function addWorkSuspensionData(&$data, $workSuspension, $date)
    {
        if ($workSuspension) {
            $data['workSuspension'][] = [
                'title' => $workSuspension->reason,
                'from_date' => $workSuspension->date,
                'to_date' => $workSuspension->date,
                'date' => $date,
                'className' => 'bg-suspension text-white',
            ];
        }
    }

    public function addLeaveData(&$data, $leave, $date)
    {
        if ($leave) {
            $halfday = '';
            $without_pay = '';

            if($leave->half_day == 1){
                $halfday = ' (Half Day)';
            }

            if($leave->half_day == 2){
                $halfday = ' (Half Day)';
            }

            if($leave->without_pay == 1){
                $without_pay = ' (Absent)';
            }

            $data['leave'][] = [
                'title' => $leave->leave_type->name.$halfday.$without_pay,
                'from_date' => $leave->from_date,
                'to_date' => $leave->to_date,
                'date' => $date,
                'className' => 'bg-leave text-white',
            ];

            // dd($data);
        }
    }

    public function addTardinessData(&$data, $tardiness, $date)
    {
        if ($tardiness) {
            $data['tardiness'][] = [
                'title' => $tardiness.' minutes',
                'date' => $date,
                'className' => 'bg-tardiness text-white',
            ];
        }
    }

    public function addOvertimeData(&$data, $overtime, $date)
    {
        if ($overtime) {
            $data['overtime'][] = [
                'id' => $date,
                'date' => $date,
                'title' => date('H:i', strtotime($overtime->from_time)) . '-' . date('H:i', strtotime($overtime->to_time)),
                'start' => $date,
                'className' => 'bg-overtime text-white',
            ];
        }
    }

    public function addWfhData(&$data, $wfhRecord, $date)
    {
        if ($wfhRecord) {
            // dd($ob);
            $data['wfhRecord'][] = [
                'title' => $wfhRecord->hours.' HOURS (WFH)',
                'date' => $date,
                'className' => 'bg-wfh text-white',
            ];
        }
    }

    public function addOBData(&$data, $ob, $date)
    {
        if ($ob) {
            // dd($ob);
            $data['ob'][] = [
                'title' => date('H:i A', strtotime($ob->from_time)).' - '.date('H:i A', strtotime($ob->to_time)),
                'date' => $date,
                'className' => 'bg-ob text-white',
            ];
        }
    }

    public function addOffsetAvailmentData(&$data, $offsetAvailment, $date)
    {
        if ($offsetAvailment) {
            // dd($ob);
            $data['offsetAvailment'][] = [
                'title' => date('H:i A', strtotime($offsetAvailment->from_time)).' - '.date('H:i A', strtotime($offsetAvailment->to_time)),
                'date' => $date,
                'className' => 'bg-offset-availment text-white',
            ];
        }
    }

    public function addUndertimeData(&$data, $undertime, $date)
    {
        if ($undertime) {
            $data['undertime'][] = [
                'title' => $undertime.' minutes',
                'date' => $date,
                'className' => 'bg-undertime text-white',
            ];
        }
    }

    private function alwaysPresent($employee_id){
        $isAlwaysPresent = false;
        $data = SalaryAndWages::where('employee_id',$employee_id)->first();
        if($data->always_present ==1){
            $isAlwaysPresent = true;
        }
        return $isAlwaysPresent;
    }

    public function addAbsenceData(&$data, $timelogs, $leave, $holiday, $schedule, $date)
    {
        $dayoff = EmployeeChangeSchedule::where('dayoff_date', $date)->where('status', 2)->where('validated', 1)->first();

        // if($holiday){
        //     dd($holiday);
        // }
        if($holiday && $holiday['isAbsentBeforeHoliday'] == true){
            $dayOfWeek = date('l', strtotime($date));
            $daysArray = explode(',', $schedule->schedule->day_off); // Convert string to array

            if (!in_array($dayOfWeek, $daysArray) && new DateTime($date) < new DateTime()) {
                $data['absent'][] = [
                    'title' => "Absent",
                    'date' => $date,
                    'className' => 'bg-absent text-white',
                ];
            }
        }

        if (!$timelogs->count() && !$leave && !$holiday && $schedule && empty($dayoff)) {
            $dayOfWeek = date('l', strtotime($date));
            $daysArray = explode(',', $schedule->schedule->day_off); // Convert string to array

            if (!in_array($dayOfWeek, $daysArray) && new DateTime($date) < new DateTime()) {
                $data['absent'][] = [
                    'title' => "Absent",
                    'date' => $date,
                    'className' => 'bg-absent text-white',
                ];
            }
        }
    }

    public function getSchedule($date, $employee_id)
    {
        $dayOfWeek = Carbon::parse($date)->format('l');
        $employeeSchedule = EmployeeSchedule::with('schedule')
            ->where('date_from', '<=', $date)
            ->where('date_to', '>=', $date)
            ->where('effectivity_date', '<=', $date)
            ->where('employee_id', '=', $employee_id)
            ->whereHas('schedule')
            ->first();
            
        if($employeeSchedule == null){
            $employeeSchedule = EmployeeSchedule::with('schedule')
            ->where('effectivity_date', '<=', $date)
            ->where('employee_id', '=', $employee_id)
            ->orderBy('effectivity_date', 'desc')
            ->whereHas('schedule')
            ->first();
        }
        
        if($employeeSchedule == null){
            return null; // Changed from 'continue' to 'return null'
        }
        
        $employee_change_schedule = EmployeeChangeSchedule::where(fn($q) =>
            $q->whereNull('date_to')
                ->where('date', $date)
                ->orWhere(fn($q) =>
                    $q->whereNotNull('date_to')
                        ->where('date', '<=', $date)
                        ->where('date_to', '>=', $date)
                )
                ->where('status', 2)
                ->where('validated', 1)
        )->where('status', 2)
        ->where('validated', 1)
        ->where('employee_id', $employee_id)->first();
        
        if (!empty($employeeSchedule) && isset($employeeSchedule->schedule['shifting_day'])) {
            if ($dayOfWeek == $employeeSchedule->schedule['shifting_day']) {
                $employeeSchedule->schedule['from_time'] = $employeeSchedule->schedule['shifting_from_time'];
                $employeeSchedule->schedule['to_time'] = $employeeSchedule->schedule['shifting_to_time'];
            }
        }
        
        if(!empty($employee_change_schedule)){
            $employeeSchedule->schedule['from_time'] = $employee_change_schedule['from_time'];
            $employeeSchedule->schedule['to_time'] = $employee_change_schedule['to_time'];
            $employeeSchedule->schedule['isChangeSchedule'] = true;
        }
        
        return $employeeSchedule;
    }

    public function getHoliday($date, $employee, $schedule)
    {
        $data = Holiday::where(fn($query) =>
            $query->where('from_date', '<=', $date)
                ->where('to_date', '>=', $date)
                ->where('enabled', 1)
        )
        ->orWhere(fn($query) =>
            $query->where('recurring', 1) // Assuming a `recurring` column
                ->where(DB::raw('DATE_FORMAT(from_date, "%m-%d")'), '=', Carbon::parse($date)->format('m-d'))
                ->where('enabled', 1)
        )
        ->first();

        if($data && $data->holiday_type==3) {
            if(empty($employee->work_location_id) || $employee->work_location_id != $data->locality) {
                $data = null;
            }
        }

        if($schedule && $data){
            $daysArray = explode(',', $schedule->schedule->day_off); // Convert string to array
            $date = $date; // Example starting date
            $origDate = $date; // Example starting date

            do {
                $date = date('Y-m-d', strtotime($date . ' -1 day'));
                $dayOfWeek = date('l', strtotime($date)); // Get the day of the week
                $timelog = $this->getTimelog($date, $employee->time_keeping_id);
                $ob = $this->getOB($date, $employee->employee_id);

                $checkIfPreviousDateIsHoliday = Holiday::where(fn($query) =>
                    $query->where('from_date', '<=', $date)
                        ->where('to_date', '>=', $date)
                        ->where('enabled', 1)
                )
                ->orWhere(fn($query) =>
                    $query->where('recurring', 1) // Assuming a `recurring` column
                        ->where(DB::raw('DATE_FORMAT(from_date, "%m-%d")'), '=', Carbon::parse($date)->format('m-d'))
                        ->where('enabled', 1)
                )
                ->first();

            } while (
                in_array($dayOfWeek, $daysArray) ||
                (
                    $checkIfPreviousDateIsHoliday &&
                    // $checkIfPreviousDateIsHoliday->holiday_type != 1 &&
                    ($timelog->filter(fn($tl) => $tl->in_out=='I')->isEmpty() && $timelog->filter(fn($tl) => $tl->in_out=='O')->isEmpty() && !$ob)
                )
            ); // Continue if it's in $daysArray


            $newDate = $date;

            $leave = $this->getLeave($newDate, $employee->employee_id);
            $timelogs = $this->getTimelog($newDate, $employee->time_keeping_id);
            $ob = $this->getOB($newDate, $employee->employee_id);
            $offsetAvailment = $this->getOffsetAvailment($newDate, $employee->employee_id);
            $schedule = $this->getSchedule($newDate, $employee->employee_id);
            // if($origDate == '2024-12-30'){
            //     dd($timelogs->filter(fn($tl) => $tl->in_out=='O')->isEmpty());
            // }
            $dayoff = EmployeeChangeSchedule::where('dayoff_date', $newDate)->where('status', 2)->where('employee_id', $employee->employee_id)->where('validated', 1)->first();

            if ($data && ($timelogs->filter(fn($tl) => $tl->in_out=='O')->isEmpty() || $timelogs->filter(fn($tl) => $tl->in_out=='I')->isEmpty()) && !$leave && $schedule && empty($dayoff) && !$ob && !$offsetAvailment) { // && $data->holiday_type != 1 && !$isPreviousHolidayRegular
                $data['isAbsentBeforeHoliday'] = true;
            } else if($data && $leave && ($leave['without_pay'] == 1) && !$timelogs->count()) // && $data->holiday_type != 1 && !$isPreviousHolidayRegular
            {
                $data['isAbsentBeforeHoliday'] = true;
            }
        }

        return $data;
    }

    public function getWorkSuspension($date)
    {
        return WorkSuspension::where('date', '<=', $date)
            ->where('date', '>=', $date)
            ->where('enabled', '=', 1)
            ->first();
    }

    public function getLeave($date, $employee_id)
    {
        return EmployeeLeave::with('leave_type')
            ->where('employee_id', '=', $employee_id)
            ->where('date_from', '<=', $date)
            ->where('date_to', '>=', $date)
            ->where('enabled', '=', 1)
            ->where('status', '=', 2)
            ->where('validated', '=', 1)
            ->first();
    }

    // public function getTimelog($date, $employee_id)
    // {
    //     return Timelog::select('employee_id', DB::raw("MIN(datetimelog) AS datetimelog"), 'time_keeping_id', 'in_out')->whereDate('datetimelog', $date)
    //         ->where(fn($query) => $query->where('employee_id', $employee_id)
    //             ->orWhere('time_keeping_id', $employee_id))
    //         ->groupBy('employee_id', DB::raw("DATE(datetimelog)"), 'time_keeping_id', 'in_out')
    //         ->get();

    // }
    public function getTimelog($date, $employee_id)
    {
        // Get the primary timelog records for the specified date and employee
        $timelog = $this->getPrimaryTimelog($date, $employee_id);

        // if ($date == '2025-12-02') {
        //     dd($timelog);
        // }
        // Get any applicable time adjustments
        $timeAdjustments = $this->getTimeAdjustments($date, $employee_id);

        // if($date == '2025-12-11'){
        //     dd($timelog);
        // }

        if ($timeAdjustments->isNotEmpty()) {
            // Get the time adjustments for IN and OUT
            $time_in = $this->getTimeAdjustmentByType($timeAdjustments, 0);
            $time_out = $this->getTimeAdjustmentByType($timeAdjustments, 1);

            // Create a map of the existing timelogs by in_out type for quick lookup
            $timelogMap = $timelog->keyBy('in_out');

            // If there's a time adjustment for IN, update or add the IN timelog
            if ($time_in) {
                $timelogMap['I'] = (object)[
                    'employee_id' => $employee_id,
                    'datetimelog' => $time_in,
                    'time_keeping_id' => $employee_id, // Assuming time_keeping_id is the same as employee_id
                    'in_out' => 'I',
                    'adjustment' => true,
                    'priority' => 1,
                ];
            }

            // If there's a time adjustment for OUT, update or add the OUT timelog
            if ($time_out) {
                $timelogMap['O'] = (object)[
                    'employee_id' => $employee_id,
                    'datetimelog' => $time_out,
                    'time_keeping_id' => $employee_id, // Assuming time_keeping_id is the same as employee_id
                    'in_out' => 'O',
                    'adjustment' => true,
                    'priority' => 1,
                ];
            }

            // Convert the map back to a collection
            $timelog = collect($timelogMap->values());
        }

        // Get any applicable time adjustments
        // DB::enableQueryLog();
        $alteredTimelog = $this->getTimelogEdits($date, $employee_id);

        if ($alteredTimelog->isNotEmpty()) {
            $time_in = $this->getTimelogEditByType($alteredTimelog, "I");
            $time_out = $this->getTimelogEditByType($alteredTimelog, "O");
            $latestOut = $alteredTimelog->where('in_out', 'O')->sortByDesc('datetimelog')->first();
            $latestIn = $alteredTimelog->where('in_out', 'I')->sortByDesc('datetimelog')->first();

            $alteredTimelog->each(function ($log) use (&$timelog, $time_in, $time_out, $latestOut, $latestIn) {
                $logData = (object)[
                    'employee_id' => $log->employee_id,
                    'datetimelog' => $this->getAlteredTime($log, $time_in, $time_out),
                    'time_keeping_id' => $log->time_keeping_id,
                    'in_out' => $log->in_out,
                    'priority' => 1,
                ];
                // Add the entry back
                $timelog->push($logData);
            });

            // Ensure there is an "I" if there is an "O"
            $hasIn = $timelog->where('in_out', 'I')->isNotEmpty();
            $hasOut = $timelog->where('in_out', 'O')->isNotEmpty();
            if ($hasOut && !$hasIn && $latestIn) {
                // If "O" exists but no "I", add the latest "I"
                $timelog->push((object)[
                    'employee_id' => $latestIn->employee_id,
                    'datetimelog' => $latestIn->datetimelog,
                    'time_keeping_id' => $latestIn->time_keeping_id,
                    'in_out' => 'I',
                    'priority' => 0,
                ]);
            }

            $timelog = $timelog->map(function ($item) {
                // Convert Eloquent model to stdClass
                if ($item instanceof \Illuminate\Database\Eloquent\Model) {
                    $item = (object) $item->getAttributes();
                }

                // Ensure it's a stdClass
                if (is_array($item)) {
                    $item = (object) $item;
                }

                // Set priority = 0 if it doesn't exist
                if (!property_exists($item, 'priority')) {
                    $item->priority = 0;
                }

                return $item;
            });

            // Split collection into "I" and "O" entries
            // $inEntries = $timelog->where('in_out', 'I')->sortBy('datetimelog')->values();
            // $outEntries = $timelog->where('in_out', 'O')->sortByDesc('datetimelog')->values();
            /**sort by priority first, then datetimelogs */
            $inEntries = $timelog->where('in_out', 'I')
                ->sortBy(function ($item) {
                    return [-$item->priority, $item->datetimelog];
                })
                ->values();

            $outEntries = $timelog->where('in_out', 'O')
                ->sortBy(function ($item) {
                    return [-$item->priority, $item->datetimelog];
                })
                ->values();

            // Merge both collections with "I" entries first (in ascending order) followed by "O" entries (in descending order)
            $timelog = $inEntries->concat($outEntries);


        }
        // if ($date == '2025-12-02') {
        //     dd($timelog);
        // }
        return $timelog;
    }

    // Helper to retrieve primary timelog entries
    private function getPrimaryTimelog($date, $employee_id)
    {
        // return Timelog::select('employee_id', 'time_keeping_id', 'in_out', DB::raw("CASE WHEN in_out = 'I' THEN MIN(datetimelog) ELSE MAX(datetimelog) END AS datetimelog"))
        // ->whereDate('datetimelog', $date)
        // ->where(fn($query) => $query->where('employee_id', $employee_id)
        //     ->orWhere('time_keeping_id', $employee_id))
        // ->groupBy('employee_id', 'time_keeping_id', 'in_out')
        // ->get();
        $data = [];
        // $payrollSetting = PayrollSetting::first();
        $employee = Employee::where('employee_id',$employee_id)->first();
        $company_id = $employee->company_id;
         $payrollSetting = PayrollSetting::where('company_id',$company_id)->first();
        if(!$payrollSetting) {
            $payrollSetting = PayrollSetting::whereNull('company_id')->first();
        }
        $nextDayLastTimeout = $payrollSetting->next_day_last_timeout ?? '00:00:00';
        $nextDay = Carbon::parse($date)->addDay()->format('Y-m-d');
        $timelogIn = Timelog::select('employee_id', 'time_keeping_id', 'in_out', DB::raw("MIN(datetimelog) AS datetimelog"))
            ->whereDate('datetimelog', $date)
            ->where('in_out', 'I')
            ->where(fn($query) => $query->where('employee_id', $employee_id)
                ->orWhere('time_keeping_id', $employee_id))
            ->groupBy('employee_id', 'time_keeping_id', 'in_out')
            ->first();

        // Check if there's a record greater than 5:00 AM
        $timelogInAfter5AM = Timelog::select('employee_id', 'time_keeping_id', 'in_out', DB::raw("MIN(datetimelog) AS datetimelog"))
            ->whereDate('datetimelog', $date)
            ->where('in_out', 'I')
            ->where('datetimelog', '>=', Carbon::parse($date . ' 05:00:00'))
            ->where(fn($query) => $query->where('employee_id', $employee_id)
                ->orWhere('time_keeping_id', $employee_id))
            ->groupBy('employee_id', 'time_keeping_id', 'in_out')
            ->first();

        // Use the 5:00 AM record if it exists, otherwise keep the original
        $timelogIn = $timelogInAfter5AM ?: $timelogIn;

        if($timelogIn) {
            $timeIn = $timelogIn->datetimelog;
            $timeAdjustments = $this->getTimeAdjustments($date, $employee_id);

            if($timeAdjustments->isNotEmpty()) {
                $adjustedTimeIn = $this->getTimeAdjustmentByType($timeAdjustments, 0);
                if($adjustedTimeIn) {
                    $timelogIn->datetimelog = $adjustedTimeIn;
                }
            } 

            $timeIn = Carbon::parse($timelogIn->datetimelog)->format('Y-m-d H:i:s');

            // DB::enableQueryLog();
            $timelogOut = Timelog::select('employee_id', 'time_keeping_id', 'in_out', DB::raw("MIN(datetimelog) AS datetimelog"))
                ->whereDate('datetimelog', $date)
                ->where('datetimelog', '>=', \Carbon\Carbon::parse($timeIn)->subSeconds(50))
                ->where('in_out', 'O')
                ->where(fn($query) => $query->where('employee_id', $employee_id)
                    ->orWhere('time_keeping_id', $employee_id))
                ->groupBy('employee_id', 'time_keeping_id', 'in_out')
                ->first();

            // if ($date == '2025-12-11') {
            //     dd($timeIn);
            // }
            // if ($date == '2025-12-02') {
            //     DB::enableQueryLog();
            //     $timelogOut = Timelog::select('employee_id', 'time_keeping_id', 'in_out', DB::raw("MIN(datetimelog) AS datetimelog"))
            //     ->whereDate('datetimelog', $date)
            //     ->where('datetimelog', '>=', \Carbon\Carbon::parse($timeIn)->subSeconds(50))
            //     ->where('in_out', 'O')
            //     ->where(fn($query) => $query->where('employee_id', $employee_id)
            //         ->orWhere('time_keeping_id', $employee_id))
            //     ->groupBy('employee_id', 'time_keeping_id', 'in_out')
            //     ->first();

            //     dd(DB::getQueryLog());
            //     dd($date.'sssss');
            // }

        } else {
            $timelogOut = Timelog::select('employee_id', 'time_keeping_id', 'in_out', DB::raw("MIN(datetimelog)AS datetimelog"))
            ->whereDate('datetimelog', $date)
            ->where('datetimelog', '>', $date.' '.$nextDayLastTimeout)
            ->where('in_out', 'O')
            ->where(fn($query) => $query->where('employee_id', $employee_id)
                ->orWhere('time_keeping_id', $employee_id))
            ->groupBy('employee_id', 'time_keeping_id', 'in_out')
            ->first();

            // if ($date == '2025-12-11') {
            //     dd($timelogOut);
            // }
        }
        if(!$timelogOut) {
            $timelogOut = Timelog::select('employee_id', 'time_keeping_id', 'in_out', DB::raw("MIN(datetimelog)AS datetimelog"))
            ->whereDate('datetimelog', $nextDay)
            ->where('datetimelog', '<', $nextDay.' '.$nextDayLastTimeout)
            ->where('in_out', 'O')
            ->where(fn($query) => $query->where('employee_id', $employee_id)
                ->orWhere('time_keeping_id', $employee_id))
            ->groupBy('employee_id', 'time_keeping_id', 'in_out')
            ->first();
        }

        // if ($date == '2025-12-02') {
        //     dd($timelogOut);
        // }

        return collect([])->when($timelogIn, fn($collection) => $collection->merge([$timelogIn]))
                      ->when($timelogOut, fn($collection) => $collection->merge([$timelogOut]));

    }

    public function getTimeAdjustments($date, $employee_id)
    {
        return EmployeeTimeAdjustment::select('employee_id', 'date', 'time', 'in_out')
            ->where('employee_id', $employee_id)
            ->where('date', $date)
            ->where('status', 2)
            ->where('validated', 1)
            ->get();
    }

    private function getTimelogEdits($date, $employee_id)
    {
        return TimelogEdit::select('employee_id', 'date', 'time', 'in_out')
            ->where('employee_id', $employee_id)
            ->where('date', $date)
            ->where('approved', 1)
            ->get();
    }

    // Helper to filter time adjustments by in/out type
    private function getTimeAdjustmentByType($timeAdjustments, int $type)
    {
        return $timeAdjustments->filter(fn($item) => $item->in_out === $type)
            ->map(fn($item) => $item->date . ' ' . $item->time)
            ->first();
    }

    private function getTimelogEditByType($timelogEdit, string $type)
    {
        return $timelogEdit->filter(fn($item) => $item->in_out === $type)
            ->map(fn($item) => $item->date . ' ' . $item->time)
            ->first();
    }

    // Helper to get adjusted time if available, else fallback to original
    private function getAdjustedTime($log, $time_in, $time_out)
    {
        return match ($log->in_out) {
            'I' => $time_in ?? $log->datetimelog,
            'O' => $time_out ?? $log->datetimelog,
            default => $log->datetimelog,
        };
    }

    // Helper to get adjusted time if available, else fallback to original
    private function getAlteredTime($log, $time_in, $time_out)
    {
        return match ($log->in_out) {
            'I' => $time_in ?? $log->datetimelog,
            'O' => $time_out ?? $log->datetimelog,
            default => $log->datetimelog,
        };
    }

    public function getOB($date, $employee_id)
    {
        return EmployeeOb::where('employee_id', '=', $employee_id)
            ->where('date_from', '=', $date)
            // ->where('date_from', '>=', $date)
            ->where('enabled', '=', 1)
            ->where('status', '=', 2)
            ->where('validated', 1)
            ->first();
    }

    public function getOffsetAvailment($date, $employee_id)
    {
        return EmployeeOffset::where('employee_id', '=', $employee_id)
            ->where('date_from', '<=', $date)
            ->where('date_to', '>=', $date)
            ->where('enabled', '=', 1)
            ->where('status', '=', 2)
            ->where('validated', 1)
            ->first();
    }

    public function getTardiness($timelogs, $schedule, $halfDayLeave=false, $ob, $offsetAvailment, $classification_id, $wholeDayLeave, $company_id)
    {
        if($wholeDayLeave){
            return false;
        }

        // $payrollSetting = PayrollSetting::first();
         $payrollSetting = PayrollSetting::where('company_id',$company_id)->first();
        if(!$payrollSetting) {
            $payrollSetting = PayrollSetting::whereNull('company_id')->first();
        }
        if ((($timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty()) && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() && $schedule) || ($ob && $schedule)) {
            $firstTimelog = $timelogs->filter(fn($tl) => $tl->in_out=='I')->first();
            // $lastTimelog = $timelogs->filter(fn($tl) => $tl->in_out=='O')->first();

            if($ob){
                $date = Carbon::parse($ob->date_from)->format('Y-m-d');

                if(empty($firstTimelog)){
                    $firstTimelog = (object) [ 'datetimelog' => Carbon::parse($date.' '.$ob->from_time)->format('Y-m-d H:i:s') ];

                } else if (!empty($firstTimelog)) {
                    if(new DateTime($date.' '.$ob->from_time) < new DateTime($firstTimelog->datetimelog)){
                        $firstTimelog = (object) [ 'datetimelog' => Carbon::parse($date.' '.$ob->from_time)->format('Y-m-d H:i:s') ];
                    }
                }
            } else {
                $date = Carbon::parse($firstTimelog->datetimelog)->format('Y-m-d');
            }

            $dayOfWeek = date('l', strtotime($date));
            $daysArray = explode(',', $schedule->schedule->day_off);

            $daysWFHArray = explode(',', $schedule->schedule->wfh);
            $daysCWSArray = explode(',', $schedule->schedule->cws_day);
            $schedule_in = "";
            $lunchBreak = $schedule->schedule->lunch_break ?? null;
            if(in_array($dayOfWeek,$daysCWSArray) && !$schedule->schedule['isChangeSchedule']) {
                $schedule_in = $schedule->schedule->cws_from_time;
                $lunchBreak = $schedule->schedule->cws_lunch_break ?? ($schedule->schedule->lunch_break ?? null);
            } elseif(!in_array($dayOfWeek, $daysArray)) {
                $schedule_in = $schedule->schedule->from_time;
            }

            if(($timelogs->filter(fn($tl) => $tl->in_out=='O')->isEmpty() && (!$ob && !$offsetAvailment)) && $schedule)
            {
                $schedule_out = "";

                if(in_array($dayOfWeek,$daysCWSArray)) {
                    $schedule_out = $schedule->schedule->cws_to_time;

                } elseif(!in_array($dayOfWeek, $daysArray)) {
                    $schedule_out = $schedule->schedule->to_time;

                    // $schedTimeIn = new DateTime($date . ' ' . $schedule_in);
                    // $schedTimeOut = new DateTime($date . ' ' . $schedule_out);

                    // // Calculate the difference between the two DateTime objects
                    // $interval = $schedTimeOut->diff($schedTimeIn);

                    // // Convert the interval to total minutes
                    // $totalMinutes = ($interval->h * 60) + $interval->i;

                    // // Use floor() if needed (though $totalMinutes is already an integer)
                    // $totalMinutes = floor($totalMinutes) - 60;

                    // // echo $employee_id;
                    // // $minutes = ($interval->h * 60) + $interval->i;

                    // return $totalMinutes;
                }

            }
            if ($ob && $ob->date_from == $date) {
                $obTimeStart = $date.' '.$ob->from_time;

                if (!$firstTimelog || new DateTime($obTimeStart) < new DateTime($firstTimelog->datetimelog)) {
                    $firstTimelog->datetimelog = $obTimeStart;
                }
            }

            if ($offsetAvailment && $offsetAvailment->date_from == $date) {
                $offsetAvailmentTimeStart = $date.' '.$offsetAvailment->from_time;

                if (!$firstTimelog || new DateTime($offsetAvailmentTimeStart) < new DateTime($firstTimelog->datetimelog)) {
                    $firstTimelog->datetimelog = $offsetAvailmentTimeStart;
                }
            }

            if ($firstTimelog && !empty($schedule_in)) {

                $firstTimelogTime = new DateTime($firstTimelog->datetimelog);
                // $lastTimelogTime = new DateTime($lastTimelog->datetimelog);

                $dayOfWeek = date('l', strtotime($date));
                $daysCWSArray = explode(',', $schedule->schedule->cws_day);

                if(in_array($dayOfWeek,$daysCWSArray) && !$schedule->schedule['isChangeSchedule']) {
                    $scheduledStartTime = new DateTime($date.' '.$schedule->schedule->cws_from_time);
                    $scheduledEndTime = new DateTime($date.' '.$schedule->schedule->cws_to_time);
                } else {
                    $scheduledStartTime = new DateTime($date.' '.$schedule->schedule->from_time);
                    $scheduledEndTime = new DateTime($date.' '.$schedule->schedule->to_time);
                }


                // if($date == '2025-01-10'){
                //     dd([
                //         'firstTimelogTime' => $firstTimelog,
                //         'scheduledStartTime' => $scheduledStartTime,
                //         'isChangeSchedule' => $schedule->schedule['isChangeSchedule']
                //     ]);
                // }

                // Calculate the difference between first time log and scheduled start time
                $timeDifference = $firstTimelogTime->diff($scheduledStartTime);
                $hoursDifference = $timeDifference->h + ($timeDifference->days * 24);

                // Check if first time log is 3 hours greater than scheduled start time
                if ($firstTimelogTime > $scheduledStartTime && $hoursDifference >= 3 && $halfDayLeave) {
                    // Make scheduled start time half
                    $interval = $scheduledStartTime->diff($scheduledEndTime);
                    $halfTimeInterval = floor($interval->h / 2) * 3600 + floor($interval->i / 2) * 60;

                    // Create a new scheduled start time at the halfway point
                    $adjustedScheduledStartTime = clone $scheduledStartTime;
                    $adjustedScheduledStartTime->add(new DateInterval("PT{$halfTimeInterval}S"));

                    // if(!in_array($dayOfWeek,$daysCWSArray) && $schedule->schedule->cws_day != "") {
                        $adjustedScheduledStartTime = Carbon::instance($adjustedScheduledStartTime)->addHour();
                    // }

                    // For example, you might want to set this as the new scheduled start time:
                    $scheduledStartTime = $adjustedScheduledStartTime;
                }

                /**set default breaktime start and end */
                $breakTimeStartTime = new DateTime($date.' 12:00:00');
                $breakTimeEndTime = new DateTime($date.' 13:00:00');

                /**set break time start and end based on settings*/
                if($lunchBreak) {
                    $breakTimeStartTime = new DateTime($date.' '.$lunchBreak->start_break_time);
                    $breakTimeEndTime = new DateTime($date.' '.$lunchBreak->end_break_time);
                }
            // if($date=='2025-01-16') dd(['start' => $breakTimeStartTime, 'end' => $breakTimeEndTime]);

                $breakInterval = 0;
                if($firstTimelogTime>$breakTimeStartTime && $firstTimelogTime<$breakTimeEndTime) {
                    $interval = $breakTimeStartTime->diff($scheduledStartTime);
                    // if($date == '2025-01-17'){
                    //     dd($breakTimeStartTime);
                    // }
                } else if($firstTimelog> $breakTimeEndTime) {
                    $interval = $breakTimeStartTime->diff($scheduledStartTime);
                    $interval2 = $firstTimelogTime->diff($breakTimeEndTime);
                    $interval->h = $interval2->h;
                    $interval->i = $interval2->i;
                } else {
                    // Calculate the difference
                    $interval = $firstTimelogTime->diff($scheduledStartTime);
                    // if($date == '2025-01-15'){
                    //     dd($scheduledStartTime);
                    // }
                }

                /**If halfday leave */
                if($halfDayLeave) {
                    $workHours = $scheduledStartTime->diff($scheduledEndTime)->h - 1;

                    if($interval->h >= $workHours/2) { /**if the interval exceeds half day, this means that the leave is at the start of schedule thus the timelog is after leave, then change the scheduledStartTime and recompute intervals */
                        $decimalHours = ($workHours / 2) + 1;
                        $hours = floor($decimalHours); // whole hours
                        $minutes = ($decimalHours - $hours) * 60; // convert decimal to minutes

                        $interval = new DateInterval(sprintf('PT%dH%dM', $hours, $minutes));
                        $scheduledStartTime->add($interval);

                        $interval =  $firstTimelogTime->diff($scheduledStartTime);

                        $minutes = ($interval->h * 60) + $interval->i;

                        if($halfDayLeave && $minutes >= 59) {
                            return false;
                        }

                        return floor($minutes);
                        // $workHoursAttendended = $firstTimelogTime->diff($lastTimelogTime);

                        // if($workHoursAttendended->h >= 4){
                            //     return false;
                            // }
                    } else {
                            $grace_period = $payrollSetting->late_grace_period ?? 5;
                            if($classification_id == '3') {
                                $grace_period = $payrollSetting->late_grace_period_manager ?? 30;
                            }
                            $interval =  $firstTimelogTime->diff($scheduledStartTime);

                            if($scheduledStartTime->format('H:i:s') == $schedule_in){
                                $scheduledStartTime->add(new DateInterval('PT'.($grace_period+1).'M'));
                            }

                            if($firstTimelogTime >= $scheduledStartTime) { /**IF HALFDAY IN THE AFTERNOON */
                                $minutes = ($interval->h * 60) + $interval->i;
                                if($minutes >= 59) {
                                    return false;
                                }
                                return floor($minutes);
                                // if($date=='2025-01-17') dd($minutes);

                            }
                        }
                    }

                $grace_period = $payrollSetting->late_grace_period ?? 5;

                if($classification_id == '3')
                {
                    $grace_period = $payrollSetting->late_grace_period_manager ?? 30;

                    if(($halfDayLeave && $scheduledStartTime->format('H:i:s') == $schedule_in) || (!$halfDayLeave && $scheduledStartTime->format('H:i:s') == $schedule_in)){
                        $scheduledStartTime->add(new DateInterval('PT'.($grace_period).'M')); // Add 30 minutes grace period
                    }
                } else {
                    // if($date == '2025-01-15'){
                    //     dd($schedule_in);
                    // }
                    if(($halfDayLeave && $scheduledStartTime->format('H:i:s') == $schedule_in) || (!$halfDayLeave && $scheduledStartTime->format('H:i:s') == $schedule_in)){

                        $scheduledStartTime->add(new DateInterval('PT'.($grace_period).'M'));// Add 6 minutes grace period
                    }
                }

                //  if($date=='2025-01-07') dd(['timeIn' => $firstTimelogTime, 'schedStart'=>$scheduledStartTime, 'halfDay' => $halfDayLeave, 'class'=>$classification_id]);
                // if($classification_id == '3' && $scheduledStartTime == $schedule_in)
                // {
                //     $scheduledStartTime->add(new DateInterval('PT31M')); // Add 6 minutes grace period
                // } else if($classification_id < '3' && $scheduledStartTime == $schedule_in){
                //     $scheduledStartTime->add(new DateInterval('PT6M')); // Add 6 minutes grace period
                // }


                $firstTimelogTimeFormatted = $firstTimelogTime->format('H:i:s');
                $scheduledStartTimeFormatted = $scheduledStartTime->format('H:i:s');


                // if($date == '2025-01-10'){
                //     dd([
                //         'firstTimelogTime' => $firstTimelog,
                //         'scheduledStartTime' => $scheduledStartTime
                //     ]);
                // }
                
                $firstTimelogTime->setTime(
                    (int)$firstTimelogTime->format('H'),
                    (int)$firstTimelogTime->format('i'),
                    0
                );
                
                if ($firstTimelogTime > $scheduledStartTime) {

                    $minutes = ($interval->h * 60) + $interval->i;

                    // if($date == '2025-01-18'){
                    //     // dd($minutes);
                    //     dd(
                    //         [
                    //             'first_time_Log' => $firstTimelogTimeFormatted,
                    //             'schedule_start_Tiem' => $scheduledStartTimeFormatted
                    //         ]
                    //         );
                    // }
                    // if($halfDayLeave && $minutes >= 60) {
                    //     return false;
                    // }

                    return floor($minutes);
                }
            }
        }
        return false;
    }

    public function getTardinessHeadDisplay($timelogs, $schedule, $halfDayLeave=false, $ob, $offsetAvailment, $classification_id, $wholeDayLeave, $company_id)
    {
        if($wholeDayLeave){
            return false;
        }

        // $payrollSetting = PayrollSetting::first();
         $payrollSetting = PayrollSetting::where('company_id',$company_id)->first();
        if(!$payrollSetting) {
            $payrollSetting = PayrollSetting::whereNull('company_id')->first();
        }
        if ((($timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty()) && $schedule) || ($ob && $schedule)) {
            $firstTimelog = $timelogs->filter(fn($tl) => $tl->in_out=='I')->first();
            // $lastTimelog = $timelogs->filter(fn($tl) => $tl->in_out=='O')->first();

            if($ob){
                $date = Carbon::parse($ob->date_from)->format('Y-m-d');

                if(empty($firstTimelog)){
                    $firstTimelog = (object) [ 'datetimelog' => Carbon::parse($date.' '.$ob->from_time)->format('Y-m-d H:i:s') ];

                } else if (!empty($firstTimelog)) {
                    if(new DateTime($date.' '.$ob->from_time) < new DateTime($firstTimelog->datetimelog)){
                        $firstTimelog = (object) [ 'datetimelog' => Carbon::parse($date.' '.$ob->from_time)->format('Y-m-d H:i:s') ];
                    }
                }
            } else {
                $date = Carbon::parse($firstTimelog->datetimelog)->format('Y-m-d');
            }

            $dayOfWeek = date('l', strtotime($date));
            $daysArray = explode(',', $schedule->schedule->day_off);

            $daysWFHArray = explode(',', $schedule->schedule->wfh);
            $daysCWSArray = explode(',', $schedule->schedule->cws_day);
            $schedule_in = "";
            $lunchBreak = $schedule->schedule->lunch_break ?? null;
            if(in_array($dayOfWeek,$daysCWSArray) && !$schedule->schedule['isChangeSchedule']) {
                $schedule_in = $schedule->schedule->cws_from_time;
                $lunchBreak = $schedule->schedule->cws_lunch_break ?? ($schedule->schedule->lunch_break ?? null);
            } elseif(!in_array($dayOfWeek, $daysArray)) {
                $schedule_in = $schedule->schedule->from_time;
            }

            if(($timelogs->filter(fn($tl) => $tl->in_out=='O')->isEmpty() && (!$ob && !$offsetAvailment)) && $schedule)
            {
                $schedule_out = "";

                if(in_array($dayOfWeek,$daysCWSArray)) {
                    $schedule_out = $schedule->schedule->cws_to_time;

                } elseif(!in_array($dayOfWeek, $daysArray)) {
                    $schedule_out = $schedule->schedule->to_time;

                    // $schedTimeIn = new DateTime($date . ' ' . $schedule_in);
                    // $schedTimeOut = new DateTime($date . ' ' . $schedule_out);

                    // // Calculate the difference between the two DateTime objects
                    // $interval = $schedTimeOut->diff($schedTimeIn);

                    // // Convert the interval to total minutes
                    // $totalMinutes = ($interval->h * 60) + $interval->i;

                    // // Use floor() if needed (though $totalMinutes is already an integer)
                    // $totalMinutes = floor($totalMinutes) - 60;

                    // // echo $employee_id;
                    // // $minutes = ($interval->h * 60) + $interval->i;

                    // return $totalMinutes;
                }

            }
            if ($ob && $ob->date_from == $date) {
                $obTimeStart = $date.' '.$ob->from_time;

                if (!$firstTimelog || new DateTime($obTimeStart) < new DateTime($firstTimelog->datetimelog)) {
                    $firstTimelog->datetimelog = $obTimeStart;
                }
            }

            if ($offsetAvailment && $offsetAvailment->date_from == $date) {
                $offsetAvailmentTimeStart = $date.' '.$offsetAvailment->from_time;

                if (!$firstTimelog || new DateTime($offsetAvailmentTimeStart) < new DateTime($firstTimelog->datetimelog)) {
                    $firstTimelog->datetimelog = $offsetAvailmentTimeStart;
                }
            }

            if ($firstTimelog && !empty($schedule_in)) {

                $firstTimelogTime = new DateTime($firstTimelog->datetimelog);
                // $lastTimelogTime = new DateTime($lastTimelog->datetimelog);

                $dayOfWeek = date('l', strtotime($date));
                $daysCWSArray = explode(',', $schedule->schedule->cws_day);

                if(in_array($dayOfWeek,$daysCWSArray) && !$schedule->schedule['isChangeSchedule']) {
                    $scheduledStartTime = new DateTime($date.' '.$schedule->schedule->cws_from_time);
                    $scheduledEndTime = new DateTime($date.' '.$schedule->schedule->cws_to_time);
                } else {
                    $scheduledStartTime = new DateTime($date.' '.$schedule->schedule->from_time);
                    $scheduledEndTime = new DateTime($date.' '.$schedule->schedule->to_time);
                }


                // if($date == '2025-01-10'){
                //     dd([
                //         'firstTimelogTime' => $firstTimelog,
                //         'scheduledStartTime' => $scheduledStartTime,
                //         'isChangeSchedule' => $schedule->schedule['isChangeSchedule']
                //     ]);
                // }

                // Calculate the difference between first time log and scheduled start time
                $timeDifference = $firstTimelogTime->diff($scheduledStartTime);
                $hoursDifference = $timeDifference->h + ($timeDifference->days * 24);

                // Check if first time log is 3 hours greater than scheduled start time
                if ($firstTimelogTime > $scheduledStartTime && $hoursDifference >= 3 && $halfDayLeave) {
                    // Make scheduled start time half
                    $interval = $scheduledStartTime->diff($scheduledEndTime);
                    $halfTimeInterval = floor($interval->h / 2) * 3600 + floor($interval->i / 2) * 60;

                    // Create a new scheduled start time at the halfway point
                    $adjustedScheduledStartTime = clone $scheduledStartTime;
                    $adjustedScheduledStartTime->add(new DateInterval("PT{$halfTimeInterval}S"));

                    // if(!in_array($dayOfWeek,$daysCWSArray) && $schedule->schedule->cws_day != "") {
                        $adjustedScheduledStartTime = Carbon::instance($adjustedScheduledStartTime)->addHour();
                    // }

                    // For example, you might want to set this as the new scheduled start time:
                    $scheduledStartTime = $adjustedScheduledStartTime;
                }

                /**set default breaktime start and end */
                $breakTimeStartTime = new DateTime($date.' 12:00:00');
                $breakTimeEndTime = new DateTime($date.' 13:00:00');

                /**set break time start and end based on settings*/
                if($lunchBreak) {
                    $breakTimeStartTime = new DateTime($date.' '.$lunchBreak->start_break_time);
                    $breakTimeEndTime = new DateTime($date.' '.$lunchBreak->end_break_time);
                }
            // if($date=='2025-01-16') dd(['start' => $breakTimeStartTime, 'end' => $breakTimeEndTime]);

                $breakInterval = 0;
                if($firstTimelogTime>$breakTimeStartTime && $firstTimelogTime<$breakTimeEndTime) {
                    $interval = $breakTimeStartTime->diff($scheduledStartTime);
                    // if($date == '2025-01-17'){
                    //     dd($breakTimeStartTime);
                    // }
                } else if($firstTimelog> $breakTimeEndTime) {
                    $interval = $breakTimeStartTime->diff($scheduledStartTime);
                    $interval2 = $firstTimelogTime->diff($breakTimeEndTime);
                    $interval->h = $interval2->h;
                    $interval->i = $interval2->i;
                } else {
                    // Calculate the difference
                    $interval = $firstTimelogTime->diff($scheduledStartTime);
                    // if($date == '2025-01-15'){
                    //     dd($scheduledStartTime);
                    // }
                }

                /**If halfday leave */
                if($halfDayLeave) {
                    $workHours = $scheduledStartTime->diff($scheduledEndTime)->h - 1;

                    if($interval->h >= $workHours/2) { /**if the interval exceeds half day, this means that the leave is at the start of schedule thus the timelog is after leave, then change the scheduledStartTime and recompute intervals */
                        $decimalHours = ($workHours / 2) + 1;
                        $hours = floor($decimalHours); // whole hours
                        $minutes = ($decimalHours - $hours) * 60; // convert decimal to minutes

                        $interval = new DateInterval(sprintf('PT%dH%dM', $hours, $minutes));
                        $scheduledStartTime->add($interval);

                        $interval =  $firstTimelogTime->diff($scheduledStartTime);

                        $minutes = ($interval->h * 60) + $interval->i;

                        if($halfDayLeave && $minutes >= 59) {
                            return false;
                        }

                        return floor($minutes);
                        // $workHoursAttendended = $firstTimelogTime->diff($lastTimelogTime);

                        // if($workHoursAttendended->h >= 4){
                            //     return false;
                            // }
                    } else {
                            $grace_period = $payrollSetting->late_grace_period ?? 5;
                            if($classification_id == '3') {
                                $grace_period = $payrollSetting->late_grace_period_manager ?? 30;
                            }
                            $interval =  $firstTimelogTime->diff($scheduledStartTime);

                            if($scheduledStartTime->format('H:i:s') == $schedule_in){
                                $scheduledStartTime->add(new DateInterval('PT'.($grace_period+1).'M'));
                            }

                            if($firstTimelogTime >= $scheduledStartTime) { /**IF HALFDAY IN THE AFTERNOON */
                                $minutes = ($interval->h * 60) + $interval->i;
                                if($minutes >= 59) {
                                    return false;
                                }
                                return floor($minutes);
                                // if($date=='2025-01-17') dd($minutes);

                            }
                        }
                    }

                $grace_period = $payrollSetting->late_grace_period ?? 5;

                if($classification_id == '3')
                {
                    $grace_period = $payrollSetting->late_grace_period_manager ?? 30;

                    if(($halfDayLeave && $scheduledStartTime->format('H:i:s') == $schedule_in) || (!$halfDayLeave && $scheduledStartTime->format('H:i:s') == $schedule_in)){
                        $scheduledStartTime->add(new DateInterval('PT'.($grace_period).'M')); // Add 30 minutes grace period
                    }
                } else {
                    // if($date == '2025-01-15'){
                    //     dd($schedule_in);
                    // }
                    if(($halfDayLeave && $scheduledStartTime->format('H:i:s') == $schedule_in) || (!$halfDayLeave && $scheduledStartTime->format('H:i:s') == $schedule_in)){

                        $scheduledStartTime->add(new DateInterval('PT'.($grace_period).'M'));// Add 6 minutes grace period
                    }
                }

                //  if($date=='2025-01-07') dd(['timeIn' => $firstTimelogTime, 'schedStart'=>$scheduledStartTime, 'halfDay' => $halfDayLeave, 'class'=>$classification_id]);
                // if($classification_id == '3' && $scheduledStartTime == $schedule_in)
                // {
                //     $scheduledStartTime->add(new DateInterval('PT31M')); // Add 6 minutes grace period
                // } else if($classification_id < '3' && $scheduledStartTime == $schedule_in){
                //     $scheduledStartTime->add(new DateInterval('PT6M')); // Add 6 minutes grace period
                // }


                $firstTimelogTimeFormatted = $firstTimelogTime->format('H:i:s');
                $scheduledStartTimeFormatted = $scheduledStartTime->format('H:i:s');


                // if($date == '2025-01-10'){
                //     dd([
                //         'firstTimelogTime' => $firstTimelog,
                //         'scheduledStartTime' => $scheduledStartTime
                //     ]);
                // }

                if ($firstTimelogTime > $scheduledStartTime) {

                    $minutes = ($interval->h * 60) + $interval->i;

                    // if($date == '2025-01-18'){
                    //     // dd($minutes);
                    //     dd(
                    //         [
                    //             'first_time_Log' => $firstTimelogTimeFormatted,
                    //             'schedule_start_Tiem' => $scheduledStartTimeFormatted
                    //         ]
                    //         );
                    // }
                    // if($halfDayLeave && $minutes >= 60) {
                    //     return false;
                    // }

                    return floor($minutes);
                }
            }
        }
        return false;
    }

    public function getUndertime($timelogs, $schedule, $workSuspension, $formattedDate, $ob, $offsetAvailment, $wfhRecord, $halfDayLeave=false)
    {

        if ($timelogs && ($timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() || $ob || $offsetAvailment) && $schedule && !$workSuspension) {
            $lastTimelog = $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => $tl->datetimelog)->first();
            $employee_id = $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => $tl->employee_id)->first();

            if($offsetAvailment && $offsetAvailment->date_to == $formattedDate) {
                $offsetAvailmentTimeEnd = $formattedDate.' '.$offsetAvailment->to_time;

                if(!$lastTimelog || new DateTime($offsetAvailmentTimeEnd) > new DateTime($lastTimelog))
                {
                    $lastTimelog = $offsetAvailmentTimeEnd;
                }
            }

            $date = $lastTimelog ? Carbon::parse($lastTimelog)->format('Y-m-d') : $formattedDate;

            $dayOfWeek = date('l', strtotime($date));
            $daysArray = explode(',', $schedule->schedule->day_off);

            $daysWFHArray = explode(',', $schedule->schedule->wfh);
            $daysCWSArray = explode(',', $schedule->schedule->cws_day);
            $schedule_out = "";

            /**check if WFH and if has DAR */

            $isWFH = in_array($dayOfWeek, $daysWFHArray);
            $validWFH = $wfhRecord && $wfhRecord->isNotEmpty();

            $isChangeSchedule = false;

            if($ob && $ob->date_from == $formattedDate) {

                $dayOfOb = date('l', strtotime($ob->date_from));

                if(in_array($dayOfOb, $daysArray))
                {
                    return false;
                }
            }

            if($ob && $ob->date_to == $formattedDate) {
                $obTimeEnd = $formattedDate.' '.$ob->to_time;

                if(!$lastTimelog || new DateTime($obTimeEnd) > new DateTime($lastTimelog))
                {
                    $lastTimelog = $obTimeEnd;
                }

                // dd(new DateTime($formattedDate . ' 5:00:00'));
                // dd(new DateTime($obTimeEnd));
                if(new DateTime($obTimeEnd) < new DateTime($formattedDate . ' 5:00:00')){
                    return false;
                }
            }

            $lastTimelogTime = Carbon::parse($lastTimelog);

            if($schedule->schedule->isChangeSchedule){
                $isChangeSchedule = true;
            }

            $lunchBreak = null;
            $lunchBreak = $schedule->schedule->lunch_break ?? null;
            if(in_array($dayOfWeek,$daysCWSArray) && !$isChangeSchedule) {
                $schedule_in = $schedule->schedule->cws_from_time;
                $schedule_out = $schedule->schedule->cws_to_time;
                $lunchBreak = $schedule->schedule->cws_lunch_break ?? ($schedule->schedule->lunch_break ?? null);
            } else if(in_array($dayOfWeek,$daysCWSArray) && $isChangeSchedule) {
                $schedule_in = $schedule->schedule->from_time;
                $schedule_out = $schedule->schedule->to_time;
                $lunchBreak = $schedule->schedule->cws_lunch_break ?? ($schedule->schedule->lunch_break ?? null);
            } elseif(!in_array($dayOfWeek, $daysArray)) {
                $schedule_in = $schedule->schedule->from_time;
                $schedule_out = $schedule->schedule->to_time;

                if(($timelogs->filter(fn($tl) => $tl->in_out=='I')->isEmpty() && !$ob && !$offsetAvailment) && $schedule && !$workSuspension)
                {
                    $schedule_in = "";
                    if(in_array($dayOfWeek,$daysCWSArray)) {
                        $schedule_in = $schedule->schedule->cws_from_time;
                    } elseif(!in_array($dayOfWeek, $daysArray)) {
                        $schedule_in = $schedule->schedule->from_time;
                    }

                    // $schedTimeIn = new DateTime($date . ' ' . $schedule_in);
                    // $schedTimeOut = new DateTime($date . ' ' . $schedule_out);

                    // // Calculate the difference between the two DateTime objects
                    // $interval = $schedTimeOut->diff($schedTimeIn);

                    // // Convert the interval to total minutes
                    // $totalMinutes = ($interval->h * 60) + $interval->i;

                    // // Use floor() if needed (though $totalMinutes is already an integer)
                    // $totalMinutes = floor($totalMinutes) - 60;

                    // dd($totalMinutes);
                    // $minutes = ($interval->h * 60) + $interval->i;

                    // return $totalMinutes;

                }
            }

            $interval = null;

             if ($lastTimelog && !empty($schedule_out)) {
                $scheduledEndTime = Carbon::parse($date . ' ' . $schedule_out);
                $scheduledStartTime = Carbon::parse($date . ' ' . $schedule_in);

                $schedHours = Carbon::parse($scheduledStartTime)->diffInHours(Carbon::parse($scheduledEndTime));
                if($schedHours > 8) $schedHours--;

                $breakTimeStartTime = Carbon::parse($formattedDate.' 12:00:00');
                $breakTimeEndTime = Carbon::parse($formattedDate.' 13:00:00');

                if($lunchBreak) {
                    $breakTimeStartTime = Carbon::parse($formattedDate.' '.$lunchBreak->start_break_time);
                    $breakTimeEndTime = Carbon::parse($formattedDate.' '.$lunchBreak->end_break_time);
                }
            /**IF WHOLEDAY */
                if(!$halfDayLeave) {
                    if($lastTimelogTime->lt($scheduledEndTime)) {
                        if($lastTimelogTime->lt($breakTimeStartTime)) {
                            $interval = $lastTimelogTime->diff($breakTimeStartTime);
                            $interval2 = $breakTimeEndTime->diff($scheduledEndTime);
                            $interval->h += $interval2->h;
                            $interval->i += $interval2->i;
                        }elseif($lastTimelogTime->gt($breakTimeStartTime) && $lastTimelogTime->lt($breakTimeEndTime)) {
                            $interval = $breakTimeEndTime->diff($scheduledEndTime);
                        }else {
                            $interval = $lastTimelogTime->diff($scheduledEndTime);
                        }
                    }
                }else { /**IF HALFDAY LEAVE */
                    $hoursInterval = $scheduledEndTime->diffInHours($lastTimelogTime);
                    if($hoursInterval >= $schedHours/2) {
                        $morningLeave = true;
                    } else {
                        $morningLeave = false;
                    }
                    if($morningLeave) {
                        if($lastTimelogTime->lt($scheduledEndTime)) {
                            if($lastTimelogTime->lt($breakTimeEndTime)) {
                                $interval = $breakTimeEndTime->diff($scheduledEndTime);
                            } else {
                                $interval = $lastTimelogTime->diff($scheduledEndTime);
                            }
                        }
                    } else {
                        if($lastTimelogTime->lt($breakTimeStartTime)) {
                            $interval = $lastTimelogTime->diff($breakTimeStartTime);
                        }
                        // if($date=='2024-12-28') dd($interval);
                    }
                }

                if($interval) {
                         // Calculate the total difference in minutes, including seconds
                    $totalMinutes = ($interval->h * 60) + $interval->i + ($interval->s / 60);

                    $intervalSchedule = $scheduledEndTime->diff($scheduledStartTime);
                    $totalMinutesSchedule = ($intervalSchedule->h * 60) + $intervalSchedule->i + ($intervalSchedule->s / 60);

                    if($totalMinutes >= $totalMinutesSchedule){
                        return ceil($totalMinutesSchedule - 60);
                    }

                    // dd($totalMinutesSchedule);
                    // Round down to the nearest whole minute

                    return ceil($totalMinutes);
                }



                // $morningEnd = Carbon::parse($scheduledStartTime)->addHour($schedHours/2);
                // $afternoonStart = Carbon::parse($scheduledStartTime)->addHour(($schedHours/2)+1);
                // $lastTimelogTime = Carbon::parse($lastTimelog);
                // if($lastTimelogTime->gt($morningEnd) && $lastTimelogTime->lt($afternoonStart)) {
                //     $lastTimelogTime = $afternoonStart;
                // }

                // // if($formattedDate=='2024-12-21') dd($lastTimelogTime);

                // // $lastTimelogTime = new DateTime($lastTimelog);
                // // $lastTimelogTime->setTime($lastTimelogTime->format('H'), $lastTimelogTime->format('i'), 0);

                // $interval = $scheduledEndTime->diff($lastTimelogTime);
                // $intervalSchedule = $scheduledEndTime->diff($scheduledStartTime);

                // $lastTimelogTimeFormatted = $lastTimelogTime->format('H:i:s');
                // $scheduledEndTimeFormatted = $scheduledEndTime->format('H:i:s');

                // // if($halfDayLeave) {
                // //     $workHours = $scheduledStartTime->diff($scheduledEndTime)->h - 1;

                // //     // dd($workHours);

                // //     if($interval->h >= $workHours/2) { /**if the interval exceeds half day, this means that the leave is at the start of schedule thus the timelog is after leave, then change the scheduledStartTime and recompute intervals */
                // //         $scheduledEndTime->sub(new DateInterval('PT'.(($workHours/2)+1).'H'));
                // //         $interval = $scheduledEndTime->diff($lastTimelogTime);

                // //         $totalMinutes = ($interval->h * 60) + $interval->i + ($interval->s / 60);

                // //         // if($totalMinutes){

                // //         // }
                // //         dd($interval);
                // //     }

                // //     /**THIS IS FOR TEST  AND DEBUGGING ONLY */
                // //     if($employee_id == '1922' && $date == '2024-12-23') {
                // //         // dd($firstTimelog);
                // //         dd(['timelogs' => $lastTimelog, 'schedule' => $scheduledEndTime, 'interval' => $interval]);
                // //     }
                // // }

                // if ($lastTimelogTime < $scheduledEndTime) {

                //     // Calculate the total difference in minutes, including seconds
                //     $totalMinutes = ($interval->h * 60) + $interval->i + ($interval->s / 60);
                //     $totalMinutesSchedule = ($intervalSchedule->h * 60) + $intervalSchedule->i + ($intervalSchedule->s / 60);

                //     if($totalMinutes >= $totalMinutesSchedule){
                //         return ceil($totalMinutesSchedule - 60);
                //     }

                //     // dd($totalMinutesSchedule);
                //     // Round down to the nearest whole minute

                //     return ceil($totalMinutes);
                // }
            }
        }

        return false;

    }

    public function getOvertime($date, $employee_id, $start_date, $end_date)
    {
        return EmployeeOvertime::where('date_from', '=', $date)
            // ->where('date_to', '=', $date)
            ->where('enabled', '=', 1)
            ->where('status', '=', 2)
            ->where('validated', '=', 1)
            ->where('employee_id', '=', $employee_id)
            // ->whereDate('approved_at', '>=', $start_date)
            // ->whereDate('approved_at', '<=', $end_date)
            ->first();

    }

    public function getAbsentTardinessHeadDashboard(Request $request)
    {
        // dd($request->all());
        $user = Auth::user();

        $get_the_approver_hierarchy = Approver::where('approvers', 'like','%"'.$user->employee_id.'"%')->get();

        $approver_hierarchy_result = [];

        foreach($get_the_approver_hierarchy as $data) {
            $approver_hierarchy_result['data'][$data->type][] = $data->type_id;
        }

        $members = [];

        $today = date('Y-m-d', strtotime($request->date ?? now()));

        $processedEmployees = []; // Array to keep track of processed employees
        $wfhEmployees = []; // Array to keep track of processed employees

        $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();
        }

        foreach ($approver_hierarchy_result as $key => $data2) {
            // Loop through each organization type (dealership, division, group, etc.)
            foreach ($data2 as $key2 => $organization) {
                $key2 == 'dealership' ? $keys = 'dealer' : $keys = $key2;

                // Fetch employees based on the organization ID
                $employees = Employee::select('employee_id', DB::raw('CONCAT(firstname, " ", lastname) as fullname'), DB::raw('departments.name as department_name'))
                    ->join('departments', 'employees.department_id', '=', 'departments.id')
                    ->whereIn('employees.' . $keys . '_id', $organization)
                    ->where('employees.employee_id', '!=', $user->employee_id)
                    ->where('employees.enabled', '=', '1')
                    ->whereNull('employees.date_resign')
                    ->where('employees.classification_id', '<=', $user->employees->classification_id)
                    ->whereIn('employees.dealer_id', $dealers) // Filter by dealers
                    ->get();
                    foreach ($employees as $employee) {
                        // Check if the employee has already been processed
                        if (in_array($employee->employee_id, $processedEmployees)) {
                            continue; // Skip if the employee has been processed
                        }

                        if(EmployeeWfh::whereDate('date', $today)->where('employee_id', $employee->employee_id)->exists()){
                            $userLog = \App\Models\UserLog::select('created_at')->whereDate('created_at', $today)->where('employee_id',$employee->employee_id)->orderByDesc('created_at')->first();
                            $lastLog = null;
                            if($userLog) {
                                $userLog = $userLog->toArray();
                                $lastLog = Carbon::parse($userLog['created_at'])->setTimezone('Asia/Manila')->format('g:iA');
                            }
                            $wfhData = EmployeeWfh::whereDate('date', $today)->where('employee_id', $employee->employee_id)->first();

                            $wfhEmployees[] = [
                                'employee_id' => $employee->employee_id,
                                'fullname' => $employee->fullname,
                                'department_name' => $employee->department_name,
                                'remarks' => $wfhData->description,
                                'last_log' => $lastLog,
                                'date' => $wfhData->date
                            ];
                        }

                    $processedEmployees[] = $employee->employee_id; // Mark the employee as processed

                    $date = date('Y-m-d', strtotime($request->date ?? now()));;
                    $company_id = $employee->company_id;
                    $timelogs = $this->getTimelog($date, $employee->employee_id);
                    $schedule = $this->getSchedule($date, $employee->employee_id);
                    $holiday = $this->getHoliday($date, $employee, $schedule);
                    $leave = $this->getLeave($date, $employee->employee_id);
                    $ob = $this->getLeave($date, $employee->employee_id);
                    $offsetAvailment = $this->getOffsetAvailment($date, $employee->employee_id);
                    $halfDayLeave = $leave && ($leave->half_day == 1 || $leave->half_day == 2);
                    $wholeDayLeave = $leave && $leave->hours >= 8;
                    // if($employee->employee_id == '60599'){
                        $tardiness = $this->getTardinessHeadDisplay($timelogs, $schedule, $halfDayLeave, $ob, $offsetAvailment, $employee->classification_id, $wholeDayLeave,$company_id);
                        // dd($date, $tardiness);
                    // }
                    // $tardiness = $this->getTardiness($timelogs, $schedule, $halfDayLeave, $ob, $offsetAvailment, $employee->classification_id, $wholeDayLeave);

                    // Check absence
                    $isAbsent = $this->isAbsent($timelogs, $leave, $holiday, $schedule, $date);

                    if ($timelogs) {
                        $filteredTimelogs = $timelogs->where('in_out', "I");

                        if ($filteredTimelogs->count() > 0) {
                            $members['timelogsMembers'][] = [
                                'employee' => $employee,
                                'timelogs' => $filteredTimelogs
                            ];
                        }
                    }

                    if ($tardiness) {
                        $members['tardyMembers'][] = [
                            'employee' => $employee,
                            'tardiness' => $tardiness, // for checking
                        ];
                    }

                    if ($isAbsent) {
                        $members['absentMembers'][] = [
                            'employee' => $employee,
                            // 'absent' => $isAbsent // for checking
                        ];
                    }
                }
            }
//
        }
        // dd($wfhEmployees);

        return response()->json([
            'members' => $members,
            'wfhEmployees' => $wfhEmployees
        ]);
    }

    public function isAbsent($timelogs, $leave, $holiday, $schedule, $date)
    {
        // Check if there are no timelogs, no leave, no holiday, and it's not a day off
        if (!$timelogs->count() && !$leave && !$holiday) {
            if ($schedule) {
                // Proceed with accessing schedule->schedule
                $dayOfWeek = date('l', strtotime($date));
                $daysArray = explode(',', $schedule->schedule->day_off); // Convert string to array
            } else {
                // Handle case where schedule is not found
                $dayOfWeek = date('l', strtotime($date));
                $daysArray = []; // Or any default value
            }

            // dd($dayOfWeek);
            if (!in_array($dayOfWeek, $daysArray) && new DateTime($date) < new DateTime()) {
                return true;
            }
        }
        return false;
    }

    public function isPresent($timelogs, $leave, $holiday, $ob, $validWFH, $schedule, $date, $isAbsentBeforeHoliday=true,)
    {
        // Check if there are timelogs or it's a day off or holiday or leave
        if ($timelogs->count() > 0 || ($leave && $leave->without_pay==0) || $ob || $validWFH || ($holiday && !$isAbsentBeforeHoliday && $schedule)) {
        // if ((!$timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() && !$timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty()) || ($leave && $leave->without_pay==0) || $ob || $validWFH || ($holiday && !$isAbsentBeforeHoliday && $schedule)) {
            return true;
        }

        if ($schedule) {
            $dayOfWeek = date('l', strtotime($date));
            $daysArray = explode(',', $schedule->schedule->day_off); // Convert string to array

            if (in_array($dayOfWeek, $daysArray)) {
                return false; // It's a day off
            }
        }

        return false;
    }

    public function addTITO(Request $request)
    {
        // dd($request->all());
        DB::beginTransaction();

        try {
            $request['datetimelog'] = date('Y-m-d H:i:s', strtotime($request->datetimelog));

            $status = WfhFloatedTimelog::create($request->all());

            DB::commit();

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

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

    public function getProcessedAttendance(Request $request)
    {
        $getLastPayrollDate = ProcessedTimelog::where('employee_id', $request->employee_id)
            ->orderBy('payroll_date', 'DESC')
            ->first();

        // Check if payroll date exists, return false if not
        if (!$getLastPayrollDate) {
            return response()->json(false);
        }

        $timelogs = ProcessedTimelog::where('payroll_date', $getLastPayrollDate->payroll_date)
            ->where('employee_id', $request->employee_id)
            ->get();

        $abensences = ProcessedAbsent::where('payroll_date', $getLastPayrollDate->payroll_date)
            ->where('employee_id', $request->employee_id)
            ->get();

        $tardiness = ProcessedTardiness::where('payroll_date', $getLastPayrollDate->payroll_date)
            ->where('employee_id', $request->employee_id)
            ->get();

        $result = [];

        foreach ($timelogs as $timelog) {
            // Check if the date already exists in the result array
            $date = $timelog['date'];
            if (isset($result[$date])) {
                // If the date exists and 'out' time is present, add it to the existing entry
                if ($timelog['in_out'] == 'O') {
                    $result[$date]['name'] .= ' - ' . $timelog['time'] . ' OUT';
                    $result[$date]['has_out'] = true; // Mark that 'OUT' time exists
                }
            } else {
                // Create a new entry for 'in' or 'out'
                $result[$date] = [
                    'date' => $timelog['date'],
                    'name' => $timelog['time'] . ($timelog['in_out'] == 'I' ? ' IN' : ' OUT'),
                    'title' => 'Present',
                    'has_in' => $timelog['in_out'] == 'I',  // Mark if 'IN' exists
                    'has_out' => $timelog['in_out'] == 'O'  // Mark if 'OUT' exists
                ];
            }
        }

        // Post-processing to update title if 'IN' or 'OUT' is missing
        foreach ($result as &$entry) {
            if (empty($entry['has_in'])) {
                $entry['title'] = 'No Time In';
            } elseif (empty($entry['has_out'])) {
                $entry['title'] = 'No Time Out';
            }
            // Remove the markers as they are no longer needed
            unset($entry['has_in'], $entry['has_out']);
        }

        // To reset the array indices if needed
        $result = array_values($result);

        foreach($abensences as $absent){
            $result[] = [
                'date' => $absent['date'],
                'name' => $absent['no_of_days'] . ' Day/s',
                'title' => 'Absent',
            ];
        }

        foreach($tardiness as $tardy){
            $result[] = [
                'date' => $tardy['date'],
                'name' => $tardy['no_of_minutes']. ' Minutes',
                'title' => 'Late',
            ];
        }

        // Sort the result array by the 'date' key
        usort($result, function ($a, $b) {
            return strcmp($a['date'], $b['date']);
        });

        return response()->json(array_values($result));
    }

    public function processAttendance(Request $request) {

        set_time_limit(180);
        ini_set('memory_limit', '1024M'); // Add this line - adjust as needed
        // dd($request->all());return;
        $employee_id =$request->employee_id;
        $company_id = $request->company_id;
        $dealer_id = $request->dealership_id;
        $department_id = $request->department_id;
        $payroll_date = $request->payroll_date;

        $start_date = new DateTime($request->start_date);
        $end_date = new DateTime($request->end_date);
        $end_date->modify('+1 day');

        // dd($request->all());
        $payrollSetting = PayrollSetting::where('company_id',$company_id)->first();
        if(!$payrollSetting) {
            $payrollSetting = PayrollSetting::whereNull('company_id')->first();
        }
        // dd($payrollSetting);
        // Create a DatePeriod object
        $period = new DatePeriod($start_date, new DateInterval('P1D'), $end_date);

        $presentDays = 0;
        $workDays = 0;
        $actualWorkDays = 0;
        $employee = Employee::where('employee_id', $employee_id)->first();

        $isAlwaysPresent = $this->alwaysPresent($employee->employee_id);
        $salary = SalaryAndWages::where('employee_id', $employee_id)->where('salary_effectivity_date', '<=', $end_date)->orderBy('salary_effectivity_date','DESC')->first();
        $payrollRate = $salary->payroll_rate ?? '';

        $data = [
            'timelog' => [],
            'schedule' => [],
            'holiday' => [],
            'leave' => [],
            'ob' => [],
            'offsetAvailment' => [],
            'undertime' => [],
            'tardiness' => [],
            'overtime' => [],
            'night_differential' => [],
            'absent' => [],
            'dailyWorkHours' => [],
            'days_present' => null,
            'workDays' => null,
            'actualWorkDays' => null,
            'isAlwaysPresent' => $isAlwaysPresent,
        ];

        $where = [
            'employee_id' => $employee_id,
            'company_id' => $company_id,
            'dealership_id' => $dealer_id,
            'payroll_date' => $payroll_date,
        ];
        /**Delete temp record */
        ProcessedLeave::where($where)->delete();
        ProcessedTimelog::where($where)->delete();
        ProcessedAbsent::where($where)->delete();
        ProcessedUndertime::where($where)->delete();
        ProcessedTardiness::where($where)->delete();
        ProcessedOvertime::where($where)->delete();

        ProcessedNightDifferential::where($where)->delete();
        ProcessedDailyWorkHours::where($where)->delete();
        ProcessedSchedule::where($where)->delete();
        ProcessedOb::where($where)->delete();
        ProcessedOffsetAvailment::where($where)->delete();
        ProcessedHolidayRestdayDuty::where($where)->delete();
        DB::beginTransaction();

        $processedOTDates =[];
        try {
            foreach ($period as $date) {
                $overtime = null;
                $formattedDate = $date->format('Y-m-d');
                $validWFH = false;
                // Get Timelogs
                $schedule = $this->getSchedule($formattedDate, $employee_id);

                if(!$schedule){
                    continue;
                }

                $timelogs = $this->getTimelog($formattedDate, $employee_id);
                $timelogData = [];
                if($timelogs) {
                    $timelogData = $timelogs->map(fn($tl) => [
                            'employee_id' => $employee_id,
                            'time_keeping_id' => $tl->time_keeping_id ?? null,
                            'company_id' => $company_id,
                            'dealership_id' => $dealer_id,
                            'department_id' => $department_id,
                            'payroll_date' => $payroll_date,
                            'date' => $formattedDate,
                            'time' => Carbon::parse($tl->datetimelog)->format('H:i:s'),
                            'in_out' => $tl->in_out,
                        ]
                    );
                    foreach($timelogData as $timelog) {
                        $tlog = ProcessedTimelog::create($timelog);
                        // dd($tlog);
                        $data['timelog'][] = $tlog;
                    }
                }
                // $this->addTimelogData($data, $timelogs, $formattedDate);
                // Get Holiday
                $holiday = $this->getHoliday($formattedDate, $employee, $schedule);

                $isHoliday = false;
                $isAbsentBeforeHoliday = false;
                if($holiday) {
                    $isHoliday = true;
                    // if($holiday->holiday_type=='3') {
                    //     $dealers = explode(',',$holiday->dealership_ids);
                    //     if(!in_array($dealer_id, $dealers)) {
                    //         $isHoliday = false;
                    //     }
                    // }
                }
                if($holiday && $holiday['isAbsentBeforeHoliday'] == true){
                    $isAbsentBeforeHoliday = true;
                }
                // Get Schedule
                $schedule = $this->getSchedule($formattedDate, $employee_id);
                // echo'<pre>';print_r($schedule);echo'</pre>';
                $workSuspension = $this->getWorkSuspension($formattedDate);

                $dayoff = EmployeeChangeSchedule::where('dayoff_date', $formattedDate)->where('validated', 1)->where('status', 2)->where('employee_id', $employee_id)->first();
                $employee_change_schedule = EmployeeChangeSchedule::where(fn($q) =>
                    $q->whereNull('date_to')
                        ->where('date', $formattedDate)
                        ->orWhere(fn($q) =>
                            $q->whereNotNull('date_to')
                                ->where('date', '<=', $formattedDate)
                                ->where('date_to', '>=', $formattedDate)
                        )
                    ->where('status', 2)
                    ->where('validated', 1)
                )->where('status', 2)
                ->where('validated', 1)
                ->where('employee_id', $employee_id)->first();


                // if($employee_id=='60638') {
                //     dd($schedule->toArray());
                // }
                $scheduleData = [];
                $schedule_in = "";
                $schedule_out = "";
                $isRestDay = false;

                // if(!$isAlwaysPresent)
                // {
                    if(!empty($dayoff)){
                        $isRestDay = true;
                        $scheduleData = [
                            'employee_id' => $employee_id,
                            'company_id' => $company_id,
                            'dealership_id' => $dealer_id,
                            'department_id' => $department_id,
                            'payroll_date' => $payroll_date,
                            'date' => $formattedDate,
                            'schedule_in' => $schedule_in,
                            'schedule_out' => $schedule_out,
                            'cws' => 0,
                            'wfh' => 0,
                            'restday' => $isRestDay,
                            'duty_hours' => 0,
                            'holiday' => $isHoliday ? $holiday->name : null,
                            'holiday_type' => $isHoliday ? $holiday->holiday_type: null,
                        ];
                        $data['schedule'][] = $scheduleData;
                    }
                    else if(!empty($employee_change_schedule)){
                        $startTime = Carbon::parse($formattedDate.' '.$employee_change_schedule->from_time);
                        $endTime = Carbon::parse($formattedDate.' '.$employee_change_schedule->to_time);
                        // Compute the difference in hours
                        $hoursDifference = (int)$startTime->diffInHours($endTime);
                        if($hoursDifference > 0) {
                            $hoursDifference--;
                        }
                            $scheduleData = [
                                'employee_id' => $employee_id,
                                'company_id' => $company_id,
                                'dealership_id' => $dealer_id,
                                'department_id' => $department_id,
                                'payroll_date' => $payroll_date,
                                'date' => $formattedDate,
                                'schedule_in' => $employee_change_schedule->from_time,
                                'schedule_out' => $employee_change_schedule->to_time,
                                'cws' => 0,
                                'wfh' => 0,
                                'restday' => $isRestDay,
                                'duty_hours' => $hoursDifference < 0 ? 0 : $hoursDifference,
                                'holiday' => $isHoliday ? $holiday->name : null,
                                'holiday_type' => $isHoliday ? $holiday->holiday_type: null,
                            ];
                            $data['schedule'][] = $scheduleData;
                            ProcessedSchedule::create($scheduleData);
                    }
                    elseif($schedule) {
                        $dayOfWeek = date('l', strtotime($formattedDate));
                        $daysArray = explode(',', $schedule->schedule->day_off);

                        $daysWFHArray = explode(',', $schedule->schedule->wfh);
                        $daysCWSArray = explode(',', $schedule->schedule->cws_day);
                        if(in_array($dayOfWeek,$daysCWSArray)) {
                            $schedule_in = $schedule->schedule->cws_from_time;
                            $schedule_out = $schedule->schedule->cws_to_time;
                        } elseif(!in_array($dayOfWeek, $daysArray)) {
                            $schedule_in = $schedule->schedule->from_time;
                            $schedule_out = $schedule->schedule->to_time;
                        }

                        $isRestDay = in_array($dayOfWeek, $daysArray);
                        $startTime = Carbon::parse($formattedDate.' '.$schedule_in);
                        $endTime = Carbon::parse($formattedDate.' '.$schedule_out);
                        // dd($formattedDate.' '.$schedule->schedule->from_time. '  |  '.$formattedDate.' '.$schedule->schedule->to_time);
                        // Compute the difference in hours
                        $hoursDifference = (int)$startTime->diffInHours($endTime);

                        if($hoursDifference > 0) {
                            $hoursDifference--;
                        }
                        $scheduleData = [
                            'employee_id' => $employee_id,
                            'company_id' => $company_id,
                            'dealership_id' => $dealer_id,
                            'department_id' => $department_id,
                            'payroll_date' => $payroll_date,
                            'date' => $formattedDate,
                            'schedule_in' => $schedule_in,
                            'schedule_out' => $schedule_out,
                            'cws' => in_array($dayOfWeek, $daysCWSArray),
                            'wfh' => in_array($dayOfWeek, $daysWFHArray),
                            'restday' => $isRestDay,
                            'duty_hours' => $hoursDifference < 0 ? 0 : $hoursDifference,
                            'holiday' => $isHoliday ? $holiday->name : null,
                            'holiday_type' => $isHoliday ? $holiday->holiday_type: null,
                        ];
                        // if($employee_id == '661') {
                        //     echo '<pre>';
                        //     print_r($scheduleData);
                        //     echo '</pre>';
                        // }
                        $data['schedule'][] = $scheduleData;
                        ProcessedSchedule::create($scheduleData);
                    }

                // }

                //GET WFH
                $wfhRecord = EmployeeWfh::whereNotNull('attachment')->where(['employee_id'=> $employee_id, 'date'=>$formattedDate, 'status'=>2, 'validated'=>1])->first();
                // Get Leave
                $leaveHours = 0;
                $leave = $this->getLeave($formattedDate, $employee_id);

                // if($formattedDate == '2025-09-04'){
                //     dd(Carbon::parse($leave->date_from)->diffInDays(Carbon::parse($leave->date_to), false) + 1);
                // }

                // if($formattedDate == '2025-09-04'){
                //     dd(Carbon::parse($leave->date_from)->diffInDays(Carbon::parse($leave->date_to), false) + 1);
                // }

                if($leave) {

                    $noOfDaysLeave = Carbon::parse($leave->date_from)->diffInDays(Carbon::parse($leave->date_to), false) + 1;

                    // if($noOfDaysLeave > 1 && $leave->half_day == 0){
                    //     $noOfHoursLeave = $hoursDifference;
                    // }

                    // if($noOfDaysLeave > 1 && $leave->half_day == 1 && $formattedDate == $leave->date_from){
                    //     $noOfHoursLeave = $leave->first_or_last_day_halfday_leave;
                    // }

                    // if($noOfDaysLeave > 1 && $leave->half_day == 2 && $formattedDate == $leave->date_to){
                    //     $noOfHoursLeave = $leave->first_or_last_day_halfday_leave;
                    // }
                    if($noOfDaysLeave > 1 && $leave->half_day == 0){
                        //if multiple days of leave, check if current date is the first day of leave
                        $noOfHoursLeave = $hoursDifference;
                    } else if($noOfDaysLeave > 1 && $leave->half_day != 0){
                        //if multiple days of leave, check if current date is the first day of leave
                        $noOfHoursLeave = $hoursDifference;
                    } else {
                        $noOfHoursLeave = $leave->hours;
                    }

                    if($leave->half_day == 1 && $formattedDate == $leave->date_to){
                        $noOfHoursLeave = $leave->first_or_last_day_halfday_leave;
                    } else if($leave->half_day == 2 && $formattedDate == $leave->date_from) {
                        $noOfHoursLeave = $leave->first_or_last_day_halfday_leave;
                    }

                    $leaveHours = $leave->hours;

                    // if($formattedDate == '2025-06-03'){
                    //     dd($noOfHoursLeave);
                    // }

                    $leaveData =
                    [
                        'employee_id' => $employee_id,
                        'company_id' => $company_id,
                        'dealership_id' => $dealer_id,
                        'department_id' => $department_id,
                        'payroll_date' => $payroll_date,
                        'date' => $formattedDate,
                        'no_of_hours' => $noOfHoursLeave,
                        'type' => $leave->leave_id,
                        'without_pay' => $leave->without_pay,
                    ];
                        ProcessedLeave::create($leaveData);
                    $data['leave'][] = $leaveData;
                }
                // $this->addLeaveData($data, $leave, $formattedDate);

                $ob = $this->getOB($formattedDate, $employee_id);

                if($ob) {
                    $obData = [
                        'ob_id' => $ob->id,
                        'employee_id' => $employee_id,
                        'company_id' => $company_id,
                        'dealership_id' => $dealer_id,
                        'department_id' => $department_id,
                        'payroll_date' => $payroll_date,
                        'date' => $formattedDate,
                        'from_time' => $ob->from_time,
                        'to_time' => $ob->to_time,
                        'meal' => $ob->meal,
                        'transportation' => $ob->transportation,
                        'meal_amount' => $ob->meal_amount,
                        'transportation_amount' => $ob->transportation_amount,
                        'description' => $ob->description,
                        'destination' => $ob->destination,
                    ];
                    $data['ob'][] = $obData;
                    ProcessedOb::create($obData);
                }


                $offsetAvailment = $this->getOffsetAvailment($formattedDate, $employee_id);
                if($offsetAvailment) {
                    $offsetAvailmentData = [
                        'offset_availment_id' => $offsetAvailment->id,
                        'employee_id' => $employee_id,
                        'company_id' => $company_id,
                        'dealership_id' => $dealer_id,
                        'department_id' => $department_id,
                        'payroll_date' => $payroll_date,
                        'date' => $formattedDate,
                        'from_time' => $offsetAvailment->from_time,
                        'to_time' => $offsetAvailment->to_time,
                        'description' => $offsetAvailment->description,
                    ];
                    $data['offset'][] = $offsetAvailmentData;
                    ProcessedOffsetAvailment::create($offsetAvailmentData);
                    // dd()
                }

                // Check Tardiness
                // if($formattedDate == "2024-12-30"){
                //     dd($holiday);
                // }

                if(!$holiday){
                    $halfDayLeave = $leave && ($leave->half_day == 1 || $leave->half_day == 2);
                    $wholeDayLeave = $leave && $leave->hours >= 8;
                    // if($formattedDate == "2024-12-23"){
                    //     dd($wholeDayLeave);
                    // }
                    $tardiness = $this->getTardiness($timelogs, $schedule, $halfDayLeave, $ob, $offsetAvailment, $employee->classification_id, $wholeDayLeave,$company_id);
                    // if($formattedDate=='2025-01-17') dd($tardiness);

                    // if($tardiness && $tardiness < 60) {

                    //         $tardinessData = [
                    //             'employee_id' => $employee_id,
                    //             'company_id' => $company_id,
                    //             'dealership_id' => $dealer_id,
                    //             'department_id' => $department_id,
                    //             'payroll_date' => $payroll_date,
                    //             'date' => $formattedDate,
                    //             'schedule_in' => $scheduleData['schedule_in'] ?? null,
                    //             'schedule_out' => $scheduleData['schedule_out'] ?? null,
                    //             'time_in' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='I')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : '',
                    //             'time_out' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : '',
                    //             'no_of_minutes' => $tardiness,
                    //         ];
                    //         $data['tardiness'][] = $tardinessData;
                    //         ProcessedTardiness::create($tardinessData);
                    // }
                    // $this->addTardinessData($data, $tardiness, $formattedDate);

                }

                // if ($formattedDate == '2024-12-23' && $employee_id == '1922') {
                //     dd($data['undertime']);
                // }
                // Get Overtime and holiday pay
                $time_in = $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='I')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('Y-m-d H:i:s'))->first() : null;
                $time_out = $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('Y-m-d H:i:s'))->first() : null;
                $hoursWorked = 0;
                $regularHoursWorked = 0;
                $hoursOT = 0;
                $holidayRestdayHours = 0;

                // if($formattedDate == '2024-12-24'){
                //     dd($time_out);

                // }


                if(($time_in && $time_out) || $ob) {

                    $overtime = $this->getOvertime($formattedDate, $employee_id, $start_date, $end_date);

                    $timeIn = Carbon::parse($time_in);
                    $timeOut = Carbon::parse($time_out);

                    if($ob){
                        $obTimeEnd = $ob->date_to.' '.$ob->to_time;
                        $obTimeStart = $ob->date_from.' '.$ob->from_time;
                    }

                    if($ob && $time_in)
                    {
                        // if($formattedDate == '2024-12-23'){
                        //     dd($time_out);
                        // }
                        if(new DateTime($obTimeStart) < new DateTime($time_in)){
                            $timeIn = Carbon::parse($formattedDate.' '.$ob->from_time);
                        } else {
                            $timeIn = $timeIn;
                        }
                    } else if ($ob && !$time_in){
                        $timeIn = Carbon::parse($formattedDate.' '.$ob->from_time);
                    }

                    if($ob && $time_out)
                    {
                        if(new DateTime($obTimeEnd) > new DateTime($time_out)){
                            $timeOut = Carbon::parse($formattedDate.' '.$ob->to_time);
                        } else {
                            $timeOut = $timeOut;
                        }
                    } else if ($ob && !$time_out){
                        $timeOut = Carbon::parse($ob->date_to.' '.$ob->to_time);
                    }

                    /**If there is filed OT and the timeout is beyond the approved OT */

                    if($overtime) {
                        $overtimeRegeneration = EmployeeOvertime::where('date_from', '<=', $formattedDate)
                            ->where('date_to', '>=', $formattedDate)
                            ->where('enabled', '=', 1)
                            ->where('status', '=', 2)
                            ->where('validated', '=', 1)
                            ->where('employee_id', '=', $employee_id)
                            // ->whereDate('approved_at', '>=', $start_date)
                            // ->whereDate('approved_at', '<=', $end_date)
                            ->orderByDesc('date_from')
                            ->first();

                        $overtimeOut = Carbon::parse($overtimeRegeneration->date_to.' '.$overtimeRegeneration->to_time);

                        if($timeOut->gt($overtimeOut)) {
                            $timeOut = $overtimeOut;
                        }
                    }

                    /** CHECK IF FALLSE WITHIN BREAKTIME, THIS AFFECT THE RESTDAY AND HOLIDAY DUTY ONLY */
                    $fallsOnBreakTime = false;
                    $breakTimeHours = 0;
                    $startBreakTime = Carbon::parse($formattedDate." 12:00:00");
                    $endBreakTime = Carbon::parse($formattedDate." 13:00:00");
                    if($timeIn->lt($endBreakTime)) {
                        $fallsOnBreakTime = true;
                        if($timeIn->gt($startBreakTime)) {
                            $breakTimeHours = $timeIn->diffInMinutes($endBreakTime)/60;
                        } else {
                            $breakTimeHours = $startBreakTime->diffInMinutes($endBreakTime)/60;
                        }
                    }

                    $schedIn = !$isRestDay ? Carbon::parse($formattedDate.' '.$schedule_in) : null;
                    $schedOut = !$isRestDay ? Carbon::parse($formattedDate.' '.$schedule_out) : null;

                      // Set the start of work to the scheduled time-in if time-in is earlier than schedule
                    if ($schedIn && $timeIn->lt($schedIn)) {
                        $timeIn = $schedIn;
                    }

                    // Calculate hours worked between adjusted time-in and time-out
                    $hoursWorked = abs((float)$timeOut->diffInMinutes($timeIn) / 60);

                    if($hoursWorked>8) {
                        $hoursWorked--;
                    }

                    if($schedOut) {
                        /**get regular hours worked */
                        if($timeOut->lt($schedOut)) {
                            $regularHoursWorked = (float)$timeIn->diffInHours($timeOut);
                            $holidayRestdayHours = (float)$timeIn->diffInHours($timeOut);

                            // if($formattedDate == '2024-12-22'){
                            //     dd($holidayRestdayHours);
                            // }
                        } else {
                            $regularHoursWorked = (float)$timeIn->diffInHours($schedOut);
                            $holidayRestdayHours = (float)$timeIn->diffInHours($schedOut);
                            // if($formattedDate == '2024-12-22'){
                            //     dd($holidayRestdayHours);
                            // }
                        }

                        // if($formattedDate == '2025-01-05'){
                        //     dd($regularHoursWorked);
                        // }

                        if($holidayRestdayHours > 6) {
                            $holidayRestdayHours--;
                        }

                        // if($formattedDate == '2025-01-10'){
                        //     // dd($timeOut);
                        //     dd([
                        //         'out' => $timeOut,
                        //         'schedout' => $schedOut
                        //     ]);
                        // }

                        // Check if time-out is beyond the scheduled time-out for overtime calculation
                        if ($timeOut->gt($schedOut)) {

                            $schedOut = Carbon::parse($formattedDate.' '.$scheduleData['schedule_out']);
                            $interval = $timeOut->diff($schedOut);

                            $minutes = (float) ltrim($interval->format('%i'), '0');
                            $totalMinutes = ($interval->days * 24 * 60) + ($interval->h * 60) + $interval->i;

                            if($totalMinutes >= $payrollSetting->overtime_minute_from) { /**if OT hours is equal or exceeds the minimum OT hours */
                                // $hoursOT = (int)$schedOut->diffInHours($timeOut);
                                $hoursOT = $interval->h + ($interval->i/60);
                            }
                        }

                        if($regularHoursWorked > 8) {
                            $regularHoursWorked--;
                        }
                    } else {
                        // $holidayRestdayHours = $timeIn->diffInMinutes($timeOut) / 60;
                        // Used microsecond to 0 so that it will not round off
                        $overtime = $this->getOvertime($formattedDate, $employee_id, $start_date, $end_date);

                        if($overtime) {
                            $overtimeOut = Carbon::parse($overtime->date_to.' '.$overtime->to_time);
                            if($timeOut->gt($overtimeOut)) {
                                $timeOut = $overtimeOut;
                            }
                            $overtimeIn = Carbon::parse($overtime->date_from.' '.$overtime->from_time);
                            if($timeIn->lt($overtimeIn)) {
                                $timeIn = $overtimeIn;
                            }
                        }
                        // if($formattedDate == '2025-01-05') dd($timeIn);
                        $timeInTruncated = $timeIn->copy()->setSecond(0)->setMicrosecond(0);
                        $timeOutTruncated = $timeOut->copy()->setSecond(0)->setMicrosecond(0);
                        $holidayRestdayHours = $timeInTruncated->diffInMinutes($timeOutTruncated) / 60;

                        // $onePM = $timeInTruncated->copy()->setTime(13, 0, 0); // 1:00 PM on same date

                        if($fallsOnBreakTime && $holidayRestdayHours >= 5) {
                            // if($formattedDate == '2025-01-20') dd($holidayRestdayHours);
                            $holidayRestdayHours = $holidayRestdayHours >= 9 ? $holidayRestdayHours - $breakTimeHours : $holidayRestdayHours;
                        }

                        if($overtime){
                            if($overtime->break_time){
                                $hoursOT = $hoursOT - ($overtime->break_time / 60);
                            }
                        }

                        if($holidayRestdayHours > 8) {
                            $hoursOT = $holidayRestdayHours - 8;
                            $holidayRestdayHours = 8;

                            // $holidayRestdayHours = round($holidayRestdayHours - 1, 2) > 8 ? 8 : round($holidayRestdayHours - 1, 2);
                        }

                    }


                    /**IF OT hours exceeds the MAX OT based on payroll settings */
                    if($hoursOT > 0 && $hoursOT > ceil($payrollSetting->overtime_minute_to/60)) {
                        $hoursOT = ceil($payrollSetting->overtime_minute_to/60);
                    }

                    // if($formattedDate == '2024-12-22'){
                    //     dd($holidayRestdayHours);
                    // }

                    // if($formattedDate == '2024-12-22'){
                    //     dd($holidayRestdayHours);
                    // }
                }
                // if($employee_id==661 && $formattedDate=='2024-12-22') dd(['rdHours' => $holidayRestdayHours, 'otHours'=>$hoursOT]);
                 $holidayData = [];
                // if($formattedDate == '2025-01-01'){
                //             dd($isAbsentBeforeHoliday);
                //         }
                /**Daily wage and regular holiday AND not overtime*/
                // if($formattedDate=='2025-01-01') dd(['rate' => $payrollRate,'isHoliday' => $isHoliday, 'absentB4' => $isAbsentBeforeHoliday, 'overtime' => $overtime]);
                if($payrollRate=='Daily' && $isHoliday && ($holiday->holiday_type == 1 && !$isAbsentBeforeHoliday) && !$overtime) {
                    // if($formattedDate == '2024-12-25')
                    // {
                    //     dd();
                    // }
                    $holidaySetting = PremiumOvertimePaySetting::where([
                        'isRestday' => 0,
                        'holiday_type_id' => $holiday->holiday_type,
                        'isOvertime' => 0
                    ])->first();

                    // if($formattedDate == '2024-12-25')
                    // {
                    //     dd($holidaySetting);
                    // }

                        // dd($timelogs);
                    $holidayData = [
                        'employee_id' => $employee_id,
                        'company_id' => $company_id,
                        'dealership_id' => $dealer_id,
                        'department_id' => $department_id,
                        'payroll_date' => $payroll_date,
                        'date' => $formattedDate,
                        'payment_setting_id' => $holidaySetting->id,
                        'payment_setting_name' => $holidaySetting->name,
                        'holiday_name' => $holiday->name,
                        'holiday_type' => $holiday->holiday_type,
                        'percentage' => $timelogs->isNotEmpty() ? $holidaySetting->percentage : 100,
                        'no_of_hours' => $holidayRestdayHours > 0 ? $holidayRestdayHours : 8,
                        'schedule_in' => $scheduleData['schedule_in'] ?? null,
                        'schedule_out' => $scheduleData['schedule_out'] ?? null,
                        'time_in' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='I')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                        'time_out' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                        'isRestday' => false,

                     ];
                     $data['holiday'][] = $holidayData;
                     ProcessedHolidayRestdayDuty::create($holidayData);
                    }

                // if($isHoliday && $overtime && ($timelogs->isNotEmpty() || $ob) && $holidayRestdayHours > 0) {

                //     $regularhoursWorked = 0; /**reset regular hours, set holiday hours instead */
                //     // DB::enableQueryLog();
                //     $holidaySetting = PremiumOvertimePaySetting::where([
                //         'isRestday' => $scheduleData['restday'] ?? 0,
                //         'holiday_type_id' => $holiday->holiday_type ?? null,
                //         'isOvertime' => 0
                //     ])->first();
                //     // if($employee_id == 60653 && !$holidaySetting)
                //     // {
                //     //     dd(DB::getQueryLog());
                //     // }
                //      $holidayData = [
                //         'employee_id' => $employee_id,
                //         'company_id' => $company_id,
                //         'dealership_id' => $dealer_id,
                //         'department_id' => $department_id,
                //         'payroll_date' => $payroll_date,
                //         'date' => $formattedDate,
                //         'payment_setting_id' => $holidaySetting->id,
                //         'payment_setting_name' => $holidaySetting->name,
                //         'holiday_name' => $holiday->name,
                //         'holiday_type' => $holiday->holiday_type,
                //         'percentage' => $holidaySetting->percentage,
                //         'no_of_hours' => $holidayRestdayHours,
                //         'schedule_in' => $scheduleData['schedule_in'] ?? null,
                //         'schedule_out' => $scheduleData['schedule_out'] ?? null,
                //         'time_in' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='I')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                //         'time_out' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                //      ];
                //      $data['holiday'][] = $holidayData;
                //      ProcessedHolidayRestdayDuty::create($holidayData);
                // }

                $overtime = $this->getOvertime($formattedDate, $employee_id, $start_date, $end_date);

                $overtimeData = [];

                if($overtime && ($timelogs->isNotEmpty() || $ob) && !empty($scheduleData)) {

                    $overtimeSetting = PremiumOvertimePaySetting::where([
                        'isRestday' => $scheduleData['restday'] ?? 0,
                        'holiday_type_id' => $holidayData['type'] ?? null,
                        'isOvertime' => true
                        ])->first();
                // if($employee_id == '60623') { dd(DB::getQueryLog()); }
                // dd($formattedDate.' '.$schedule->schedule->from_time. '  |  '.$formattedDate.' '.$schedule->schedule->to_time);
                // Compute the difference in hours
                    /**IF RESTDAY DUTY */
                    if(isset($scheduleData['restday']) && $scheduleData['restday']==1) {
                        $regularhoursWorked = 0; /**reset regular hours, set restday duty hours instead */
                        $holidaySetting = PremiumOvertimePaySetting::where([
                        'isRestday' => 1,
                        'holiday_type_id' => $holiday->holiday_type ?? null,
                        'isOvertime' => 0
                        ])->first();
                            // dd(
                            //     [
                            //         'holiday_rest_day_hours' => $holidayRestdayHours,
                            //         'overtime_hours' => $overtime->hours,

                            //     ]
                            // );

                        // if($overtime->break_time){
                        //     $hoursOT -= $overtime->break_time / 60;
                        //     $holidayRestdayHours -= $overtime->break_time / 60;
                        // }

                        $holidayData = [
                            'employee_id' => $employee_id,
                            'company_id' => $company_id,
                            'dealership_id' => $dealer_id,
                            'department_id' => $department_id,
                            'payroll_date' => $payroll_date,
                            'date' => $formattedDate,
                            'no_of_hours' => $overtime->hours - ($overtime->break_time ?? 0) / 60 < $holidayRestdayHours ? $overtime->hours - ($overtime->break_time ?? 0) / 60 : $holidayRestdayHours,
                            'payment_setting_id' => $holidaySetting->id,
                            'payment_setting_name' => $holidaySetting->name,
                            'holiday_name' => $holiday->name ?? null,
                            'holiday_type' => $holiday->holiday_type ?? null,
                            'percentage' => $holidaySetting->percentage,
                            'schedule_in' => $scheduleData['schedule_in'] ?? null,
                            'schedule_out' => $scheduleData['schedule_out'] ?? null,
                            'time_in' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='I')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                            'time_out' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                            'isRestday' => $isRestDay,
                            'meal' => $overtime ? $overtime->meal : 0,
                            'meal_amount' => $overtime ? $overtime->meal_amount : 0,
                            'transportation' => $overtime ? $overtime->transportation : 0,
                            'transportation_amount' => $overtime ? $overtime->transportation_amount : 0,
                        ];

                        $data['holiday'][] = $holidayData;
                        ProcessedHolidayRestdayDuty::create($holidayData);

                        /**In excess of 8 hours put to OT */
                        // if($formattedDate == '2025-11-23'){
                        //     dd([
                        //         'otHours' => $hoursOT,
                        //         'overtimeHours' => $overtime->hours,
                        //         'Cal' => $overtime->hours - ($overtime->break_time ?? 0) / 60,
                        //         'breakTime' => $overtime->hours - ($overtime->break_time ?? 0) / 60,
                        //         'hoursMinus8' => $overtime->hours -8,
                        //     ]);
                        // }

                        if($hoursOT > 0 && $overtime->hours - ($overtime->break_time ?? 0) / 60 > 8) {
                            $overtimeData = [
                                'employee_id' => $employee_id,
                                'company_id' => $company_id,
                                'dealership_id' => $dealer_id,
                                'department_id' => $department_id,
                                'payroll_date' => $payroll_date,
                                'date' => $formattedDate,
                                'no_of_hours' => ($overtime->hours-8) < $hoursOT ? ($overtime->hours-8) : $hoursOT,
                                'payment_setting_id' => $overtimeSetting->id,
                                'payment_setting_name' => $overtimeSetting->name,
                                'percentage' => $overtimeSetting->percentage,
                                'schedule_in' => $scheduleData['schedule_in'] ?? null,
                                    'schedule_out' => $scheduleData['schedule_out'] ?? null,
                                    // 'time_in' => $time_in_ot,
                                    // 'time_out' => $time_out_ot,
                                    'time_in' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='I')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                                    'time_out' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                                    'meal' => $isRestDay ? 0 : $overtime->meal,
                                    'transportation' => $isRestDay ? 0 :  $overtime->transportation,
                                    'meal_amount' => $isRestDay ? 0 : $overtime->meal_amount,
                                    'transportation_amount' => $isRestDay ? 0 : $overtime->transportation_amount,
                            ];
                            $data['overtime'][] = $overtimeData;

                            ProcessedOvertime::create($overtimeData);
                        }
                    } else { /**If not restday */
                        /**if Daily and has timelog and has approved OT */
                        // if($formattedDate=='2025-01-09') dd(['rate' => $payrollRate,'isHoliday' => $isHoliday, 'absentB4' => (!$isAbsentBeforeHoliday || $timelogs->isNotEmpty()), 'hours' => $holidayRestdayHours]);
                        if($payrollRate=='Daily' && $isHoliday && (!$isAbsentBeforeHoliday || $timelogs->isNotEmpty()) && $holidayRestdayHours > 0) {

                            $holidaySetting = PremiumOvertimePaySetting::where([
                                'isRestday' => 0,
                                'holiday_type_id' => $holiday->holiday_type,
                                'isOvertime' => 0
                            ])->first();
                                // dd($timelogs);
                            $holidayData = [
                                'employee_id' => $employee_id,
                                'company_id' => $company_id,
                                'dealership_id' => $dealer_id,
                                'department_id' => $department_id,
                                'payroll_date' => $payroll_date,
                                'date' => $formattedDate,
                                'payment_setting_id' => $holidaySetting->id,
                                'payment_setting_name' => $holidaySetting->name,
                                'holiday_name' => $holiday->name,
                                'holiday_type' => $holiday->holiday_type,
                                'percentage' => $timelogs->isNotEmpty() ? $holidaySetting->percentage : 100,
                                'no_of_hours' => $holidayRestdayHours > 0 ? $holidayRestdayHours : 8,
                                'schedule_in' => $scheduleData['schedule_in'] ?? null,
                                'schedule_out' => $scheduleData['schedule_out'] ?? null,
                                'time_in' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='I')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                                'time_out' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                                'isRestday' => false,

                             ];
                             $data['holiday'][] = $holidayData;
                             ProcessedHolidayRestdayDuty::create($holidayData);
                        } else if($isHoliday && !$isAbsentBeforeHoliday && $timelogs->isNotEmpty() && $holidayRestdayHours > 0) {
                            $holidaySetting = PremiumOvertimePaySetting::where([
                                'isRestday' => 0,
                                'holiday_type_id' => $holiday->holiday_type,
                                'isOvertime' => 0
                            ])->first();
                                // dd($timelogs);
                            $holidayData = [
                                'employee_id' => $employee_id,
                                'company_id' => $company_id,
                                'dealership_id' => $dealer_id,
                                'department_id' => $department_id,
                                'payroll_date' => $payroll_date,
                                'date' => $formattedDate,
                                'payment_setting_id' => $holidaySetting->id,
                                'payment_setting_name' => $holidaySetting->name,
                                'holiday_name' => $holiday->name,
                                'holiday_type' => $holiday->holiday_type,
                                'percentage' => $holidaySetting->percentage,
                                'no_of_hours' => $holidayRestdayHours,
                                'schedule_in' => $scheduleData['schedule_in'] ?? null,
                                'schedule_out' => $scheduleData['schedule_out'] ?? null,
                                'time_in' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='I')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                                'time_out' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                                'isRestday' => false,

                             ];
                            //  if($formattedDate == '2025-01-09') dd($holidayData);
                             $data['holiday'][] = $holidayData;
                             ProcessedHolidayRestdayDuty::create($holidayData);
                        }

                        if (in_array($formattedDate, $processedOTDates)) {
                            continue;
                        }
                        if($hoursOT > 0) {

                            $isLastDay = $formattedDate == Carbon::parse($overtime->date_to)->toDateString();
                            $isMultiDay = $overtime->date_from != $overtime->date_to ;
                            $isRegularShift = isset($scheduleData['restday']) && $scheduleData['restday'] == 0;

                            // if($overtime->break_time){
                            //     $hoursOT -= $overtime->break_time / 60;
                            // }

                            // dd($scheduleData);
                            // if (!$isLastDay || !$isMultiDay || !$isRegularShift) {
                                // Only process OT if it's not the last day of a multi-day OT on a regular shift
                                $overtimeData = [
                                    'employee_id' => $employee_id,
                                    'company_id' => $company_id,
                                    'dealership_id' => $dealer_id,
                                    'department_id' => $department_id,
                                    'payroll_date' => $payroll_date,
                                    'date' => $formattedDate,
                                    'no_of_hours' => $overtime->hours < $hoursOT ? $overtime->hours : $hoursOT,
                                    'payment_setting_id' => $overtimeSetting->id,
                                    'payment_setting_name' => $overtimeSetting->name,
                                    'percentage' => $overtimeSetting->percentage,
                                    'schedule_in' => $scheduleData['schedule_in'] ?? null,
                                    'schedule_out' => $scheduleData['schedule_out'] ?? null,
                                    'time_in' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='I')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                                    'time_out' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                                    'meal' => $overtime->meal,
                                    'transportation' => $overtime->transportation,
                                    'meal_amount' => $overtime->meal_amount,
                                    'transportation_amount' => $overtime->transportation_amount,
                                ];
                                $data['overtime'][] = $overtimeData;
                                ProcessedOvertime::create($overtimeData);

                                // Track OT dates if needed
                                // $processedOTDates[] = $formattedDate;
                            // }

                        }
                    }
                }
                // $this->addOvertimeData($data, $overtime, $formattedDate);

                /**Night Differential */
                if($time_in || $ob) {

                    if($ob){
                        $nightDifferentialTime = Carbon::parse($ob->date_from. $payrollSetting->night_differential_to);
                        $timeInTime = Carbon::parse($ob->date_from. $ob->from_time);
                        $timeOutTime = Carbon::parse($ob->date_from. $ob->to_time);
                    } else {
                        $nightDifferentialTime = Carbon::parse($formattedDate. $payrollSetting->night_differential_to);
                        $timeInTime = Carbon::parse($time_in);
                        $timeOutTime = $time_out ? Carbon::parse($time_out) : "";
                    }

                    // $startTime = Carbon::parse($formattedDate.' '.$schedule_in);

                    // if($formattedDate == '2024-12-23'){
                        // if($timeInTime < $startTime){
                        //     $timeInTime = $startTime;
                        // } elseif ($timeInTime->gt($startTime->addMinutes(6))) {
                        //     $timeInTime = $timeInTime;
                        // }
                    // }

                    $night_diff_hours = 0;

                    if($schedule){
                        $dayOfWeek = date('l', strtotime($formattedDate));
                        $daysArray = explode(',', $schedule->schedule->day_off);

                        if(!in_array($dayOfWeek, $daysArray)) {
                            if($overtime){

                                $nightDiffStart = $payrollSetting->night_differential_from;
                                $nightDiffEnd = $payrollSetting->night_differential_to;

                                // Create Carbon instances for overtime start and end
                                $overtimeStart = Carbon::parse($overtime->date_from . ' ' . $overtime->from_time);

                                // if($ob){
                                //     if(Carbon::parse($time_out) > Carbon::parse($ob->date_to . ' ' . $ob->to_time)){
                                //         if(Carbon::parse($overtime->date_to . ' ' . $overtime->to_time) <= Carbon::parse($time_out)){
                                //             $overtimeEnd = Carbon::parse($overtime->date_to . ' ' . $overtime->to_time);
                                //         } else {
                                //             $overtimeEnd = Carbon::parse($overtime->date_to . ' ' . Carbon::parse($time_out)->format('H:i:s'));
                                //         }
                                //     } else {
                                //         if(Carbon::parse($overtime->date_to . ' ' . $overtime->to_time) <= Carbon::parse($ob->date_to . ' ' . $ob->to_time)){
                                //             $overtimeEnd = Carbon::parse($overtime->date_to . ' ' . $overtime->to_time);
                                //         } else {
                                //             $overtimeEnd = Carbon::parse($overtime->date_to . ' ' . $ob->to_time);
                                //         }
                                //     }
                                // } else {
                                //     // dd(Carbon::parse($time_out)->format('H:i:s'));
                                //     if(Carbon::parse($overtime->date_to . ' ' . $overtime->to_time) <= Carbon::parse($time_out)){
                                //         $overtimeEnd = Carbon::parse($overtime->date_to . ' ' . Carbon::parse($time_out)->format('H:i:s'));
                                //     } else {
                                //         $overtimeEnd = Carbon::parse($overtime->date_to . ' ' . $overtime->to_time);
                                //     }
                                // }

                                $overtimeEnd = Carbon::parse($overtime->date_to . ' ' . $overtime->to_time);
                                // If overtime ends earlier than the start, meaning next day
                                if ($overtimeEnd->lt($overtimeStart)) {
                                    $overtimeEnd->addDay();
                                }

                                // if($formattedDate == '2025-06-05'){
                                //     dd($overtimeEnd);
                                // }
                                $night_diff_hours = 0;
                                $currentDate = $overtimeStart->copy()->startOfDay();
                                $endDate = $overtimeEnd->copy()->startOfDay();

                                $sixAM = Carbon::parse($overtime->date_to . ' 06:00:00');

                                // Check if $overtimeEnd is earlier than 6:00 AM

                                if ($overtimeEnd->gt($sixAM)) {
                                    while ($currentDate->lte($endDate)) {
                                        // Get today's night differential period
                                        $nightDiffStartTime = Carbon::parse($currentDate->format('Y-m-d') . ' ' . $nightDiffStart);
                                        $nightDiffEndTime = Carbon::parse($currentDate->format('Y-m-d') . ' ' . $nightDiffEnd);

                                        // If night differential end time is before start time, it spans to the next day
                                        if ($nightDiffEndTime->lt($nightDiffStartTime)) {
                                            $nightDiffEndTime->addDay();
                                        }

                                        // Get current day's overtime period
                                        $dayOvertimeStart = $overtimeStart->gt($currentDate) ? $overtimeStart : $currentDate->copy()->setTime(0, 0, 0);
                                        $nextDay = $currentDate->copy()->addDay()->setTime(0, 0, 0);
                                        $dayOvertimeEnd = $overtimeEnd->lt($nextDay) ? $overtimeEnd : $nextDay;

                                        // Only calculate overlap if there's actual overtime on this day
                                        if ($dayOvertimeStart->lt($dayOvertimeEnd)) {
                                            // Check overlap between day's overtime period and night differential period
                                            $overlapStart = $dayOvertimeStart->gt($nightDiffStartTime) ? $dayOvertimeStart : $nightDiffStartTime;
                                            $overlapEnd = $dayOvertimeEnd->lt($nightDiffEndTime) ? $dayOvertimeEnd : $nightDiffEndTime;

                                            // If there's an overlap, add it to the total night differential hours
                                            if ($overlapStart->lt($overlapEnd)) {
                                                $night_diff_hours += $overlapStart->diffInMinutes($overlapEnd);
                                            }
                                        }

                                        $currentDate->addDay();
                                    }



                                    $morningDiff = 0;
                                    // if($formattedDate == '2025-01-02'){
                                        if($startTime <= $nightDifferentialTime){

                                            if($time_in < $startTime){
                                                $morningDiff += $startTime->diffInMinutes($nightDifferentialTime);

                                            } else if ($time_in > $startTime && $time_in < $nightDifferentialTime){

                                                $morningDiff += $time_in->diffInMinutes($nightDifferentialTime);
                                            }
                                            // dd(Carbon::parse($time_in));

                                        }

                                        // if($formattedDate == '2024-12-23')
                                        // {
                                        //     dd($morningDiff);
                                            // dd(Carbon::parse($formattedDate. ' ' . $nightDiffEnd));
                                        // if($timeInTime < Carbon::parse($formattedDate. ' ' . $nightDiffEnd)){
                                        //     // dd($nightDiffEnd);
                                        //     $morningDiff += $timeInTime->diffInMinutes(Carbon::parse($formattedDate. ' ' . $nightDiffEnd));

                                        // }
                                        // }
                                    // }

                                    // if($)
                                    // Convert minutes to hours
                                    $night_diff_hours = ($night_diff_hours + $morningDiff) / 60;

                                } else {
                                    $overtimeDateFrom = $overtime->date_from;

                                    $overtimeCount = EmployeeOvertime::where('date_from', '<=', $formattedDate)
                                    ->where('date_to', '>=', $formattedDate)
                                    ->where('enabled', '=', 1)
                                    ->where('status', '=', 2)
                                    ->where('validated', '=', 1)
                                    ->where('employee_id', '=', $employee_id)
                                    ->count();

                                    if($overtimeCount > 1){
                                            $newOvertime = EmployeeOvertime::where('date_from', '<=', $formattedDate)
                                            ->where('date_to', '>=', $formattedDate)
                                            ->where('enabled', '=', 1)
                                            ->where('status', '=', 2)
                                            ->where('validated', '=', 1)
                                            ->where('employee_id', '=', $employee_id)
                                            ->orderBy('date_from', 'desc')
                                            ->first();

                                        $overtimeStart = Carbon::parse($newOvertime->date_from . ' ' . $newOvertime->from_time);
                                        $overtimeEnd = Carbon::parse($newOvertime->date_to . ' ' . $newOvertime->to_time);

                                        $overtimeDateFrom = $newOvertime->date_from;
                                    }

                                    if(date('Y-m-d', strtotime($overtimeDateFrom)) == $formattedDate){
                                        // This is now the original if block
                                        while ($currentDate->lte($endDate)) {
                                            // Get today's night differential period
                                            $nightDiffStartTime = Carbon::parse($currentDate->format('Y-m-d') . ' ' . $nightDiffStart);
                                            $nightDiffEndTime = Carbon::parse($currentDate->format('Y-m-d') . ' ' . $nightDiffEnd);
                                            // If night differential end time is before start time, it spans to the next day
                                            if ($nightDiffEndTime->lt($nightDiffStartTime)) {
                                                $nightDiffEndTime->addDay();
                                            }

                                            // Get current day's overtime period
                                            $dayOvertimeStart = $overtimeStart->gt($currentDate) ? $overtimeStart : $currentDate->copy()->setTime(0, 0, 0);
                                            $nextDay = $currentDate->copy()->addDay()->setTime(0, 0, 0);

                                            // FIXED: Handle overtime that spans into the next day
                                            if ($overtimeEnd->gt($nextDay)) {
                                                // If overtime extends beyond midnight, we need to handle it differently
                                                if ($currentDate->format('Y-m-d') == $overtimeEnd->copy()->subDay()->format('Y-m-d')) {
                                                    // This is the last day of overtime that extends into the next day
                                                    $dayOvertimeEnd = $overtimeEnd; // Include the full overtime end time
                                                } else {
                                                    // This is not the last day, so end at midnight
                                                    $dayOvertimeEnd = $nextDay;
                                                }
                                            } else {
                                                // Overtime doesn't extend past midnight or ends before/at midnight
                                                $dayOvertimeEnd = $overtimeEnd->lt($nextDay) ? $overtimeEnd : $nextDay;
                                            }

                                            // Only calculate overlap if there's actual overtime on this day
                                            if ($dayOvertimeStart->lt($dayOvertimeEnd)) {
                                                // Check overlap between day's overtime period and night differential period
                                                $overlapStart = $dayOvertimeStart->gt($nightDiffStartTime) ? $dayOvertimeStart : $nightDiffStartTime;
                                                $overlapEnd = $dayOvertimeEnd->lt($nightDiffEndTime) ? $dayOvertimeEnd : $nightDiffEndTime;

                                                // If there's an overlap, add it to the total night differential hours
                                                if ($overlapStart->lt($overlapEnd)) {
                                                    $night_diff_hours += $overlapStart->diffInMinutes($overlapEnd);
                                                }

                                                // Debug output for the specific date
                                                // if($formattedDate == '2025-05-26'){
                                                //     echo "Day: " . $currentDate->format('Y-m-d') . "\n";
                                                //     echo "Day Overtime Start: " . $dayOvertimeStart->format('Y-m-d H:i:s') . "\n";
                                                //     echo "Day Overtime End: " . $dayOvertimeEnd->format('Y-m-d H:i:s') . "\n";
                                                //     echo "Night Diff Start: " . $nightDiffStartTime->format('Y-m-d H:i:s') . "\n";
                                                //     echo "Night Diff End: " . $nightDiffEndTime->format('Y-m-d H:i:s') . "\n";
                                                //     echo "Overlap Start: " . $overlapStart->format('Y-m-d H:i:s') . "\n";
                                                //     echo "Overlap End: " . $overlapEnd->format('Y-m-d H:i:s') . "\n";
                                                //     echo "Minutes added: " . ($overlapStart->lt($overlapEnd) ? $overlapStart->diffInMinutes($overlapEnd) : 0) . "\n\n";
                                                // }
                                            }
                                            $currentDate->addDay();
                                        }

                                        $morningDiff = 0;

                                        if($startTime <= $nightDifferentialTime){

                                            if($time_in < $startTime){
                                                $morningDiff += $startTime->diffInMinutes($nightDifferentialTime);

                                            } else if ($time_in > $startTime && $time_in < $nightDifferentialTime){

                                                $morningDiff += $time_in->diffInMinutes($nightDifferentialTime);
                                            }
                                            // dd(Carbon::parse($time_in));

                                        }

                                        $night_diff_hours = ($night_diff_hours + $morningDiff) / 60;
                                    }
                                }
                            } else {
                                // dd([
                                //     'startTime' => $startTime,
                                //     'timeInTime' => $timeInTime,
                                // ]);

                                if($timeInTime->lt($nightDifferentialTime) && $time_in > $startTime && $time_in < $nightDifferentialTime) {
                                    $night_diff_hours = (float)$timeInTime->diffInHours($nightDifferentialTime);
                                }

                                // if($formattedDate == '2025-11-25'){
                                //     dd($night_diff_hours.'last');
                                // }
                            }
                        } else {
                                if($overtime){
                                    $nightDifferentialFromTime = Carbon::parse($overtime->date_from . ' ' . $payrollSetting->night_differential_from);
                                    $nightDifferentialToTime = Carbon::parse($overtime->date_to . ' ' . $payrollSetting->night_differential_to);
                                    $nightDifferentialTimeOut = '';

                                    $overtimeDateTimeOut = Carbon::parse($overtime->date_to . ' '. $overtime->to_time);
                                    if($overtimeDateTimeOut->lt($nightDifferentialToTime)){
                                        // echo $overtimeDateTimeOut. ' - '.$nightDifferentialToTime;
                                        $nightDifferentialTimeOut = $overtimeDateTimeOut;
                                    } else {
                                        $nightDifferentialTimeOut = $nightDifferentialToTime;
                                    }

                                    if($timeInTime->lt($nightDifferentialFromTime)) {
                                        // $night_diff_hours = (float)$nightDifferentialFromTime->diffInHours($nightDifferentialTimeOut) * 60;
                                        $night_diff_hours = (float)$nightDifferentialFromTime->diffInHours($nightDifferentialTimeOut);
                                        // if($employee_id =='1798'){
                                        //     dd($night_diff_hours);
                                        // }
                                    } else {
                                        // if($formattedDate == '2024-12-22')
                                        // {
                                        //     dd($nightDifferentialTime->setDateFrom($overtime->date_to));
                                        //     // dd($timeOutTime);
                                        // }
                                        // if($timeInTime->format('Y-m-d'))
                                        if($timeInTime->lt($nightDifferentialTime->setDateFrom($overtime->date_to))) {
                                            $night_diff_hours = (float)$timeInTime->diffInHours($nightDifferentialTimeOut);
                                        }
                                    }
                                }
                        }
                    }

                    if($night_diff_hours > 0) {
                        $nightDiffData = [
                            'employee_id' => $employee_id,
                            'company_id' => $company_id,
                            'dealership_id' => $dealer_id,
                            'department_id' => $department_id,
                            'payroll_date' => $payroll_date,
                            'date' => $formattedDate,
                            'no_of_hours' => $night_diff_hours,
                            'payment_setting_id' => $holidayData['payment_setting_id'] ?? 0,
                            'payment_setting_name' => $holidayData['payment_setting_name'] ?? null,
                            'percentage' => ($holidayData['percentage'] ?? 100) * ($payrollSetting->night_differential_rate/100),
                            'schedule_in' => $scheduleData['schedule_in'] ?? null,
                            'schedule_out' => $scheduleData['schedule_out'] ?? null,
                            'time_in' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='I')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                            'time_out' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                        ];
                        $data['night_differential'][] = $nightDiffData;

                        ProcessedNightDifferential::create($nightDiffData);
                    }
                }

                if($time_out) {

                    if($schedule){
                        $dayOfWeek = date('l', strtotime($formattedDate));
                        $daysArray = explode(',', $schedule->schedule->day_off);

                        if(in_array($dayOfWeek, $daysArray)) {
                            if($overtime){
                                if(new DateTime($overtime->to_time) > new DateTime($time_out)){
                                    $timeOut = Carbon::parse($formattedDate.' '.$overtime->to_time);
                                } else {
                                    $timeOut = $time_out;
                                }

                                $nightDifferentialTime = Carbon::parse($formattedDate. $payrollSetting->night_differential_from);
                                $night_diff_hours = 0;
                                if($nightDifferentialTime->lt($timeOut)) {
                                    $night_diff_hours = (float)$nightDifferentialTime->diffInHours($timeOut);
                                }

                            }
                        } else {
                            $dayOfWeek = date('l', strtotime($formattedDate));
                            $daysArray = explode(',', $schedule->schedule->day_off);

                            $daysWFHArray = explode(',', $schedule->schedule->wfh);
                            $daysCWSArray = explode(',', $schedule->schedule->cws_day);
                            if(in_array($dayOfWeek,$daysCWSArray)) {
                                $schedule_in = $schedule->schedule->cws_from_time;
                                $schedule_out = $schedule->schedule->cws_to_time;
                            } elseif(!in_array($dayOfWeek, $daysArray)) {
                                $schedule_in = $schedule->schedule->from_time;
                                $schedule_out = $schedule->schedule->to_time;
                            }

                            $nightDifferentialTime = Carbon::parse($formattedDate. $payrollSetting->night_differential_from);
                            $schedOut = $formattedDate . ' ' .$schedule_out;
                            // $timeOutTime = Carbon::parse($time_out);

                            if(new DateTime($time_out) > new DateTime($schedOut)){
                                $timeOutTime = Carbon::parse($schedOut);
                            } else {
                                $timeOutTime = $time_out;
                            }

                            $night_diff_hours = 0;
                            if($nightDifferentialTime->lt($timeOutTime)) {
                                $night_diff_hours = (float)$nightDifferentialTime->diffInHours($timeOutTime);
                            }
                        }
                    }

                    if($night_diff_hours > 0) {
                        $nightDiffData = [
                            'employee_id' => $employee_id,
                            'company_id' => $company_id,
                            'dealership_id' => $dealer_id,
                            'department_id' => $department_id,
                            'payroll_date' => $payroll_date,
                            'date' => $formattedDate,
                            'no_of_hours' => $night_diff_hours,
                            'payment_setting_id' => $holidayData['payment_setting_id'] ?? 0,
                            'payment_setting_name' => $holidayData['payment_setting_name'] ?? null,
                            'percentage' => ($holidayData['percentage'] ?? 100) * ($payrollSetting->night_differential_rate/100),
                            'schedule_in' => $scheduleData['schedule_in'] ?? null,
                            'schedule_out' => $scheduleData['schedule_out'] ?? null,
                            'time_in' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='I')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                            'time_out' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                        ];
                        $data['night_differential'][] = $nightDiffData;

                        ProcessedNightDifferential::create($nightDiffData);
                    }
                }

                /**set default value for days and hours absent */
                $days_absent = 0;
                $hours_absent = 0;

                // Check Tardiness
                $halfDayLeave = $leave && ($leave->half_day == 1 || $leave->half_day == 2);
                $wholeDayLeave = $leave && $leave->hours >= 8;
                $undertime_minutes_for_absent = 0;

                if(!$isAlwaysPresent){

                    if(!$holiday || ($holiday && $payrollRate == 'Daily' && $holiday->holiday_type != 1) || ($holiday && $payrollRate == 'Monthly' && $timelogs->isNotEmpty())){
                        $tardiness = $this->getTardiness($timelogs, $schedule, $halfDayLeave, $ob, $offsetAvailment, $employee->classification_id, $wholeDayLeave,$company_id);
                        if($tardiness && $tardiness <= 60) {

                            $tardinessData = [
                                    'employee_id' => $employee_id,
                                    'company_id' => $company_id,
                                    'dealership_id' => $dealer_id,
                                    'department_id' => $department_id,
                                    'payroll_date' => $payroll_date,
                                    'date' => $formattedDate,
                                    'schedule_in' => $scheduleData['schedule_in'] ?? null,
                                    'schedule_out' => $scheduleData['schedule_out'] ?? null,
                                    'time_in' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='I')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : '',
                                    'time_out' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : '',
                                    'no_of_minutes' => $tardiness,
                                ];
                                $data['tardiness'][] = $tardinessData;
                                ProcessedTardiness::create($tardinessData);
                            }



                        // Get Undertime
                        $undertime = $this->getUndertime($timelogs, $schedule, $workSuspension, $formattedDate, $ob, $offsetAvailment, $wfhRecord, $halfDayLeave);


                        $undertime_minutes = 0;
                        if($tardiness && $tardiness >= $payrollSetting->undertime_minute_from) {
                            $undertime_minutes = $tardiness;
                        }
                        if($undertime) $undertime_minutes += $undertime;


                        if(($undertime_minutes > 0 && $undertime_minutes > 239) || ($undertime_minutes >= 61 && $undertime_minutes < 240)) {
                            $undertimeData =
                                [
                                    'employee_id' => $employee_id,
                                    'company_id' => $company_id,
                                    'dealership_id' => $dealer_id,
                                    'department_id' => $department_id,
                                    'payroll_date' => $payroll_date,
                                    'date' => $formattedDate,
                                    'schedule_in' => $scheduleData['schedule_in'] ?? null,
                                    'schedule_out' => $scheduleData['schedule_out'] ?? null,
                                    'time_in' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='I')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                                    'time_out' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                                    'no_of_minutes' => $undertime_minutes,
                                ];
                            // ProcessedUndertime::create($undertimeData);
                            // $data['undertime'][] = $undertimeData;
                        }

                        // if($formattedDate == '2025-12-03'){
                        //     dd($undertime_minutes);
                        // }

                        $undertime_minutes_for_absent = $undertime_minutes;
                    }

                    // if ((!$timelogs->count() && (!$leave || ($leave && ($leave->without_pay == 1 || $leave->hours < $scheduleData['duty_hours']))) && (!$isHoliday || $isAbsentBeforeHoliday) && $schedule && !$ob && !$offsetAvailment) || $undertime_minutes_for_absent > 479) {
                    if (
                        (
                            (
                                $timelogs->filter(fn($tl) => $tl->in_out == 'I')->isEmpty() ||
                                $timelogs->filter(fn($tl) => $tl->in_out == 'O')->isEmpty() ||
                                (
                                    (
                                        $timelogs->filter(fn($tl) => $tl->in_out == 'I')->isNotEmpty() &&
                                        $timelogs->filter(fn($tl) => $tl->in_out == 'O')->isNotEmpty() &&
                                        (
                                            abs(
                                                Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'O')->first()->datetimelog)
                                                ->diffInMinutes(Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'I')->first()->datetimelog))
                                            ) <= 2
                                        )
                                    )
                                    ||
                                    (!$leave || ($leave && ($leave->without_pay == 1 || $leave->hours < $scheduleData['duty_hours'])) || ($timelogs->filter(fn($tl) => $tl->in_out == 'I')->isEmpty() && $timelogs->filter(fn($tl) => $tl->in_out == 'O')->isEmpty() && ($leave->half_day == 1 || $leave->half_day == 2)))
                                ) &&
                                (!$isHoliday || $isAbsentBeforeHoliday || ($holiday && $payrollRate=='Daily' && $holiday->holiday_type != 1))
                                &&
                                $schedule && !$ob && !$offsetAvailment
                            )
                            || ($undertime_minutes_for_absent > 239)
                        )
                        // Check if there's no "O" time log from next day before 5am
                        && !$this->hasNextDayEarlyMorningTimeOut($employee_id, $formattedDate)
                        && (!$leave || ($leave && ($leave->hours < $scheduleData['duty_hours'] || $leave->without_pay == 1))) && $schedule
                    ){


                        if(($timelogs->filter(fn($tl) => $tl->in_out == 'I')->isEmpty() || $timelogs->filter(fn($tl) => $tl->in_out == 'O')->isEmpty()) && ($leave && ($leave->half_day == 1 || $leave->half_day == 2))){

                            $dayOfWeek = date('l', strtotime($formattedDate));
                            $daysArray = explode(',', $schedule->schedule->day_off);

                            $daysWFHArray = explode(',', $schedule->schedule->wfh);
                            $daysCWSArray = explode(',', $schedule->schedule->cws_day);

                            if(in_array($dayOfWeek,$daysCWSArray)) {
                                $scheduledStartTime = new DateTime($formattedDate.' '.$schedule->schedule->cws_from_time);
                                $scheduledEndTime = new DateTime($formattedDate.' '.$schedule->schedule->cws_to_time);
                            } else {
                                $scheduledStartTime = new DateTime($formattedDate.' '.$schedule->schedule->from_time);
                                $scheduledEndTime = new DateTime($formattedDate.' '.$schedule->schedule->to_time);
                            }

                            $workHours = $scheduledStartTime->diff($scheduledEndTime)->h - 1;

                            $hours_absent = $workHours/2;
                            $days_absent = ($workHours/2) / 8;
                        }
                    
                        // }
                        $dayOfWeek = date('l', strtotime($formattedDate));
                        $daysArray = explode(',', $schedule->schedule->day_off); // Convert string to array
                        $daysWFHArray = explode(',', $schedule->schedule->wfh);
                        /**check WFH if has DAR */

                        $isWFH = in_array($dayOfWeek, $daysWFHArray);
                        $validWFH = $wfhRecord && $wfhRecord->isNotEmpty();

                        if($leave 
                            && ($leave->half_day == 1 || $leave->half_day == 2) 
                            && $leave->first_or_last_day_halfday_leave > 0 
                            && $leave->without_pay == 1)
                        {
                            if($leave->half_day == 1 && $formattedDate == $leave->date_to){
                                $hours_absent = $leave->first_or_last_day_halfday_leave;
                                $leaveHours = ($hours_absent) / 8;
                            } else if($leave->half_day == 2 && $formattedDate == $leave->date_from) {
                                $hours_absent = $leave->first_or_last_day_halfday_leave;
                                $leaveHours = ($hours_absent) / 8;
                            }
                            // $hoursDifference = $scheduleData['duty_hours'] / 2;
                            // dd($workHours);
                        } else {
                            $leaveHours = $leave ? $leave->hours / $leave->days : 0;
                        }

                        // $leaveHours = ($leave->hours / $leave->days);

                        if ((!in_array($dayOfWeek, $daysArray) && (!$isWFH || !$validWFH) && new DateTime($formattedDate) < new DateTime()) || ($undertime_minutes_for_absent > 239)) {
                            if($leave && $leave->without_pay == 1 && $leave->half_day != 1 && $leave->half_day != 2) { /**if leave without pay */
                                $days_absent = $leaveHours / 8;
                                $hours_absent = (float) $leaveHours;
                                
                                // if($formattedDate == '2025-01-03'){
                                //     dd($hours_absent);
                                // }
                            } else if($leave && $leave->without_pay == 1 && ($leave->half_day == 1 || $leave->half_day == 2)) { /**if leave without pay */

                                $days_absent = ($leaveHours) / 8;
                                $hours_absent = ($leaveHours);

                                if($days_absent > 1 && $leave->half_day == 0){
                                    //if multiple days of leave, check if current date is the first day of leave
                                    $hours_absent = $hoursDifference;
                                    $days_absent = ($hours_absent) / 8;
                                } else if($days_absent > 1 && $leave->half_day != 0){
                                    //if multiple days of leave, check if current date is the first day of leave
                                    $hours_absent = $hoursDifference;
                                    $days_absent = ($hours_absent) / 8;
                                } else {
                                    $hours_absent = $leave->hours;
                                    $days_absent = ($hours_absent) / 8;
                                }

                                if($leave->half_day == 1 && $formattedDate == $leave->date_to){
                                    $hours_absent = $leave->first_or_last_day_halfday_leave;
                                    $days_absent = ($hours_absent) / 8;
                                } else if($leave->half_day == 2 && $formattedDate == $leave->date_from) {
                                    $hours_absent = $leave->first_or_last_day_halfday_leave;
                                    $days_absent = ($hours_absent) / 8;
                                }

                                if($timelogs->filter(fn($tl) => $tl->in_out == 'I')->isNotEmpty() &&
                                        $timelogs->filter(fn($tl) => $tl->in_out == 'O')->isNotEmpty() &&
                                        (
                                            abs(
                                                Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'O')->first()->datetimelog)
                                                ->diffInMinutes(Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'I')->first()->datetimelog))
                                            ) <= 2
                                        )){
                                            $days_absent = $scheduleData['duty_hours'] / 8;
                                            $hours_absent = (float) $scheduleData['duty_hours'];
                                }
                            } else if ($leave && $leave->without_pay == 0 && ($leaveHours < $scheduleData['duty_hours']) && $leave->half_day != 1 && $leave->half_day != 2) { /**if leave with pay but the leave hours is less than the duty hours */
                                    $days_absent = ($scheduleData['duty_hours']-$leaveHours) / 8;
                                    $hours_absent = ($scheduleData['duty_hours']-$leaveHours);
                            } else if ($leaveHours < $scheduleData['duty_hours'] && $timelogs->filter(fn($tl) => $tl->in_out == 'I')->isEmpty() &&
                                $timelogs->filter(fn($tl) => $tl->in_out == 'O')->isEmpty() &&
                                (
                                    !$leave ||
                                    (
                                        $leave &&
                                        (
                                            $leave->without_pay == 1 ||
                                            $leave->hours < $scheduleData['duty_hours']
                                        )
                                    )
                                ) &&
                                (
                                    !$isHoliday ||
                                    $isAbsentBeforeHoliday
                                ) &&
                                $schedule && !$ob && !$offsetAvailment) { /**if leave with pay but the leave hours is less than the duty hours */
                                    $days_absent = ($scheduleData['duty_hours']-$leaveHours) / 8;
                                    $hours_absent = ($scheduleData['duty_hours']-$leaveHours);
                            }
                        } else if($leaveHours < $scheduleData['duty_hours'] && $timelogs->filter(fn($tl) => $tl->in_out == 'I')->isEmpty() &&
                            $timelogs->filter(fn($tl) => $tl->in_out == 'O')->isEmpty() &&
                            (
                                !$leave ||
                                (
                                    $leave &&
                                    (
                                        $leave->without_pay == 1 ||
                                        $leave->hours < $scheduleData['duty_hours']
                                    )
                                )
                            ) &&
                            (
                                !$isHoliday ||
                                $isAbsentBeforeHoliday
                            ) &&
                            $schedule && !$ob && !$offsetAvailment){
                                    $days_absent = ($scheduleData['duty_hours']-$leaveHours) / 8;
                                    $hours_absent = ($scheduleData['duty_hours']-$leaveHours);
                            }

                        if(
                            (
                                $timelogs->filter(fn($tl) => $tl->in_out == 'I')->isEmpty() ||
                                $timelogs->filter(fn($tl) => $tl->in_out == 'O')->isEmpty()) &&
                                (!$isHoliday || $isAbsentBeforeHoliday)
                                &&
                                $schedule && !$ob && !$offsetAvailment && (!$leave || ($leave && $leave->halfday != 0))
                        ){
                            $days_absent = ($scheduleData['duty_hours']) / 8;
                            $hours_absent = ($scheduleData['duty_hours']);
                        }
                    
                        // if($formattedDate == '2025-01-09'){
                        //     dd(abs(
                        //         Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'O')->first()->datetimelog)
                        //         ->diffInMinutes(Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'I')->first()->datetimelog))
                        //     ));
                        // }

                        if($undertime_minutes_for_absent > 239 &&
                            $timelogs->filter(fn($tl) => $tl->in_out == 'I')->isNotEmpty() &&
                            $timelogs->filter(fn($tl) => $tl->in_out == 'O')->isNotEmpty() &&
                            (
                                abs(
                                    Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'O')->first()->datetimelog)
                                    ->diffInMinutes(Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'I')->first()->datetimelog))
                                ) >= 2
                            )
                        ) {
                            $undertime_hours = $undertime_minutes_for_absent / 60;

                            $undertime_days = $undertime_hours / 8;

                            $hours_absent = $undertime_hours;
                            $days_absent = $undertime_days;
                        }

                        if($timelogs->filter(fn($tl) => $tl->in_out == 'I')->isNotEmpty() &&
                            $timelogs->filter(fn($tl) => $tl->in_out == 'O')->isNotEmpty() &&
                            (
                                abs(
                                    Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'O')->first()->datetimelog)
                                    ->diffInMinutes(Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'I')->first()->datetimelog))
                                ) <= 2
                            )
                        ) {
                            $days_absent = $scheduleData['duty_hours'] / 8;
                            $hours_absent = (float) $scheduleData['duty_hours'];
                        }

                        if($days_absent > 0) {
                            $absentData = [
                                'employee_id' => $employee_id,
                                'company_id' => $company_id,
                                'dealership_id' => $dealer_id,
                                'department_id' => $department_id,
                                'payroll_date' => $payroll_date,
                                'date' => $formattedDate,
                                'no_of_days' => $days_absent,
                                'no_of_hours' => $hours_absent,
                                'schedule_in' => $scheduleData['schedule_in'],
                                'schedule_out' => $scheduleData['schedule_out'],
                                'time_in' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='I')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                                'time_out' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                            ];
                            ProcessedAbsent::create($absentData);

                            $data['absent'][] = $absentData;
                        }

                        // Only record undertime if the employee is not fully absent (days_absent != 1 and days_absent != 1.25)
                        // and undertime is 4 hours or less
                        // if($formattedDate == '2025-01-11'){
                        //     dd($undertime_minutes_for_absent);
                        // }


                        if ((!$holiday || ($holiday && $payrollRate == 'Daily' && $holiday->holiday_type != 1)) && $undertime_minutes_for_absent > 0 && $undertime_minutes_for_absent <= 239 && $days_absent != 1 && $days_absent != 1.25 && $days_absent != 0.625) {
                            // if($formattedDate=='2024-12-31') dd(['undertime' =>$undertimeData]);
                            // if($formattedDate == '2025-01-15'){
                            //     dd($days_absent);
                            // }

                            // Check if record already exists
                            $existingRecord = ProcessedUndertime::where([
                                'employee_id' => $employee_id,
                                'company_id' => $company_id,
                                'dealership_id' => $dealer_id,
                                'department_id' => $department_id,
                                'payroll_date' => $payroll_date,
                                'date' => $formattedDate,
                            ])->first();

                            if (!$existingRecord) {
                                $undertimeData = [
                                    'employee_id' => $employee_id,
                                    'company_id' => $company_id,
                                    'dealership_id' => $dealer_id,
                                    'department_id' => $department_id,
                                    'payroll_date' => $payroll_date,
                                    'date' => $formattedDate,
                                    'schedule_in' => $scheduleData['schedule_in'] ?? null,
                                    'schedule_out' => $scheduleData['schedule_out'] ?? null,
                                    'time_in' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='I')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='I')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                                    'time_out' => $timelogs && $timelogs->filter(fn($tl) => $tl->in_out=='O')->isNotEmpty() ? $timelogs->filter(fn($tl) => $tl->in_out=='O')->map(fn($tl) => Carbon::parse($tl->datetimelog)->format('H:i:s'))->first() : null,
                                    'no_of_minutes' => $undertime_minutes_for_absent,
                                ];
                                ProcessedUndertime::create($undertimeData);
                                $data['undertime'][] = $undertimeData;
                            }
                        }
                    }
                }


                if(($timelogs->isNotEmpty() || $ob) && $schedule) {
                    // if($formattedDate =='2024-12-23'){
                    //     dd('check');
                    // }
                    if($tardiness){
                        if($scheduleData){
                            $dutyMinutes = $scheduleData['duty_hours'] * 60; // Convert duty hours to minutes
                            $workedMinutes = max($dutyMinutes - $tardiness, 0); // Deduct tardiness but ensure non-negative
                            $regularHoursWorked = $workedMinutes / 60; // Convert back to hours
                        }
                    } else {
                        $regularHoursWorked = $scheduleData['duty_hours']; // Convert back to hours
                    }

                    $dailyWorkHoursData = [
                        'employee_id' => $employee_id,
                        'company_id' => $company_id,
                        'dealership_id' => $dealer_id,
                        'department_id' => $department_id,
                        'payroll_date' => $payroll_date,
                        'date' => $formattedDate,
                        'work_hours' => $regularHoursWorked,
                        'holiday_restday_hours' => $holidayRestdayHours,
                        'ot_hours' => $hoursOT,
                        'leave_hours' => $leaveHours,
                    ];

                    $data['dailyWorkHours'][] = $dailyWorkHoursData;
                    ProcessedDailyWorkHours::create($dailyWorkHoursData);

                }

                // Check if present
                $isPresent =$this->isPresent($timelogs, $leave, $holiday, $ob, $validWFH, $schedule, $formattedDate, $isAbsentBeforeHoliday);
                if ($isPresent) {
                    $presentDays++;
                    $data['days_present'][] = $formattedDate;
                }

                //Workdays - CHANGED THIS TO WORKDAYS IN A WEEK (WITH SCHEDULE)
                // if($payrollRate == 'Daily') {
                //     if(($timelogs->isNotEmpty() || $ob || $validWFH) && $scheduleData && !$scheduleData['restday'] && !$holiday) $workDays += 1 - $days_absent;
                // } elseif($payrollRate =='Monthly') {
                //     if($isAlwaysPresent) {
                //         if(($timelogs->isNotEmpty() || $ob || $validWFH || $leave) || ($scheduleData && !$scheduleData['restday'])) $workDays++;
                //     } else {
                //         if($isPresent) $workDays++;
                //     }

                // }
                if($scheduleData && !$scheduleData['restday']) {
                    $schedStart = Carbon::parse($formattedDate.' '.$scheduleData['schedule_in']);
                    $schedEnd = Carbon::parse($formattedDate. ' '. $scheduleData['schedule_out']);
                    $schedHours = $schedStart->diffInHours($schedEnd)-1;
                    $days = $schedHours/8;
                    // if($formattedDate == '2025-01-11') dd($schedHours);
                    $workDays += $days;
                }
                //actualWorkDays
                if($payrollRate == 'Daily') {
                    // dd(abs(
                    //     Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'O')->first()->datetimelog)
                    //     ->diffInMinutes(Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'I')->first()->datetimelog))
                    // ) <= 2);
                    if(
                        (
                            (
                            $timelogs->filter(fn($tl) => $tl->in_out == 'I')->isNotEmpty() &&
                            $timelogs->filter(fn($tl) => $tl->in_out == 'O')->isNotEmpty() &&
                                (
                                    abs(
                                        Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'O')->first()->datetimelog)
                                        ->diffInMinutes(Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'I')->first()->datetimelog))
                                    ) >= 2
                                )
                            ) ||
                                $ob ||
                                $validWFH
                                // || ($leave && $leave->without_pay==0)
                            ) &&
                            $scheduleData &&
                            !$scheduleData['restday']
                            // ||
                            // (
                            //     $holiday && $holiday->holiday_type == 1 && $scheduleData && !$scheduleData['restday']
                            // )
                        ) $actualWorkDays += ($leave && $leave->without_pay == 0 && ($leave->half_day == 1 || $leave->half_day == 2) && 
                            (
                                (
                                $timelogs->filter(fn($tl) => $tl->in_out == 'I')->isNotEmpty() &&
                                $timelogs->filter(fn($tl) => $tl->in_out == 'O')->isNotEmpty() &&
                                    (
                                        abs(
                                            Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'O')->first()->datetimelog)
                                            ->diffInMinutes(Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'I')->first()->datetimelog))
                                        ) >= 2
                                    )
                                ) ||
                                    $ob ||
                                    $validWFH
                                    // || ($leave && $leave->without_pay==0)
                                ) &&
                                $scheduleData &&
                                !$scheduleData['restday'] ? $leave->days :  1) - $days_absent;
                } elseif($payrollRate =='Monthly') {
                    if(!$isAlwaysPresent) {
                        if(
                            (
                                (
                                    $timelogs->filter(fn($tl) => $tl->in_out == 'I')->isNotEmpty() &&
                                    $timelogs->filter(fn($tl) => $tl->in_out == 'O')->isNotEmpty() &&
                                    (
                                        abs(
                                            Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'O')->first()->datetimelog)
                                            ->diffInMinutes(Carbon::parse($timelogs->filter(fn($tl) => $tl->in_out == 'I')->first()->datetimelog))
                                        ) >= 2
                                    )
                                ) ||
                                $ob || $validWFH) &&
                                ($scheduleData && !$scheduleData['restday'])) {
                                    $days = 0;
                                    // if($scheduleData && !$scheduleData['restday']) {
                                    //     $schedStart = Carbon::parse($scheduleData['schedule_in']);
                                    //     $schedEnd = Carbon::parse($scheduleData['schedule_out']);
                                    //     $schedHours = $schedStart->diffInHours($schedEnd) - 1;
                                    //     $days = $schedHours/8;
                                    // }
                                    // $workDays
                                    $actualWorkDays++;
                                }
                    } else {
                        if($isPresent) $actualWorkDays++;
                    }
                }

                // echo $actualWorkDays.' - '. $formattedDate.'||||||';

                /**Update the requests as processed */
                EmployeeLeave::where('employee_id', $employee_id)->where('status', 2)->where('date_from','<=',$formattedDate)->where('date_to', '>=', $formattedDate)->update(['processed' => 1]);
                EmployeeOvertime::where('employee_id', $employee_id)->where('status', 2)->where('date_from','<=',$formattedDate)->where('date_to', '>=', $formattedDate)->update(['processed' => 1]);
                EmployeeOb::where('employee_id', $employee_id)->where('status', 2)->where('date_from','<=',$formattedDate)->where('date_to', '>=', $formattedDate)->update(['processed' => 1]);
                EmployeeOffset::where('employee_id', $employee_id)->where('status', 2)->where('date_from','<=',$formattedDate)->where('date_to', '>=', $formattedDate)->update(['processed' => 1]);
                EmployeeTimeAdjustment::where('employee_id', $employee_id)->where('status', 2)->where('date', $formattedDate)->update(['processed' => 1]);
                EmployeeChangeSchedule::where('employee_id', $employee_id)->where('status', 2)->where('validated', 1)->where('date', $formattedDate)->update(['processed' => 1]);
                // EmployeeOffset::where('employee_id', $employee_id)->where('status', 2)->where('date_from','<=',$formattedDate)->where('date_to', '>=', $formattedDate)->update(['processed' => 1]);
            }

            $data['workDays'] = $workDays;
            $data['actualWorkDays'] = $actualWorkDays;

            DB::commit();

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

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

    /**
     * Helper function to check if there's a time out record from the next day before 5am
     *
     * @param int $employee_id
     * @param string $date Current date being processed in Y-m-d format
     * @return bool Returns true if a next-day early morning time out exists
     */
    function hasNextDayEarlyMorningTimeOut($employee_id, $date) {
        $nextDay = date('Y-m-d', strtotime($date . ' +1 day'));

        // Get time range from 00:00:00 to 05:00:00 of the next day
        $startNextDay = $nextDay . ' 00:00:00';
        $endNextDay = $nextDay . ' 05:00:00';

        // Query for any 'O' time logs in the early morning of the next day
        $earlyMorningOut = TimeLog::where('employee_id', $employee_id)
            ->where('in_out', 'O')
            ->whereBetween('datetimelog', [$startNextDay, $endNextDay])
            ->exists();

        return $earlyMorningOut;
    }

    function isWFH(Request $request) {
        $formattedDate = $request->date ?? date('Y-m-d');
        $employee_id = $request->employee_id;
        $isWFH = 0;
        $schedule = $this->getSchedule($formattedDate, $employee_id);
        if($schedule) {
            $daysWFHArray = explode(',', $schedule->schedule->wfh);
            $dayOfWeek = date('l', strtotime($formattedDate));
            $isWFH = in_array($dayOfWeek, $daysWFHArray) ? 1 : 0;
        }

         // GET WFH
        $wfhRecord = EmployeeWfh::where([
            'employee_id'=> $employee_id,
            'date'=>$formattedDate,
            // 'status'=>2,
            ])->first();
        if($wfhRecord) {
            $isWFH = 1;
        }
        // $isWFH = 1;
        return response()->json($isWFH);
    }

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

        $start_date = new DateTime($request->start_date);
        $end_date = new DateTime($request->end_date);
        $end_date->modify('+1 day'); // Include the end date in the range

        // Create a DatePeriod object
        $period = new DatePeriod($start_date, new DateInterval('P1D'), $end_date);

        $data = [];

        $timelogs = Timelog::select('datetimelog', 'in_out')->where('time_keeping_id', $user->employees->time_keeping_id)->whereBetween('datetimelog', [$start_date, $end_date])->get();

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

    public function getDailyAttendance(Request $request)
    {
        $user = Auth::user();
        $employeeId = $request->employee_id ?? $user->employee_id;

        // Get last 30 days of attendance
        $endDate = now();
        $startDate = now()->subDays(30);

        // Check if we have cached data for the current month
        $yearMonth = $endDate->format('Y-m');
        $cachedData = CachedMonthlyAttendance::forEmployeeAndMonth($employeeId, $yearMonth)->first();

        if ($cachedData && $cachedData->isValid()) {
            // Filter cached data for last 30 days
            $allData = $cachedData->attendance_data;
            $filteredData = $this->filterDataByDateRange($allData, $startDate, $endDate);

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

        // If no cache, compute on the fly (but don't cache this small request)
        $result = $this->computeAttendanceData($user, $startDate, $endDate);

        // Transform to daily attendance format
        $dailyAttendance = $this->transformToDailyAttendance($result['data']);

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

    /**
     * Filter attendance data by date range
     */
    private function filterDataByDateRange($data, $startDate, $endDate)
    {
        $filtered = [];

        foreach ($data as $category => $items) {
            if (!is_array($items)) continue;

            $filtered[$category] = array_filter($items, function($item) use ($startDate, $endDate) {
                if (!isset($item['date'])) return false;

                $itemDate = new DateTime($item['date']);
                return $itemDate >= $startDate && $itemDate <= $endDate;
            });
        }

        return $this->transformToDailyAttendance($filtered);
    }

    /**
     * Transform attendance data to daily attendance format
     */
    private function transformToDailyAttendance($data)
    {
        $dailyAttendance = [];
        $dateMap = [];

        // Process each category
        $categories = ['timelog', 'absent', 'tardiness', 'leave', 'holiday'];

        foreach ($categories as $category) {
            if (!isset($data[$category])) continue;

            foreach ($data[$category] as $item) {
                $date = $item['date'] ?? null;
                if (!$date) continue;

                if (!isset($dateMap[$date])) {
                    $dateMap[$date] = [
                        'date' => date('M d, Y', strtotime($date)),
                        'name' => $item['title'] ?? $category,
                        'title' => $this->determineStatus($item, $category),
                    ];
                }
            }
        }

        // Convert to array and sort by date descending
        $dailyAttendance = array_values($dateMap);
        usort($dailyAttendance, function($a, $b) {
            return strtotime($b['date']) - strtotime($a['date']);
        });

        return array_slice($dailyAttendance, 0, 30); // Return last 30 days
    }

    /**
     * Determine status from item and category
     */
    private function determineStatus($item, $category)
    {
        if (isset($item['title'])) {
            // Check for specific statuses
            if (stripos($item['title'], 'absent') !== false) return 'Absent';
            if (stripos($item['title'], 'late') !== false || stripos($item['title'], 'tardy') !== false) return 'Late';
            if (stripos($item['title'], 'leave') !== false) return 'On Leave';
            if (stripos($item['title'], 'holiday') !== false) return 'Holiday';
        }

        // Default based on category
        switch ($category) {
            case 'absent': return 'Absent';
            case 'tardiness': return 'Late';
            case 'leave': return 'On Leave';
            case 'holiday': return 'Holiday';
            case 'timelog': return 'Present';
            default: return 'Present';
        }
    }
}
