<?php
declare(strict_types=1);

namespace App\Modules\PlayerAffairs\Services;

use App\Core\App;
use App\Core\EventBus;
use App\Core\Logger;
use App\Modules\PlayerAffairs\Models\PlayerInjury;

final class InjuryService
{
    /**
     * Report a new injury for a player.
     */
    public static function reportInjury(array $data): PlayerInjury
    {
        // Build restricted activities JSON if provided as array
        if (isset($data['restricted_activities']) && is_array($data['restricted_activities'])) {
            $data['restricted_activities_json'] = json_encode($data['restricted_activities'], JSON_UNESCAPED_UNICODE);
            unset($data['restricted_activities']);
        }

        // Set default status
        if (empty($data['status'])) {
            $data['status'] = 'active';
        }

        // Set reporter
        $employee = App::getInstance()->currentEmployee();
        if ($employee && empty($data['reported_by'])) {
            $data['reported_by'] = (int) ($employee->id ?? ($employee['id'] ?? null));
        }

        $injury = PlayerInjury::create($data);

        // Dispatch event
        EventBus::dispatch('player.injury_reported', [
            'injury_id'  => (int) $injury->id,
            'player_id'  => (int) $injury->player_id,
            'severity'   => $injury->severity,
            'injury_type'=> $injury->injury_type,
            'body_part'  => $injury->body_part,
        ]);

        // If severe or critical, auto-restrict the player
        if (in_array($injury->severity, ['severe', 'critical'], true)) {
            self::autoRestrict((int) $injury->player_id, $injury);
        }

        Logger::info("Injury reported for player #{$injury->player_id}: {$injury->injury_type} ({$injury->severity})");

        return $injury;
    }

    /**
     * Update injury status (recovering, recovered, chronic).
     */
    public static function updateStatus(int $injuryId, string $newStatus, ?array $clearanceData = null): bool
    {
        $injury = PlayerInjury::findOrFail($injuryId);
        $oldStatus = $injury->status;

        $updateData = ['status' => $newStatus];

        if ($newStatus === 'recovered') {
            $updateData['actual_recovery_date'] = $clearanceData['recovery_date'] ?? date('Y-m-d');

            if (!empty($clearanceData['cleared_by'])) {
                $updateData['cleared_by'] = (int) $clearanceData['cleared_by'];
            } else {
                $employee = App::getInstance()->currentEmployee();
                if ($employee) {
                    $updateData['cleared_by'] = (int) ($employee->id ?? ($employee['id'] ?? null));
                }
            }

            $updateData['cleared_at'] = date('Y-m-d');

            if (!empty($clearanceData['clearance_document_id'])) {
                $updateData['clearance_document_id'] = (int) $clearanceData['clearance_document_id'];
            }

            // Dispatch recovery event
            EventBus::dispatch('player.injury_recovered', [
                'injury_id' => $injuryId,
                'player_id' => (int) $injury->player_id,
                'injury_type' => $injury->injury_type,
            ]);
        }

        $injury->update($updateData);

        Logger::info("Injury #{$injuryId} status changed from {$oldStatus} to {$newStatus}");

        return true;
    }

    /**
     * Get active restrictions for a player (activities they cannot do).
     */
    public static function getActiveRestrictions(int $playerId): array
    {
        $db = App::getInstance()->db();
        $activeInjuries = $db->select(
            "SELECT id, injury_type, body_part, severity, restricted_activities_json, status
             FROM player_injuries
             WHERE player_id = ? AND status IN ('active', 'recovering')
             ORDER BY severity DESC",
            [$playerId]
        );

        $restrictions = [];
        foreach ($activeInjuries as $injury) {
            $activities = [];
            if (!empty($injury['restricted_activities_json'])) {
                $decoded = json_decode($injury['restricted_activities_json'], true);
                if (is_array($decoded)) {
                    $activities = $decoded;
                }
            }

            $restrictions[] = [
                'injury_id'            => (int) $injury['id'],
                'injury_type'          => $injury['injury_type'],
                'body_part'            => $injury['body_part'],
                'severity'             => $injury['severity'],
                'status'               => $injury['status'],
                'restricted_activities'=> $activities,
            ];
        }

        return $restrictions;
    }

    /**
     * Check if a player is cleared for all their enrolled activities.
     */
    public static function checkClearance(int $playerId): bool
    {
        $db = App::getInstance()->db();
        $activeCount = $db->selectOne(
            "SELECT COUNT(*) as cnt FROM player_injuries
             WHERE player_id = ? AND status IN ('active', 'recovering')",
            [$playerId]
        );

        return (int) ($activeCount['cnt'] ?? 0) === 0;
    }

    /**
     * Get injury statistics for a player.
     */
    public static function getPlayerStats(int $playerId): array
    {
        $db = App::getInstance()->db();

        $total = $db->selectOne(
            "SELECT COUNT(*) as cnt FROM player_injuries WHERE player_id = ?",
            [$playerId]
        );

        $active = $db->selectOne(
            "SELECT COUNT(*) as cnt FROM player_injuries WHERE player_id = ? AND status IN ('active', 'recovering')",
            [$playerId]
        );

        $recovered = $db->selectOne(
            "SELECT COUNT(*) as cnt FROM player_injuries WHERE player_id = ? AND status = 'recovered'",
            [$playerId]
        );

        $avgRecovery = $db->selectOne(
            "SELECT AVG(DATEDIFF(actual_recovery_date, occurred_date)) as avg_days
             FROM player_injuries
             WHERE player_id = ? AND status = 'recovered' AND actual_recovery_date IS NOT NULL",
            [$playerId]
        );

        return [
            'total'             => (int) ($total['cnt'] ?? 0),
            'active'            => (int) ($active['cnt'] ?? 0),
            'recovered'         => (int) ($recovered['cnt'] ?? 0),
            'avg_recovery_days' => $avgRecovery['avg_days'] !== null ? round((float) $avgRecovery['avg_days'], 1) : null,
        ];
    }

    /**
     * Auto-restrict player from activities when severe/critical injury.
     */
    private static function autoRestrict(int $playerId, PlayerInjury $injury): void
    {
        try {
            $db = App::getInstance()->db();

            // Suspend the player's card if severe/critical
            $player = $db->selectOne("SELECT card_status FROM players WHERE id = ?", [$playerId]);
            if ($player && $player['card_status'] === 'active') {
                $db->update('players', [
                    'card_status' => 'suspended',
                    'updated_at'  => date('Y-m-d H:i:s'),
                ], 'id = ?', [$playerId]);

                EventBus::dispatch('player.card_suspended', [
                    'player_id' => $playerId,
                    'reason'    => 'إصابة ' . (PlayerInjury::getSeverities()[$injury->severity] ?? $injury->severity),
                ]);
            }
        } catch (\Throwable $e) {
            Logger::error("Auto-restrict failed for player #{$playerId}: " . $e->getMessage());
        }
    }
}
