<?php

namespace App\Http\Controllers\API\v1;

use App\Http\Controllers\Controller;
use App\Models\AccumulatedLeaveCredits;
use App\Models\Employee;
use App\Models\EmployeeLeaveCredits;
use App\Models\EmployeeSchedule;
use App\Models\EmployeeTimeAdjustment;
use App\Models\LeaveAccumulationSetting;
use App\Models\LeaveLedger;
use App\Models\LeaveType;
use DateInterval;
use DatePeriod;
use DateTime;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Throwable;

class AccumulatedLeaveCreditsController extends Controller
{
    public function index()
    {
        if(date('d') == 7){
            // Create a DateTime object for the current date
            $currentDate = new DateTime();

            $start_date = new DateTime('first day of last month');
            $end_date = new DateTime('last day of last month');
            // $end_date->modify('+1 day');

            $period = new DatePeriod($start_date, new DateInterval('P1D'), $end_date);

            $accumulation_settings = LeaveAccumulationSetting::where('enabled', 1)->get();

            $employees = Employee::where('enabled', 1)->where('company_id', 36)->whereNull('date_resign')->get();

            $data = [];
            $accumulated_leave_credits = [];

            $year = '';
            $month = '';

            $employeeAttendance = new EmployeeAttendanceController();

            foreach ($employees as $employeeData) {
                // Initialize an array to store timelogs for this specific employee
                $daysRendered = 0;
            
                foreach ($period as $date) {
                    $year = $date->format('Y');
                    $month = $date->format('m');

                    $formattedDate = $date->format('Y-m-d'); // Format the date in 'Y-m-d'
            
                    // Get the timelog(s) for the employee on the current date
                    $timelogs = $employeeAttendance->getTimelog($formattedDate, $employeeData['time_keeping_id']);
                    
                    // Ensure timelogs is an array or iterable
                    if ($timelogs) {

                        $inLog = false;
            
                        $processedDates = []; // Array to track processed log dates

                        foreach ($timelogs as $logs) {
                            if (isset($logs->datetimelog) && isset($logs->in_out)) {
                                $logDate = date('Y-m-d', strtotime($logs->datetimelog));
                                
                                // Check if this logDate has already been processed
                                if (in_array($logDate, $processedDates)) {
                                    continue; // Skip to the next iteration if the date is already processed
                                }

                                $inLog = false; 

                                if ($logDate === $formattedDate && $logs->in_out === 'I') {
                                    $inLog = true;
                                } else {
                                    if (EmployeeTimeAdjustment::where('employee_id', $employeeData['employee_id'])
                                        ->where('status', 2)
                                        ->where('validated', 1)
                                        ->where('enabled', 1)
                                        ->where('date', $logDate)
                                        ->exists()) {
                                        $inLog = true;
                                    }
                                }

                                if ($inLog) {
                                    $employeeSchedule = $this->getSchedule($formattedDate, $employeeData['employee_id']);

                                    if ($employeeSchedule) {  
                                        if ($employeeSchedule->schedule['cws_day']) {
                                            if ($employeeSchedule->schedule['cws_day'] != date('l', strtotime($formattedDate))) {
                                                $daysRendered += 1.25;
                                            } else {
                                                $daysRendered++;
                                            }
                                        } else {
                                            $daysRendered++;
                                        }
                                    }

                                    $processedDates[] = $logDate;
                                }
                            }
                        }
                    }
                }

                $currentDate = date('Y-m-d');
                $dateHired = $employeeData['date_hired'];

                $newDateHired = new DateTime($dateHired);
                $newCurrentDate = new DateTime($currentDate);

                $interval = $newDateHired->diff($newCurrentDate);

                $yearsInService = $interval->y.'.'.$interval->d;

                $leaveAccumulation = [];

                $leaveAccumulationSettings = LeaveAccumulationSetting::where('years_from', '<=', $yearsInService)
                        ->where('years_to', '>=', $yearsInService)
                        ->where('classification_id', $employeeData['classification_id'])
                        ->get();

                foreach($leaveAccumulationSettings as $leaveAccumulationSetting){
                    
                    $leaveCredits = 0;

                    if($daysRendered != 0){
                        $leaveCreditDays = round($leaveAccumulationSetting->credits_days / 12, 3);
                        
                        if($daysRendered >= 16){ // earn the whole credits for the month
                            $leaveCredits = $leaveCreditDays;
                        } else if ($daysRendered <= 5){ // no credits must be earn
                            $leaveCredits = 0;
                        } else { // half of the credits will be earn
                            $leaveCredits = $leaveCreditDays / 2;
                        }
                    }

                    $updateOrInsertLeaveCredits = [
                        'employee_id' => $employeeData['employee_id'],
                        'company_id' => $employeeData['company_id'],
                        'dealer_id' => $employeeData['dealer_id'],
                        'leave_type_id' => $leaveAccumulationSetting->leave_type,
                        'remaining' => $leaveCredits,
                        'hours' => round($leaveCredits * 8, 3),
                        'days_rendered' => $daysRendered,
                    ]; 

                    if (EmployeeLeaveCredits::where('employee_id', $employeeData['employee_id'])
                            ->where('leave_type_id', $leaveAccumulationSetting->leave_type)
                            ->exists()) 
                    {

                        // Fetch the existing leave credits record
                        $leaveCreditsToUpdate = EmployeeLeaveCredits::where('employee_id', $employeeData['employee_id'])
                            ->where('leave_type_id', $leaveAccumulationSetting->leave_type)
                            ->first();

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

                            // Increment the leave credits and hours
                            $leaveCreditsToUpdate->remaining += $leaveCredits;
                            $leaveCreditsToUpdate->hours += round($leaveCredits * 8, 3);

                            // Save the updated record
                            $leaveCreditsToUpdate->save();
                            
                            DB::connection()->commit(); // Commit the transaction

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

                    } else {
                        EmployeeLeaveCredits::create($updateOrInsertLeaveCredits);
                    }

                    $accumulated_leave_credits[] = [
                        'employee_id' => $employeeData['employee_id'],
                        'company_id' => $employeeData['company_id'],
                        'dealer_id' => $employeeData['dealer_id'],
                        'year' => $year,
                        'month' => $month,
                        'leave_id' => $leaveAccumulationSetting->leave_type,
                        'accumulated_days' => $leaveCredits,
                        'accumulated_hours' => round($leaveCredits * 8, 3),
                        'days_rendered' => $daysRendered,
                        'max_credit' => $leaveAccumulationSetting->credits_days,
                        'created_at' => date('Y-m-d H:i:s'),                
                    ];
                }
            }

            DB::beginTransaction();

            try {
                // Use insert() to insert multiple records at once
                AccumulatedLeaveCredits::insert($accumulated_leave_credits);

                foreach($accumulated_leave_credits as $accumulated_leave_credit){

                    $leaveCredits = EmployeeLeaveCredits::where('leave_type_id', $accumulated_leave_credit['leave_id'])->where('employee_id', $accumulated_leave_credit['employee_id'])->exists();
                    
                    $credits_from = 0;
                    $credits_to = 0;

                    if($leaveCredits)
                    {
                        $leaveCredits = EmployeeLeaveCredits::where('leave_type_id', $accumulated_leave_credit['leave_id'])->where('employee_id', $accumulated_leave_credit['employee_id'])->first();
                        $credits_from = $leaveCredits->remaining;
                        // echo 'asdsadsaadasdasdd';
                    }

                    $credits_to = $accumulated_leave_credit['accumulated_days'];

                    $leaveName = LeaveType::where('id', $accumulated_leave_credit['leave_id'])->pluck('name')->first();

                    $ledger = [
                        'employee_id' => $accumulated_leave_credit['employee_id'],
                        'company_id' => $accumulated_leave_credit['company_id'],
                        'dealer_id' => $accumulated_leave_credit['dealer_id'],
                        'leave_id' => '0',
                        'date_from' => date('Y-m-d'),
                        'date_to' => date('Y-m-d'),
                        'credits_from' => $credits_from == 0 ? 0 : abs($credits_from - $credits_to),
                        'credits_to' => abs($credits_from),
                        'credit' => 0,
                        'hours' => 0,
                        'leave_type' => $accumulated_leave_credit['leave_id'],
                        'leave_name' => $leaveName . ' - Earned',
                        'date_applied' => date('Y-m-d'),
                    ];

                    LeaveLedger::create($ledger);
                }
                
                DB::commit();

                return response()->json([
                    'status' => true,
                    'message' => 'Saved successfully!',
                    'data' => $accumulated_leave_credits
                ], 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 getSchedule($date, $employee_id)
    {

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

        return $employeeSchedule;
    }

    public function store(Request $request)
    {
        $data = AccumulatedLeaveCredits::create($request->all());
    }
}
