<?php

namespace App\Services;

use App\Models\AppSetting;
use App\Models\AttendanceEvent;
use App\Models\DailyAttendance;
use App\Models\Employee;
use Illuminate\Support\Carbon;

class AttendanceComputer
{
    /**
     * Recompute daily_attendance for every employee for the given date,
     * derived from attendance_events (corrected originals are ignored).
     * Returns the number of employees processed.
     */
    public function computeForDate(Carbon $date): int
    {
        $settings = AppSetting::current();
        $dateStr = $date->toDateString();

        $shiftStart = Carbon::parse($dateStr.' '.$settings->shift_start);
        $shiftEnd = Carbon::parse($dateStr.' '.$settings->shift_end);

        $employees = Employee::query()->get();

        foreach ($employees as $employee) {
            $events = AttendanceEvent::query()
                ->where('employee_id', $employee->id)
                ->whereDate('ts', $dateStr)
                ->notCorrected()
                ->orderBy('ts')
                ->get();

            if ($events->isEmpty()) {
                DailyAttendance::updateOrCreate(
                    ['employee_id' => $employee->id, 'date' => $dateStr],
                    [
                        'first_in' => null,
                        'last_out' => null,
                        'worked_minutes' => null,
                        'late' => false,
                        'early_out' => false,
                        'status' => 'absent',
                    ]
                );

                continue;
            }

            $firstIn = $events->where('direction', 'IN')->first()?->ts;
            $lastOut = $events->where('direction', 'OUT')->last()?->ts;

            $workedMinutes = null;
            if ($firstIn && $lastOut && $lastOut->gt($firstIn)) {
                $workedMinutes = $firstIn->diffInMinutes($lastOut);
            }

            $late = $firstIn ? $firstIn->gt($shiftStart) : false;
            $earlyOut = $lastOut ? $lastOut->lt($shiftEnd) : false;
            $hasManual = $events->contains(fn (AttendanceEvent $e) => $e->source === 'manual');

            DailyAttendance::updateOrCreate(
                ['employee_id' => $employee->id, 'date' => $dateStr],
                [
                    'first_in' => $firstIn,
                    'last_out' => $lastOut,
                    'worked_minutes' => $workedMinutes,
                    'late' => $late,
                    'early_out' => $earlyOut,
                    'status' => $hasManual ? 'manual' : 'present',
                ]
            );
        }

        return $employees->count();
    }
}
