<?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) . '/core/upload.php';
require_once dirname(__DIR__, 2) . '/modules/clubs/helpers.php';

function media_module_boot(): void
{
    require_login();

    if (!can_manage_media() && !can_publish_news()) {
        abort_request(403, 'Access denied', 'You do not have permission to access media management.');
    }
}

function can_manage_media(): bool
{
    return can('manage_media');
}

function can_publish_news(): bool
{
    return can('publish_news');
}

function news_status_options(): array
{
    return ['draft', 'published'];
}

function news_category_options(): array
{
    return ['general', 'competition_update', 'fixture_postponement', 'fixture_reschedule', 'transfer_update', 'match_report', 'match_update', 'fixture_kit_confirmation'];
}

function news_category_label(string $category): string
{
    return match ($category) {
        'competition_update' => 'Competition update',
        'fixture_postponement' => 'Fixture postponement',
        'fixture_reschedule' => 'Fixture reschedule',
        'transfer_update' => 'Transfer update',
        'match_report' => 'Match report',
        'match_update' => 'Match update draft',
        'fixture_kit_confirmation' => 'Matchday kit confirmation',
        default => 'General',
    };
}

function news_category_badge_class(string $category): string
{
    return match ($category) {
        'competition_update' => 'bg-info-subtle text-info-emphasis',
        'fixture_postponement' => 'bg-warning-subtle text-warning-emphasis',
        'fixture_reschedule' => 'bg-primary-subtle text-primary-emphasis',
        'transfer_update' => 'bg-success-subtle text-success-emphasis',
        'match_report' => 'badge-soft-success',
        'match_update' => 'bg-secondary-subtle text-secondary-emphasis',
        'fixture_kit_confirmation' => 'bg-dark-subtle text-dark-emphasis',
        default => 'text-bg-light',
    };
}

function media_type_options(): array
{
    return ['image', 'video'];
}

function news_list(): array
{
    return db_fetch_all(
        'SELECT np.*, u.full_name AS author_name
         FROM news_posts np
         LEFT JOIN users u ON u.id = np.created_by
         ORDER BY COALESCE(np.published_at, np.created_at) DESC, np.id DESC'
    );
}

function media_gallery_list(): array
{
    return db_fetch_all(
        'SELECT mg.*, f.matchday, f.match_date,
                hc.name AS home_club_name, ac.name AS away_club_name,
                c.name AS club_name
         FROM media_gallery mg
         LEFT JOIN fixtures f ON f.id = mg.fixture_id
         LEFT JOIN clubs hc ON hc.id = f.home_club_id
         LEFT JOIN clubs ac ON ac.id = f.away_club_id
         LEFT JOIN clubs c ON c.id = mg.club_id
         ORDER BY mg.created_at DESC, mg.id DESC'
    );
}

function media_fixture_options(): array
{
    return db_fetch_all(
        'SELECT f.id, f.matchday, f.match_date,
                hc.name AS home_club_name, ac.name AS away_club_name,
                cmp.name AS competition_name
         FROM fixtures f
         INNER JOIN clubs hc ON hc.id = f.home_club_id
         INNER JOIN clubs ac ON ac.id = f.away_club_id
         INNER JOIN competitions cmp ON cmp.id = f.competition_id
         ORDER BY COALESCE(f.match_date, "9999-12-31") DESC, f.id DESC'
    );
}

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

function get_news_post_by_id(int $postId): ?array
{
    return db_fetch_one(
        'SELECT np.*, u.full_name AS author_name
         FROM news_posts np
         LEFT JOIN users u ON u.id = np.created_by
         WHERE np.id = :id
         LIMIT 1',
        ['id' => $postId]
    );
}

function find_news_post_or_abort(int $postId): array
{
    $post = get_news_post_by_id($postId);

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

    return $post;
}

function get_media_item_by_id(int $mediaId): ?array
{
    return db_fetch_one(
        'SELECT mg.*, f.matchday, f.match_date,
                hc.name AS home_club_name, ac.name AS away_club_name,
                c.name AS club_name
         FROM media_gallery mg
         LEFT JOIN fixtures f ON f.id = mg.fixture_id
         LEFT JOIN clubs hc ON hc.id = f.home_club_id
         LEFT JOIN clubs ac ON ac.id = f.away_club_id
         LEFT JOIN clubs c ON c.id = mg.club_id
         WHERE mg.id = :id
         LIMIT 1',
        ['id' => $mediaId]
    );
}

function find_media_item_or_abort(int $mediaId): array
{
    $item = get_media_item_by_id($mediaId);

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

    return $item;
}

function media_slugify(string $value): string
{
    $value = strtolower(trim($value));
    $value = preg_replace('/[^a-z0-9]+/', '-', $value) ?? '';
    $value = trim($value, '-');

    return $value !== '' ? $value : 'news-post';
}

function unique_news_slug(string $title, ?int $ignoreId = null): string
{
    $baseSlug = media_slugify($title);
    $slug = $baseSlug;
    $counter = 2;

    while (true) {
        $sql = 'SELECT COUNT(*) FROM news_posts WHERE slug = :slug';
        $params = ['slug' => $slug];

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

        if ((int) db_fetch_value($sql, $params, 0) === 0) {
            return $slug;
        }

        $slug = $baseSlug . '-' . $counter;
        $counter++;
    }
}

function validate_news_payload(array $data, array &$errors, ?int $postId = null): array
{
    validate_required($data, [
        'title' => 'Title',
        'body' => 'Body',
    ], $errors);

    validate_in_array_field($data, 'category', news_category_options(), 'Category', $errors);

    if (can_publish_news()) {
        validate_in_array_field($data, 'status', news_status_options(), 'Status', $errors);
    }

    $title = trim((string) ($data['title'] ?? ''));
    $status = can_publish_news() ? (string) ($data['status'] ?? 'draft') : 'draft';
    $existingPost = $postId !== null ? get_news_post_by_id($postId) : null;

    return [
        'title' => $title,
        'slug' => unique_news_slug($title, $postId),
        'category' => (string) ($data['category'] ?? 'general'),
        'body' => trim((string) ($data['body'] ?? '')),
        'status' => $status,
        'published_at' => $status === 'published'
            ? (($existingPost['published_at'] ?? null) ?: date('Y-m-d H:i:s'))
            : null,
        'created_by' => (int) (current_user()['id'] ?? 0) ?: null,
    ];
}

function validate_media_payload(array $data, array &$errors): array
{
    validate_required($data, [
        'title' => 'Title',
        'media_type' => 'Media type',
    ], $errors);
    validate_in_array_field($data, 'media_type', media_type_options(), 'Media type', $errors);

    $normalized = [
        'title' => trim((string) ($data['title'] ?? '')),
        'media_type' => (string) ($data['media_type'] ?? 'image'),
        'fixture_id' => (int) ($data['fixture_id'] ?? 0),
        'club_id' => (int) ($data['club_id'] ?? 0),
    ];

    if ($normalized['fixture_id'] > 0 && db_fetch_one('SELECT id FROM fixtures WHERE id = :id LIMIT 1', ['id' => $normalized['fixture_id']]) === null) {
        $errors['fixture_id'] = 'Selected fixture is invalid.';
    }

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

    $normalized['fixture_id'] = $normalized['fixture_id'] > 0 ? $normalized['fixture_id'] : null;
    $normalized['club_id'] = $normalized['club_id'] > 0 ? $normalized['club_id'] : null;

    return $normalized;
}
