<?php

namespace App\Jobs;

use App\Models\LeaveDays;
use App\Models\Notes;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\Admin\app\Models\Category;

class UpdateTemporaryLeaveDays implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    protected $month;
    protected $year;

    public function __construct($month = null, $year = null)
    {
        $this->month = $month ?? Carbon::now()->month;
        $this->year = $year ?? Carbon::now()->year;
    }

    /**
     * Execute the job.
     */
    public function handle()
    {
        $users = User::get();

        foreach ($users as $user) {
            $leaveDay = LeaveDays::where('ld_user_id', $user->id)
                ->where('ld_year', $this->year)
                ->first();

            $notes = Notes::where('n_reason', 'TEMPORARY_ONLEAVE')
                ->where('n_user_id', $user->id)
                ->where('n_year', $this->year)
                ->where('n_month', $this->month)
                ->whereExists(function ($query) use ($user) {
                    $query->select(DB::raw(1))
                        ->from('tickets')
                        ->where('tickets.user_id', $user->id)
                        ->where('tickets.status', 'CONFIRMED')
                        ->where('tickets.type', 'ONLEAVE');
                })
                ->get();

            $maxDaysPerMonth = $this->getMaxLeaveDaysPerMonth();

            // Tổng ngày nghỉ sẽ dùng trong tháng
            $willUsedDaysInMonth = 0;
            foreach ($notes as $note) {
                $willUsedDaysInMonth += $note->n_time_type == 'ALL' ? 1.0 : 0.5;
            }

            // Tổng phép đang có
            $onleaveDaysTotal = $leaveDay->ld_day_total +  $leaveDay->ld_additional_day + $leaveDay->ld_special_leave_day;
            // Phép đã sử dụng tới tháng hiện tại
            $usedOnleaveDaysTotal = Notes::join('categories', function ($join) {
                $join->on('notes.n_time_type', '=', 'categories.c_code')
                    ->where('categories.c_type', 'TIME_TYPE');
            })
                ->where('n_user_id', $user->id)
                ->where('n_year', $this->year)
                ->where('n_month',  "<=", $this->month)
                ->where('n_reason', 'ONLEAVE')
                ->sum('categories.c_value');
            // Phép còn lại
            $remainingOnleaveDays = $onleaveDaysTotal - $usedOnleaveDaysTotal;

            // Log::debug("User {$user->name}\n");
            // Log::debug(
            //     "📊 Thống kê ngày phép:\n" .
            //         " - Tháng: {$this->month}\n" .
            //         " - Tổng ngày nghỉ sẽ dùng trong tháng: $willUsedDaysInMonth\n" .
            //         " - Tổng ngày phép: $onleaveDaysTotal\n" .
            //         " - Tổng ngày phép đã nghỉ: $usedOnleaveDaysTotal\n" .
            //         " - Tổng ngày phép còn lại: $remainingOnleaveDays\n"
            // );

            $onleave_days_will_use = 0; // Ngày phép sẽ dùng
            $nopay_days_will_use = 0;   // Ngày ko phép sẽ dùng

            // Ngày phép còn lại <= 0 (Hết phép)
            if ($remainingOnleaveDays <= 0) {
                $onleave_days_will_use = 0;
                $nopay_days_will_use = $willUsedDaysInMonth;

                Log::debug("--- Hết phép trong tháng ---");
            }

            // Ngày phép còn lại < ngày yêu cầu (Không đủ phép)
            else if ($remainingOnleaveDays < $willUsedDaysInMonth) {
                // Vượt limit
                if ($willUsedDaysInMonth > $maxDaysPerMonth) {
                    // Phép còn lại > limit
                    if ($remainingOnleaveDays > $maxDaysPerMonth) {
                        $onleave_days_will_use = $maxDaysPerMonth;
                        $nopay_days_will_use = $willUsedDaysInMonth - $maxDaysPerMonth;
                    }
                    // Phép còn lại < limit
                    else {
                        $onleave_days_will_use = $remainingOnleaveDays;
                        $nopay_days_will_use = $willUsedDaysInMonth - $remainingOnleaveDays;
                    }

                    Log::debug("--- Không đủ phép trong tháng, vượt quá limit ---",);
                }
                // Không vượt limit
                else {
                    $onleave_days_will_use = $remainingOnleaveDays;
                    $nopay_days_will_use = $willUsedDaysInMonth - $remainingOnleaveDays;

                    Log::debug("--- Không đủ phép trong tháng, ko vượt limit ---");
                }
            }

            // Ngày phép còn lại >= ngày yêu cầu (Đủ phép)
            else {
                // Vượt limit
                if ($willUsedDaysInMonth > $maxDaysPerMonth) {
                    $onleave_days_will_use = $maxDaysPerMonth;
                    $nopay_days_will_use = $willUsedDaysInMonth - $maxDaysPerMonth;

                    Log::debug("--- Đủ phép, vượt limit ---");
                }
                // Không vượt limit
                else {
                    $onleave_days_will_use = $willUsedDaysInMonth;
                    $nopay_days_will_use = 0;

                    Log::debug("--- Đủ phép ---");
                }
            }

            Log::debug("", [
                "Phep" => $onleave_days_will_use,
                "Khong Phep" => $nopay_days_will_use
            ]);

            // Có nghỉ không phép 
            if ($nopay_days_will_use > 0) {
                foreach ($notes as $note) {
                    $value = ($note->n_time_type === 'ALL') ? 1.0 : 0.5;

                    if ($note->n_time_type === 'ALL' && $onleave_days_will_use == 0.5) {
                        // Chỉ còn 0.5 phép, chia thành 2 bản ghi: 1 phép, 1 không phép
                        // Ưu tiên phép cho buổi sáng (S), không phép cho buổi chiều (C)

                        Notes::create([
                            'n_user_id' => $user->id,
                            'n_day' => $note->n_day,
                            'n_month' => $note->n_month,
                            'n_year' => $note->n_year,
                            'n_time_type' => 'S',
                            'n_reason' => 'ONLEAVE',
                            'n_note' => $note->n_note,
                            'ticket_id' => $note->ticket_id
                        ]);
                        Notes::create([
                            'n_user_id' => $user->id,
                            'n_day' => $note->n_day,
                            'n_month' => $note->n_month,
                            'n_year' => $note->n_year,
                            'n_time_type' => 'C',
                            'n_reason' => 'LEAVE_WITHOUT_PAY',
                            'n_note' => $note->n_note,
                            'ticket_id' => $note->ticket_id
                        ]);

                        $note->delete();

                        $onleave_days_will_use = 0;
                        $nopay_days_will_use -= 0.5;
                    } elseif ($onleave_days_will_use > 0) {
                        // Dùng ngày phép trước
                        $use = min($onleave_days_will_use, $value);
                        $note->update([
                            'n_reason' => "ONLEAVE"
                        ]);
                        $onleave_days_will_use -= $use;
                    } elseif ($nopay_days_will_use > 0) {
                        // Hết phép, chuyển sang không phép
                        $use = min($nopay_days_will_use,  $value);
                        $note->update([
                            'n_reason' => "LEAVE_WITHOUT_PAY"
                        ]);
                        $nopay_days_will_use -= $use;
                    }
                }
            }
            // Đủ phép
            else {
                foreach ($notes as $note) {
                    $note->update([
                        'n_reason' => "ONLEAVE"
                    ]);
                }
            }
        }
    }

    private function getMaxLeaveDaysPerMonth(): int
    {
        $limitLeaveMonth = Category::where('c_type', 'LIMIT_LEAVE_MONTH')->where('c_code', "LIMIT")->first();
        if ($limitLeaveMonth) {
            $maxDaysPerMonth = (int)$limitLeaveMonth->c_value;
        } else {
            $maxDaysPerMonth = 3; // default nếu k có setting
        }
        return $maxDaysPerMonth;
    }
}
