<?php
declare(strict_types=1);

namespace App\Modules\PlayerAffairs\Models;

use App\Core\Model;
use App\Core\App;

class PlayerEvaluation extends Model
{
    protected static string $table = 'player_evaluations';
    protected static string $primaryKey = 'id';
    protected static bool $timestamps = true;
    protected static bool $softDelete = false;
    protected static bool $autoTrackAuthor = true;

    protected static array $fillable = [
        'player_id',
        'discipline_id',
        'session_id',
        'evaluator_coach_id',
        'evaluation_date',
        'overall_score',
        'skill_level',
        'recommended_group_type',
        'recommended_group_id',
        'scores_json',
        'strengths_ar',
        'weaknesses_ar',
        'coach_notes',
        'parent_visible',
        'status',
        'approved_by',
        'approved_at',
    ];

    /**
     * Get all evaluations for a player, ordered by date descending.
     */
    public static function getForPlayer(int $playerId): array
    {
        $db = App::getInstance()->db();
        return $db->select(
            "SELECT pe.*, d.name_ar AS discipline_name, c.full_name_ar AS coach_name
             FROM player_evaluations pe
             LEFT JOIN sport_disciplines d ON d.id = pe.discipline_id
             LEFT JOIN coaches c ON c.id = pe.evaluator_coach_id
             WHERE pe.player_id = ?
             ORDER BY pe.evaluation_date DESC, pe.id DESC",
            [$playerId]
        );
    }

    /**
     * Get all evaluations done by a specific coach.
     */
    public static function getForCoach(int $coachId): array
    {
        $db = App::getInstance()->db();
        return $db->select(
            "SELECT pe.*, p.full_name_ar AS player_name, d.name_ar AS discipline_name
             FROM player_evaluations pe
             LEFT JOIN players p ON p.id = pe.player_id
             LEFT JOIN sport_disciplines d ON d.id = pe.discipline_id
             WHERE pe.evaluator_coach_id = ?
             ORDER BY pe.evaluation_date DESC, pe.id DESC",
            [$coachId]
        );
    }

    /**
     * Calculate the weighted overall score from individual criterion scores.
     *
     * @param array $scores Array of [{criterion_id, score, notes}]
     * @param int $disciplineId
     * @return float Overall weighted score (0-10 scale)
     */
    public static function calculateOverallScore(array $scores, int $disciplineId): float
    {
        $criteria = EvaluationCriterion::getForDiscipline($disciplineId);

        if (empty($criteria) || empty($scores)) {
            return 0.0;
        }

        // Index criteria by ID
        $criteriaMap = [];
        foreach ($criteria as $c) {
            $criteriaMap[(int) $c['id']] = $c;
        }

        $totalWeightedScore = 0.0;
        $totalWeight = 0.0;

        foreach ($scores as $s) {
            $criterionId = (int) ($s['criterion_id'] ?? 0);
            $score = (float) ($s['score'] ?? 0);

            if (!isset($criteriaMap[$criterionId])) {
                continue;
            }

            $criterion = $criteriaMap[$criterionId];
            $maxScore = (int) $criterion['max_score'];
            $weight = (float) $criterion['weight'];

            // Normalize score to 0-10 scale
            $normalizedScore = $maxScore > 0 ? ($score / $maxScore) * 10.0 : 0.0;

            $totalWeightedScore += $normalizedScore * $weight;
            $totalWeight += $weight;
        }

        if ($totalWeight <= 0) {
            return 0.0;
        }

        return round($totalWeightedScore / $totalWeight, 2);
    }

    /**
     * Search evaluations with filters and pagination.
     */
    public static function search(array $filters, int $perPage = 25, int $page = 1): array
    {
        $db = App::getInstance()->db();

        $where = ['1=1'];
        $params = [];

        if (!empty($filters['player_id'])) {
            $where[] = 'pe.player_id = ?';
            $params[] = (int) $filters['player_id'];
        }

        if (!empty($filters['discipline_id'])) {
            $where[] = 'pe.discipline_id = ?';
            $params[] = (int) $filters['discipline_id'];
        }

        if (!empty($filters['evaluator_coach_id'])) {
            $where[] = 'pe.evaluator_coach_id = ?';
            $params[] = (int) $filters['evaluator_coach_id'];
        }

        if (!empty($filters['status'])) {
            $where[] = 'pe.status = ?';
            $params[] = $filters['status'];
        }

        if (!empty($filters['skill_level'])) {
            $where[] = 'pe.skill_level = ?';
            $params[] = $filters['skill_level'];
        }

        if (!empty($filters['date_from'])) {
            $where[] = 'pe.evaluation_date >= ?';
            $params[] = $filters['date_from'];
        }

        if (!empty($filters['date_to'])) {
            $where[] = 'pe.evaluation_date <= ?';
            $params[] = $filters['date_to'];
        }

        if (!empty($filters['q'])) {
            $search = '%' . $filters['q'] . '%';
            $where[] = '(p.full_name_ar LIKE ? OR p.full_name_en LIKE ?)';
            $params[] = $search;
            $params[] = $search;
        }

        $whereClause = implode(' AND ', $where);

        // Count
        $countSql = "SELECT COUNT(*) AS total
                     FROM player_evaluations pe
                     LEFT JOIN players p ON p.id = pe.player_id
                     WHERE {$whereClause}";
        $countResult = $db->selectOne($countSql, $params);
        $total = (int) ($countResult['total'] ?? 0);

        $lastPage = max(1, (int) ceil($total / $perPage));
        $page = min($page, $lastPage);
        $offset = ($page - 1) * $perPage;

        // Fetch
        $sql = "SELECT pe.*, p.full_name_ar AS player_name, d.name_ar AS discipline_name,
                       c.full_name_ar AS coach_name
                FROM player_evaluations pe
                LEFT JOIN players p ON p.id = pe.player_id
                LEFT JOIN sport_disciplines d ON d.id = pe.discipline_id
                LEFT JOIN coaches c ON c.id = pe.evaluator_coach_id
                WHERE {$whereClause}
                ORDER BY pe.evaluation_date DESC, pe.id DESC
                LIMIT {$perPage} OFFSET {$offset}";

        $data = $db->select($sql, $params);

        return [
            'data' => $data,
            'pagination' => [
                'total'        => $total,
                'per_page'     => $perPage,
                'current_page' => $page,
                'last_page'    => $lastPage,
            ],
        ];
    }

    /**
     * Get skill level labels in Arabic.
     */
    public static function getSkillLevels(): array
    {
        return [
            'beginner'     => 'مبتدئ',
            'intermediate' => 'متوسط',
            'advanced'     => 'متقدم',
            'elite'        => 'نخبة',
        ];
    }

    /**
     * Get status labels in Arabic.
     */
    public static function getStatuses(): array
    {
        return [
            'draft'     => 'مسودة',
            'submitted' => 'مقدم',
            'approved'  => 'معتمد',
        ];
    }

    /**
     * Get badge color for skill level.
     */
    public static function getSkillLevelColor(string $level): string
    {
        $colors = [
            'beginner'     => '#6B7280',
            'intermediate' => '#D97706',
            'advanced'     => '#059669',
            'elite'        => '#7C3AED',
        ];
        return $colors[$level] ?? '#6B7280';
    }

    /**
     * Get badge color for status.
     */
    public static function getStatusColor(string $status): string
    {
        $colors = [
            'draft'     => '#6B7280',
            'submitted' => '#0284C7',
            'approved'  => '#059669',
        ];
        return $colors[$status] ?? '#6B7280';
    }
}
