<?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';

function discipline_module_boot(): void
{
    require_login();

    if (!can_manage_discipline_cases() && !can_manage_discipline_suspensions()) {
        abort_request(403, 'Access denied', 'You do not have permission to access discipline management.');
    }
}

function can_manage_discipline_cases(): bool
{
    return can('manage_discipline');
}

function can_manage_discipline_suspensions(): bool
{
    return can('manage_suspensions') || can_manage_discipline_cases();
}

function discipline_competition_options(): array
{
    return db_fetch_all(
        'SELECT c.id, c.name, s.name AS season_name
         FROM competitions c
         INNER JOIN seasons s ON s.id = c.season_id
         ORDER BY s.start_date DESC, c.name ASC'
    );
}

function suspension_status_badge_class(string $status): string
{
    return match ($status) {
        'active' => 'badge-soft-danger',
        'served' => 'badge-soft-success',
        'cancelled' => 'text-bg-light',
        default => 'text-bg-light',
    };
}

function disciplinary_case_status_badge_class(string $status): string
{
    return match ($status) {
        'pending' => 'bg-warning-subtle text-warning-emphasis',
        'reviewed' => 'bg-info-subtle text-info-emphasis',
        'closed' => 'badge-soft-success',
        default => 'text-bg-light',
    };
}

function suspension_list(?int $competitionId = null): array
{
    $sql = 'SELECT s.*, p.first_name, p.last_name, c.name AS club_name,
                   f.id AS fixture_id, comp.id AS competition_id, comp.name AS competition_name
            FROM suspensions s
            INNER JOIN players p ON p.id = s.player_id
            INNER JOIN clubs c ON c.id = s.club_id
            LEFT JOIN fixtures f ON f.id = s.start_fixture_id
            LEFT JOIN competitions comp ON comp.id = f.competition_id';
    $params = [];
    if ($competitionId !== null && $competitionId > 0) {
        $sql .= ' WHERE comp.id = :competition_id';
        $params['competition_id'] = $competitionId;
    }
    $sql .= ' ORDER BY FIELD(s.status, "active", "served", "cancelled"), s.created_at DESC, s.id DESC';

    return db_fetch_all($sql, $params);
}

function disciplinary_case_list(?int $competitionId = null): array
{
    $sql = 'SELECT dc.*, p.first_name, p.last_name, c.name AS club_name,
                   f.id AS fixture_id, comp.id AS competition_id, comp.name AS competition_name
            FROM disciplinary_cases dc
            LEFT JOIN players p ON p.id = dc.player_id
            LEFT JOIN clubs c ON c.id = dc.club_id
            LEFT JOIN fixtures f ON f.id = dc.fixture_id
            LEFT JOIN competitions comp ON comp.id = f.competition_id';
    $params = [];
    if ($competitionId !== null && $competitionId > 0) {
        $sql .= ' WHERE comp.id = :competition_id';
        $params['competition_id'] = $competitionId;
    }
    $sql .= ' ORDER BY FIELD(dc.status, "pending", "reviewed", "closed"), dc.created_at DESC, dc.id DESC';

    return db_fetch_all($sql, $params);
}

function get_suspension_by_id(int $suspensionId): ?array
{
    return db_fetch_one(
        'SELECT s.*, p.first_name, p.last_name, c.name AS club_name,
                comp.name AS competition_name
         FROM suspensions s
         INNER JOIN players p ON p.id = s.player_id
         INNER JOIN clubs c ON c.id = s.club_id
         LEFT JOIN fixtures f ON f.id = s.start_fixture_id
         LEFT JOIN competitions comp ON comp.id = f.competition_id
         WHERE s.id = :id
         LIMIT 1',
        ['id' => $suspensionId]
    );
}

function get_disciplinary_case_by_id(int $caseId): ?array
{
    return db_fetch_one(
        'SELECT dc.*, p.first_name, p.last_name, c.name AS club_name,
                comp.name AS competition_name
         FROM disciplinary_cases dc
         LEFT JOIN players p ON p.id = dc.player_id
         LEFT JOIN clubs c ON c.id = dc.club_id
         LEFT JOIN fixtures f ON f.id = dc.fixture_id
         LEFT JOIN competitions comp ON comp.id = f.competition_id
         WHERE dc.id = :id
         LIMIT 1',
        ['id' => $caseId]
    );
}

function find_suspension_or_abort(int $suspensionId): array
{
    $suspension = get_suspension_by_id($suspensionId);
    if ($suspension === null) {
        abort_request(404, 'Suspension not found', 'The requested suspension record does not exist.');
    }

    return $suspension;
}

function find_disciplinary_case_or_abort(int $caseId): array
{
    $case = get_disciplinary_case_by_id($caseId);
    if ($case === null) {
        abort_request(404, 'Case not found', 'The requested disciplinary case does not exist.');
    }

    return $case;
}

function suspension_status_options(): array
{
    return ['active', 'served', 'cancelled'];
}

function disciplinary_case_status_options(): array
{
    return ['pending', 'reviewed', 'closed'];
}

function validate_suspension_payload(array $data, array &$errors): array
{
    validate_in_array_field($data, 'status', suspension_status_options(), 'Status', $errors);
    validate_numeric_min($data, 'matches_served', 'Matches served', 0, $errors);

    return [
        'matches_served' => (int) (($data['matches_served'] ?? '') === '' ? 0 : $data['matches_served']),
        'status' => (string) ($data['status'] ?? 'active'),
    ];
}

function validate_disciplinary_case_payload(array $data, array &$errors): array
{
    validate_in_array_field($data, 'status', disciplinary_case_status_options(), 'Status', $errors);
    validate_numeric_min($data, 'fine_amount', 'Fine amount', 0, $errors);

    return [
        'decision' => trim((string) ($data['decision'] ?? '')),
        'fine_amount' => (float) (($data['fine_amount'] ?? '') === '' ? 0 : $data['fine_amount']),
        'status' => (string) ($data['status'] ?? 'pending'),
    ];
}
