<?php

namespace App\Modules\HR\Attendance\Services;

use App\Modules\HR\Attendance\Support\AttendanceRecordStatus;
use App\Modules\HR\Employees\Models\Employee;
use App\Modules\HR\Shifts\Services\ShiftResolutionService;
use App\Modules\HR\Shifts\Support\ShiftOvertimePreview;
use Carbon\CarbonImmutable;

class AttendancePunchMetricsService
{
    public function __construct(
        private readonly ShiftResolutionService $shifts,
        private readonly AttendanceLateStatusResolver $lateStatus,
    ) {}

    public function statusAtCheckIn(Employee $employee, string $date, CarbonImmutable $checkIn): string
    {
        [$threshold] = $this->thresholdAndHalfDay($employee, $date, $checkIn);

        return $checkIn->gt($threshold)
            ? AttendanceRecordStatus::LATE
            : AttendanceRecordStatus::PRESENT;
    }

    /**
     * @return array{status: string, overtime_minutes: int}
     */
    public function atCheckOut(
        Employee $employee,
        string $date,
        CarbonImmutable $checkIn,
        CarbonImmutable $checkOut,
    ): array {
        [$threshold, $halfDay] = $this->thresholdAndHalfDay($employee, $date, $checkIn);
        $context = $this->shifts->resolveContextForAttendanceDate($employee, $date, $checkIn);
        $overtime = $context === null
            ? 0
            : ShiftOvertimePreview::minutesPastOvertimeThreshold($context->shift, $date, $checkOut);

        return [
            'status' => $this->lateStatus->resolve($checkIn, $checkOut, $threshold, $halfDay),
            'overtime_minutes' => $overtime,
        ];
    }

    /**
     * @return array{CarbonImmutable, float}
     */
    private function thresholdAndHalfDay(
        Employee $employee,
        string $date,
        CarbonImmutable $checkIn,
    ): array {
        $context = $this->shifts->resolveContextForAttendanceDate($employee, $date, $checkIn);
        if ($context !== null) {
            return [$context->latenessThreshold, $context->halfDayMaxHours];
        }

        $expected = (string) config('attendance.expected_start', '09:00');
        $grace = (int) config('attendance.late_grace_minutes', 0);

        return [
            CarbonImmutable::parse($date.' '.$expected, $checkIn->getTimezone())->addMinutes($grace),
            (float) config('attendance.half_day_max_hours', 4.5),
        ];
    }
}
