<?php

namespace App\Modules\HR\Attendance\Services;

use App\Modules\HR\Employees\Models\Employee;
use App\Modules\HR\Attendance\Repositories\HolidayRepository;
use App\Modules\HR\Shifts\Repositories\EmployeeShiftAssignmentRepository;
use App\Modules\HR\Shifts\Support\ShiftWeekday;
use Carbon\CarbonImmutable;

/**
 * Resolves whether a calendar day is a working day for attendance reporting.
 */
class AttendanceWorkingDayResolver
{
    public function __construct(
        private readonly EmployeeShiftAssignmentRepository $assignments,
        private readonly HolidayRepository $holidays,
    ) {}

    public function isWorkingDay(Employee $employee, CarbonImmutable $day): bool
    {
        if ($this->isHoliday($employee, $day)) {
            return false;
        }
        $key = strtolower($this->weekdayKey($day));
        $assignment = $this->assignments->coveringDate(
            (int) $employee->tenant_id,
            (int) $employee->id,
            $day->startOfDay(),
        );
        $shift = $assignment?->shift;
        if ($shift !== null) {
            $list = array_map('strtolower', $shift->working_days ?? []);

            return in_array($key, $list, true);
        }

        $weekend = array_map('strtolower', config('attendance.default_weekend_days', ['friday', 'saturday']));

        return ! in_array($key, $weekend, true);
    }

    public function isHoliday(Employee $employee, CarbonImmutable $day): bool
    {
        return $this->holidays->isHoliday((int) $employee->tenant_id, $day);
    }

    private function weekdayKey(CarbonImmutable $day): string
    {
        return match ((int) $day->dayOfWeekIso) {
            1 => ShiftWeekday::MONDAY,
            2 => ShiftWeekday::TUESDAY,
            3 => ShiftWeekday::WEDNESDAY,
            4 => ShiftWeekday::THURSDAY,
            5 => ShiftWeekday::FRIDAY,
            6 => ShiftWeekday::SATURDAY,
            7 => ShiftWeekday::SUNDAY,
            default => ShiftWeekday::MONDAY,
        };
    }
}
