<?php

namespace App\Http\Controllers\API\v1;

use App\Http\Controllers\Controller;
use App\Models\Employee;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Validator;
use App\Models\EmployeeSchedule;
use App\Models\ScheduleShift;
use DateInterval;
use DatePeriod;
use DateTime;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use PHPUnit\Event\Code\Throwable;

class EmployeeScheduleController extends Controller
{
    public function index(Request $request)
    {
        $user = Auth::user();

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

        DB::enableQueryLog();
        $data = EmployeeSchedule::with(['employee', 'schedule', 'employee.dealership'])->where(function ($query) use ($keyword) {
                    $keyword = str_replace(" ", "%", $keyword);
                    $query->where('employee_id','like',"{$keyword}%")
                    ->orWhereHas('schedule', fn($q) => $q->where('name','like',"%{$keyword}%"))
                    ->orWhereHas('employee', fn($q) =>
                        $q->where('lastname', 'like',"%{$keyword}%")
                        ->orWhere('middlename', 'like',"%{$keyword}%")
                        ->orWhere('firstname', 'like',"%{$keyword}%"));
                });

        if($user->roles[0]->group_id != 1 && $user->roles[0]->group_id != 2)
        {
            $data->whereHas('employee', fn($q) => $q->where('dealer_id', $dealership_id));
        }

        $data = $data->paginate($perPage);

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

    public function show(Request $request, string $id)
    {
        $user = Auth::user();
        
        $data = EmployeeSchedule::where('employee_id', $user->employee_id)->exists();                                
            
        return response()->json($data);
    }

    public function store(Request $request)
    {
        $request['effectivity_date'] = $request->date_from;

        // Validate the incoming request data
        $validator = Validator::make($request->all(), [
            'employee_id' => ['required'],
            'schedule_id' => ['required'],
            'date_from' => ['required'],
            'effectivity_date' => ['required'],
        ]);

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

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

        try {
            foreach ($request->employee_id as $employee) {
                $company = Employee::select('company_id')->where('employee_id', '=', $employee)->first();

                // If sat_off_effectivity_date exists, do weekly alternating logic
                if ($request->sat_off_effectivity_date) {
                    $dateFrom = new \DateTime($request->date_from);
                    $dateTo = new \DateTime($request->date_to);
                    $satOffDate = new \DateTime($request->sat_off_effectivity_date);
                    
                    // Get schedule_sub for Saturday off
                    $schedule_sub = ScheduleShift::where('schedule_header', $request->schedule_id)->first();

                    // Loop through weeks
                    $currentWeekStart = clone $dateFrom;
                    $isSaturdayOff = false;
                    
                    while ($currentWeekStart <= $dateTo) {
                        // Calculate week end (6 days from start, or dateTo if earlier)
                        $currentWeekEnd = clone $currentWeekStart;
                        $currentWeekEnd->modify('+6 days');
                        
                        if ($currentWeekEnd > $dateTo) {
                            $currentWeekEnd = clone $dateTo;
                        }

                        // Find Saturday in current week
                        $saturday = null;
                        for ($day = clone $currentWeekStart; $day <= $currentWeekEnd; $day->modify('+1 day')) {
                            if ($day->format('w') == 6) { // 6 = Saturday
                                $saturday = clone $day;
                                break;
                            }
                        }

                        // Determine which schedule to use
                        $scheduleToUse = $request->schedule_id;
                        
                        if ($saturday && $saturday >= $satOffDate) {
                            // Check if this is the first Saturday off
                            if ($saturday->format('Y-m-d') == $satOffDate->format('Y-m-d')) {
                                $isSaturdayOff = true;
                            }
                            
                            if ($isSaturdayOff) {
                                $scheduleToUse = $schedule_sub->id;
                            }
                        }

                        // Create employee schedule record for this week
                        EmployeeSchedule::create([
                            'employee_id' => $employee,
                            'company_id' => $company->company_id,
                            'schedule_id' => $scheduleToUse,
                            'date_from' => $currentWeekStart->format('Y-m-d'),
                            'date_to' => $currentWeekEnd->format('Y-m-d'),
                            'effectivity_date' => $request->effectivity_date,
                        ]);

                        // Toggle Saturday off pattern after each Saturday
                        if ($saturday && $saturday >= $satOffDate) {
                            $isSaturdayOff = !$isSaturdayOff;
                        }

                        // Move to next week
                        $currentWeekStart->modify('+7 days');
                    }
                } else {
                    // Basic creation - no Saturday off logic
                    EmployeeSchedule::create([
                        'employee_id' => $employee,
                        'company_id' => $company->company_id,
                        'schedule_id' => $request->schedule_id,
                        'date_from' => $request->date_from,
                        'date_to' => $request->date_to,
                        'effectivity_date' => $request->effectivity_date,
                    ]);
                }
            }

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

            return response()->json([
                'message' => 'Record Successfully added!',
                'status' => 'success',
            ], 201);
            
        } catch (\Exception $e) {
            DB::connection()->rollback();
            return response()->json([
                'status'  => false,
                'message' => 'Unable to process request. Please try again.',
                'data'    => $e->getMessage()
            ]);
        }
    }

    public function update(Request $request, int $id)
    {
        $data = EmployeeSchedule::where('id', $id)->first();

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

        $validator = Validator::make($request->all(),
            [
                'employee_id' => [
                    'required',
                ],
                'schedule_id' => [
                    'required',
                ],
                'date_from' => [
                    'required',
                ],
                'effectivity_date' => [
                    'required',
                ],
            ]
        );

        /** If validation fails return with error message */
        if ($validator->fails()) {
            $errors = $validator->errors();
            $first = $errors->getMessages();
            return response()->json([
                'status'  => false,
                'message' => (reset($first))[0],
                'errors'  => $errors
            ], Response::HTTP_UNPROCESSABLE_ENTITY);
        }

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

        try {

            $data->fill($request->all());
            $data->effectivity_date = $request->date_from;

            // dd($data);
            $data->save();

            $data->touch();

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

            // Invalidate cache for 'companies_' key when a company is updated
            Cache::forget('companies_'); // Adjust cache key if necessary

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

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

    public function destroy(int $id)
    {
        $data = EmployeeSchedule::find($id);
        if(!$data)
        {
            return response()->json(['message' => "Record not found!"],204);
        }
        DB::connection()->beginTransaction();
        $data->delete();
        DB::connection()->commit();
        return response()->json(['message' => "Record successfully deleted!"],201);
    }

    public function getEmployeeWorkingHoursForChangeSchedule(Request $request)
    {
        // dd($request->all());

        $user = Auth::user();

        $scheduleController = new EmployeeAttendanceController();

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

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

        $hoursTotal = 0;

        $length = iterator_count($period);
        $index = 0;

        $hoursArray = []; // Array to store $hoursMinusOne values

        foreach ($period as $date) {
            $formattedDate = $date->format('Y-m-d');

            $schedule = $scheduleController->getSchedule($formattedDate, $user->employee_id);
            $holiday = $scheduleController->getHoliday($formattedDate, $user->employee, $schedule);

            $dayOfWeek = date('l', strtotime($formattedDate));
            if ($schedule) {
                $daysArray = explode(',', $schedule->schedule->day_off); // Convert string to array
            } else {
                $daysArray = []; // Or any default value
            }

            if (!$holiday && !in_array($dayOfWeek, $daysArray)) {
                $daysCWSArray = explode(',', $schedule->schedule->cws_day);
                $daysShiftingArray = explode(',', $schedule->schedule->shifting_day);

                if (in_array($dayOfWeek, $daysCWSArray)) {
                    $fromTime = new DateTime($schedule->schedule['cws_from_time']);
                    $toTime = new DateTime($schedule->schedule['cws_to_time']);
                } else if (in_array($dayOfWeek, $daysShiftingArray)) {
                    $fromTime = new DateTime($schedule->schedule['shifting_from_time']);
                    $toTime = new DateTime($schedule->schedule['shifting_to_time']);
                } else {
                    $fromTime = new DateTime($schedule->schedule['from_time']);
                    $toTime = new DateTime($schedule->schedule['to_time']);
                }

                $interval = $fromTime->diff($toTime);

                $hours = $interval->h + ($interval->days * 24); // Calculate total hours
                $hoursMinusOne = $hours - 1;

                if ($request->half_day == 1) {
                    if ($index == 0) {
                        $hoursMinusOne = $hoursMinusOne / 2;
                    }
                } else if ($request->half_day == 2) {
                    if ($index == $length - 1) {
                        $hoursMinusOne = $hoursMinusOne / 2;
                    }
                }

                $schedule->schedule->flexible ? $hoursMinusOne = 8 : '';

                $hoursArray[] = $hoursMinusOne; // Store the value of $hoursMinusOne

                $hoursTotal += $hoursMinusOne;
            }

            $index++;
        }

        // Check if all $hoursMinusOne values are the same
        $allSame = count(array_unique($hoursArray)) === 1;

        if ($allSame) {
            return response()->json([
                'message' => 'All value are same',
                'status' => 'success',
                'hoursTotal' => $hoursTotal,
            ],201);
        } else {
            return response()->json([
                'status'  => false,
                'message' => 'All value are not the same',
                'hoursTotal' => ''
            ]);
        }
    }
}
