<?php

namespace App\Modules\HR\Overtime\Services;

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

class OvertimeRateResolver
{
    public function __construct(
        private readonly HolidayRepository $holidays,
        private readonly EmployeeShiftAssignmentRepository $assignments,
        private readonly OvertimeRatePolicyRepository $policies,
    ) {}

    /** @return array{category: string, multiplier: float} */
    public function resolve(Employee $employee, string $date): array
    {
        $day = CarbonImmutable::parse($date);
        $category = $this->category($employee, $day);
        $policy = $this->policies->defaultForTenant((int) $employee->tenant_id);
        $fallbacks = config('overtime.multipliers', [
            'normal' => 1, 'weekend' => 1.5, 'holiday' => 2, 'night' => 1.5,
        ]);
        $column = $category.'_multiplier';

        return [
            'category' => $category,
            'multiplier' => (float) ($policy?->{$column} ?? $fallbacks[$category] ?? 1),
        ];
    }

    private function category(Employee $employee, CarbonImmutable $day): string
    {
        if ($this->holidays->isHoliday((int) $employee->tenant_id, $day)) {
            return 'holiday';
        }
        $weekends = array_map('strtolower', config('attendance.default_weekend_days', ['friday', 'saturday']));
        if (in_array(strtolower($day->englishDayOfWeek), $weekends, true)) {
            return 'weekend';
        }
        $assignment = $this->assignments->coveringDate(
            (int) $employee->tenant_id,
            (int) $employee->id,
            $day,
        );

        return $assignment?->shift?->is_night_shift ? 'night' : 'normal';
    }
}
