<?php

namespace App\Console\Commands;

use App\Domain\Attendance\Enums\AttendanceStatus;
use App\Domain\Attendance\Events\AttendanceThresholdBreached;
use App\Domain\Attendance\Models\AttendanceRecord;
use App\Domain\Participant\Models\Participant;
use App\Domain\Shared\Services\SettingsService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;

class SendAttendanceAlerts extends Command
{
    protected $signature = 'attendance:send-alerts';
    protected $description = 'إرسال تنبيهات الحضور';

    private const DEFAULT_MIN_ATTENDANCE_PERCENT = 75;
    private const LOOKBACK_DAYS = 30;

    public function handle(SettingsService $settings): int
    {
        $threshold = (float) ($settings->get('min_attendance_percent', self::DEFAULT_MIN_ATTENDANCE_PERCENT));

        $participants = Participant::where('status', 'active')->get();

        $alertCount = 0;

        foreach ($participants as $participant) {
            $rate = $this->calculateRecentRate($participant);

            // Skip if insufficient data (null means not enough records)
            if ($rate === null) {
                continue;
            }

            if ($rate < $threshold) {
                AttendanceThresholdBreached::dispatch($participant, $rate, $threshold);
                $alertCount++;

                $this->warn("نسبة حضور منخفضة: {$participant->person?->name_ar} ({$rate}%)");
            }
        }

        $this->info("تم إرسال {$alertCount} تنبيه حضور.");
        Log::info("SendAttendanceAlerts: Dispatched {$alertCount} threshold breach alerts");

        return self::SUCCESS;
    }

    /**
     * Calculate attendance rate for the last 30 days.
     * Formula: rate = (present + late + partial) / (total - cancelled - exempt) x 100
     * Returns null if insufficient data (less than 5 records).
     */
    private function calculateRecentRate(Participant $participant): ?float
    {
        $since = now()->subDays(self::LOOKBACK_DAYS);

        $query = AttendanceRecord::where('subject_type', Participant::class)
            ->where('subject_id', $participant->id)
            ->whereHas('session', fn ($q) => $q->where('session_date', '>=', $since));

        $total = (clone $query)->count();

        // Need at least 5 records to be meaningful
        if ($total < 5) {
            return null;
        }

        $excluded = (clone $query)->whereIn('status', [
            AttendanceStatus::Cancelled,
            AttendanceStatus::Exempt,
        ])->count();

        $denominator = $total - $excluded;
        if ($denominator <= 0) {
            return null;
        }

        $positive = (clone $query)->whereIn('status', [
            AttendanceStatus::Present,
            AttendanceStatus::Late,
            AttendanceStatus::Partial,
        ])->count();

        return round(($positive / $denominator) * 100, 1);
    }
}
