<?php
declare(strict_types=1);

namespace App\Modules\Alerts\Services;

use App\Core\App;
use App\Modules\Alerts\Models\AlertRule;

final class AlertProcessorService
{
    /**
     * Process all active alert rules and return triggered alerts.
     */
    public static function processAll(): array
    {
        $rules = AlertRule::allActive();
        $triggered = [];

        foreach ($rules as $rule) {
            $results = [];

            switch ($rule['category']) {
                case 'medical':
                    $results = self::checkMedicalCertExpiry($rule);
                    break;
                case 'contracts':
                    $results = self::checkContractExpiry($rule);
                    break;
                case 'attendance':
                    $results = self::checkAttendanceDropping($rule);
                    break;
                case 'capacity':
                    $results = self::checkGroupNearCapacity($rule);
                    break;
            }

            if (!empty($results)) {
                foreach ($results as $context) {
                    self::logAlert((int) $rule['id'], $context);
                }
                $triggered[] = [
                    'rule' => $rule,
                    'count' => count($results),
                ];

                // Update last_triggered_at
                $db = App::getInstance()->db();
                $db->update('alert_rules', [
                    'last_triggered_at' => date('Y-m-d H:i:s'),
                ], 'id = ?', [(int) $rule['id']]);
            }
        }

        return $triggered;
    }

    /**
     * Check for player medical records expiring within configured days.
     */
    public static function checkMedicalCertExpiry(array $rule): array
    {
        $db = App::getInstance()->db();
        $config = json_decode($rule['trigger_config_json'] ?? '{}', true);
        $days = (int) ($config['days_before'] ?? 30);

        $rows = $db->select(
            "SELECT pmr.id, pmr.player_id, pmr.expiry_date, p.full_name_ar AS player_name
             FROM player_medical_records pmr
             LEFT JOIN players p ON p.id = pmr.player_id
             WHERE pmr.expiry_date IS NOT NULL
               AND pmr.expiry_date BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL ? DAY)
               AND pmr.is_current = 1",
            [$days]
        );

        $results = [];
        foreach ($rows as $row) {
            $results[] = [
                'type' => 'medical_expiry',
                'player_id' => $row['player_id'],
                'player_name' => $row['player_name'],
                'expiry_date' => $row['expiry_date'],
                'message' => "الشهادة الطبية للاعب {$row['player_name']} تنتهي في {$row['expiry_date']}",
            ];
        }

        return $results;
    }

    /**
     * Check for academy contracts expiring soon.
     */
    public static function checkContractExpiry(array $rule): array
    {
        $db = App::getInstance()->db();
        $config = json_decode($rule['trigger_config_json'] ?? '{}', true);
        $days = (int) ($config['days_before'] ?? 30);

        $rows = $db->select(
            "SELECT ac.id, ac.academy_id, ac.end_date, a.name_ar AS academy_name
             FROM academy_contracts ac
             LEFT JOIN academies a ON a.id = ac.academy_id
             WHERE ac.end_date IS NOT NULL
               AND ac.end_date BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL ? DAY)
               AND ac.status = 'active'",
            [$days]
        );

        $results = [];
        foreach ($rows as $row) {
            $results[] = [
                'type' => 'contract_expiry',
                'academy_id' => $row['academy_id'],
                'academy_name' => $row['academy_name'],
                'end_date' => $row['end_date'],
                'message' => "عقد أكاديمية {$row['academy_name']} ينتهي في {$row['end_date']}",
            ];
        }

        return $results;
    }

    /**
     * Check for players with 3+ consecutive absences.
     */
    public static function checkAttendanceDropping(array $rule): array
    {
        $db = App::getInstance()->db();
        $config = json_decode($rule['trigger_config_json'] ?? '{}', true);
        $threshold = (int) ($config['consecutive_absences'] ?? 3);

        $rows = $db->select(
            "SELECT sa.player_id, p.full_name_ar AS player_name, COUNT(*) AS absence_count
             FROM session_attendance sa
             LEFT JOIN players p ON p.id = sa.player_id
             WHERE sa.status = 'absent'
               AND sa.session_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
             GROUP BY sa.player_id
             HAVING absence_count >= ?
             ORDER BY absence_count DESC",
            [$threshold]
        );

        $results = [];
        foreach ($rows as $row) {
            $results[] = [
                'type' => 'attendance_dropping',
                'player_id' => $row['player_id'],
                'player_name' => $row['player_name'],
                'absence_count' => $row['absence_count'],
                'message' => "اللاعب {$row['player_name']} لديه {$row['absence_count']} غيابات متتالية",
            ];
        }

        return $results;
    }

    /**
     * Check for training groups at 90%+ capacity.
     */
    public static function checkGroupNearCapacity(array $rule): array
    {
        $db = App::getInstance()->db();
        $config = json_decode($rule['trigger_config_json'] ?? '{}', true);
        $threshold = (int) ($config['capacity_percent'] ?? 90);

        $rows = $db->select(
            "SELECT tg.id, tg.name_ar, tg.max_capacity,
                    COUNT(tgp.id) AS current_count
             FROM training_groups tg
             LEFT JOIN training_group_players tgp ON tgp.group_id = tg.id AND tgp.is_active = 1
             WHERE tg.is_active = 1 AND tg.max_capacity > 0
             GROUP BY tg.id
             HAVING (current_count / tg.max_capacity * 100) >= ?",
            [$threshold]
        );

        $results = [];
        foreach ($rows as $row) {
            $pct = $row['max_capacity'] > 0
                ? round(($row['current_count'] / $row['max_capacity']) * 100)
                : 0;
            $results[] = [
                'type' => 'capacity_near_full',
                'group_id' => $row['id'],
                'group_name' => $row['name_ar'],
                'current_count' => $row['current_count'],
                'max_capacity' => $row['max_capacity'],
                'percent' => $pct,
                'message' => "المجموعة {$row['name_ar']} وصلت {$pct}% من السعة ({$row['current_count']}/{$row['max_capacity']})",
            ];
        }

        return $results;
    }

    /**
     * Log a triggered alert to the alert_log table.
     */
    public static function logAlert(int $ruleId, array $context): void
    {
        $db = App::getInstance()->db();
        $db->insert('alert_log', [
            'alert_rule_id' => $ruleId,
            'triggered_at'  => date('Y-m-d H:i:s'),
            'context_json'  => json_encode($context, JSON_UNESCAPED_UNICODE),
            'recipients_json' => null,
            'status'        => 'sent',
        ]);
    }
}
