<?php

namespace App\Modules\HR\Attendance\Services\ExceptionDetection;

use App\Modules\HR\Attendance\Contracts\AttendanceExceptionDetectionRule;
use App\Modules\HR\Attendance\Models\AttendanceRecord;
use App\Modules\HR\Attendance\Repositories\AttendanceExceptionRepository;
use App\Modules\HR\Attendance\Support\AttendanceExceptionDedupeKey;
use App\Modules\HR\Attendance\Support\AttendanceExceptionSeverity as Sev;
use App\Modules\HR\Attendance\Support\AttendanceExceptionType;
use Carbon\CarbonImmutable;

class ExcessiveOvertimeExceptionRule implements AttendanceExceptionDetectionRule
{
    public function __construct(
        private readonly AttendanceExceptionRepository $exceptions,
    ) {}

    public function run(int $tenantId, CarbonImmutable $from, CarbonImmutable $to): int
    {
        $min = (int) config('attendance.overtime_exception_threshold_minutes', 180);
        $crit = (int) config('attendance.overtime_critical_minutes', 360);
        $created = 0;

        AttendanceRecord::query()
            ->where('tenant_id', $tenantId)
            ->whereBetween('attendance_date', [$from->toDateString(), $to->toDateString()])
            ->where('overtime_minutes', '>=', $min)
            ->chunkById(500, function ($chunk) use ($tenantId, $crit, &$created): void {
                foreach ($chunk as $record) {
                    $dayKey = $record->attendance_date->toDateString();
                    $key = AttendanceExceptionDedupeKey::forRecordType(
                        $tenantId,
                        (int) $record->employee_id,
                        (int) $record->id,
                        AttendanceExceptionType::EXCESSIVE_OVERTIME,
                        $dayKey,
                    );
                    $sev = (int) $record->overtime_minutes >= $crit ? Sev::CRITICAL : Sev::MEDIUM;
                    $created += (int) $this->exceptions->tryInsert(
                        $tenantId,
                        (int) $record->employee_id,
                        (int) $record->id,
                        AttendanceExceptionType::EXCESSIVE_OVERTIME,
                        $sev,
                        $key,
                        ['overtime_minutes' => (int) $record->overtime_minutes],
                    );
                }
            });

        return $created;
    }
}
