<?php

declare(strict_types=1);

require_once dirname(__DIR__, 2) . '/core/auth.php';
require_once dirname(__DIR__, 2) . '/core/csrf.php';
require_once dirname(__DIR__, 2) . '/core/validation.php';
require_once dirname(__DIR__, 2) . '/core/audit.php';
require_once dirname(__DIR__, 2) . '/modules/seasons/helpers.php';
require_once dirname(__DIR__, 2) . '/modules/competitions/helpers.php';
require_once dirname(__DIR__, 2) . '/modules/clubs/helpers.php';
require_once dirname(__DIR__, 2) . '/modules/players/helpers.php';

function awards_module_boot(): void
{
    require_login();
    require_permission('manage_awards');
}

function award_type_options(): array
{
    return ['champion', 'runner_up', 'top_scorer', 'best_goalkeeper', 'best_player', 'fair_play', 'best_coach'];
}

function award_type_label(string $type): string
{
    return match ($type) {
        'champion' => 'Champion',
        'runner_up' => 'Runner-up',
        'top_scorer' => 'Top scorer',
        'best_goalkeeper' => 'Best goalkeeper',
        'best_player' => 'Best player',
        'fair_play' => 'Fair play',
        'best_coach' => 'Best coach',
        default => ucfirst(str_replace('_', ' ', $type)),
    };
}

function award_player_types(): array
{
    return ['top_scorer', 'best_goalkeeper', 'best_player'];
}

function award_club_types(): array
{
    return ['champion', 'runner_up', 'fair_play', 'best_coach'];
}

function awards_list(): array
{
    return db_fetch_all(
        'SELECT a.*, s.name AS season_name,
                c.name AS competition_name,
                cl.name AS club_name,
                p.first_name, p.last_name, p.middle_name
         FROM awards a
         INNER JOIN seasons s ON s.id = a.season_id
         LEFT JOIN competitions c ON c.id = a.competition_id
         LEFT JOIN clubs cl ON cl.id = a.club_id
         LEFT JOIN players p ON p.id = a.player_id
         ORDER BY a.created_at DESC, a.id DESC'
    );
}

function award_competition_options(): array
{
    return competition_list();
}

function award_club_options(): array
{
    return club_options();
}

function award_player_options(): array
{
    return db_fetch_all(
        'SELECT p.id, p.club_id, p.first_name, p.middle_name, p.last_name, c.name AS club_name
         FROM players p
         INNER JOIN clubs c ON c.id = p.club_id
         ORDER BY p.first_name ASC, p.last_name ASC, p.id DESC'
    );
}

function get_award_by_id(int $awardId): ?array
{
    return db_fetch_one(
        'SELECT a.*, s.name AS season_name,
                c.name AS competition_name,
                cl.name AS club_name,
                p.first_name, p.last_name, p.middle_name
         FROM awards a
         INNER JOIN seasons s ON s.id = a.season_id
         LEFT JOIN competitions c ON c.id = a.competition_id
         LEFT JOIN clubs cl ON cl.id = a.club_id
         LEFT JOIN players p ON p.id = a.player_id
         WHERE a.id = :id
         LIMIT 1',
        ['id' => $awardId]
    );
}

function find_award_or_abort(int $awardId): array
{
    $award = get_award_by_id($awardId);

    if ($award === null) {
        abort_request(404, 'Award not found', 'The requested award record does not exist.');
    }

    return $award;
}

function award_recipient_name(array $award): string
{
    if (!empty($award['player_id'])) {
        return trim((string) (($award['first_name'] ?? '') . ' ' . ($award['middle_name'] ?? '') . ' ' . ($award['last_name'] ?? '')));
    }

    return (string) ($award['club_name'] ?? 'No recipient');
}

function validate_award_payload(array $data, array &$errors, ?int $awardId = null): array
{
    validate_required($data, [
        'season_id' => 'Season',
        'award_type' => 'Award type',
        'title' => 'Title',
    ], $errors);

    validate_in_array_field($data, 'award_type', award_type_options(), 'Award type', $errors);

    $normalized = [
        'season_id' => (int) ($data['season_id'] ?? 0),
        'competition_id' => (int) ($data['competition_id'] ?? 0),
        'award_type' => (string) ($data['award_type'] ?? ''),
        'club_id' => (int) ($data['club_id'] ?? 0),
        'player_id' => (int) ($data['player_id'] ?? 0),
        'title' => trim((string) ($data['title'] ?? '')),
        'description' => trim((string) ($data['description'] ?? '')),
    ];

    if ($normalized['season_id'] <= 0 || get_season_by_id($normalized['season_id']) === null) {
        $errors['season_id'] = 'Selected season is invalid.';
    }

    if ($normalized['competition_id'] > 0) {
        $competition = get_competition_by_id($normalized['competition_id']);
        if ($competition === null) {
            $errors['competition_id'] = 'Selected competition is invalid.';
        } elseif ((int) $competition['season_id'] !== $normalized['season_id']) {
            $errors['competition_id'] = 'Competition must belong to the selected season.';
        }
    } else {
        $normalized['competition_id'] = null;
    }

    $awardType = $normalized['award_type'];
    $requiresPlayer = in_array($awardType, award_player_types(), true);
    $requiresClub = in_array($awardType, award_club_types(), true);

    $player = null;
    if ($normalized['player_id'] > 0) {
        $player = get_player_by_id($normalized['player_id']);
        if ($player === null) {
            $errors['player_id'] = 'Selected player is invalid.';
        }
    }

    if ($requiresPlayer && $normalized['player_id'] <= 0) {
        $errors['player_id'] = 'This award type requires a player recipient.';
    }

    if ($requiresClub && $normalized['club_id'] <= 0) {
        $errors['club_id'] = 'This award type requires a club recipient.';
    }

    if ($normalized['club_id'] > 0 && get_club_by_id($normalized['club_id']) === null) {
        $errors['club_id'] = 'Selected club is invalid.';
    }

    if ($requiresPlayer && $player !== null) {
        $normalized['club_id'] = (int) $player['club_id'];
    }

    if (!$requiresPlayer) {
        $normalized['player_id'] = null;
    }

    if (!$requiresClub && !$requiresPlayer) {
        $normalized['club_id'] = $normalized['club_id'] > 0 ? $normalized['club_id'] : null;
    }

    $params = [
        'season_id' => $normalized['season_id'],
        'award_type' => $normalized['award_type'],
        'title' => $normalized['title'],
    ];
    $sql = 'SELECT COUNT(*) FROM awards WHERE season_id = :season_id AND award_type = :award_type AND title = :title';

    if ($normalized['competition_id'] !== null) {
        $sql .= ' AND competition_id = :competition_id';
        $params['competition_id'] = $normalized['competition_id'];
    } else {
        $sql .= ' AND competition_id IS NULL';
    }

    if ($awardId !== null) {
        $sql .= ' AND id <> :id';
        $params['id'] = $awardId;
    }

    if ($normalized['title'] !== '' && (int) db_fetch_value($sql, $params, 0) > 0) {
        $errors['title'] = 'An award with this title already exists for the selected season and competition.';
    }

    return $normalized;
}
