<?php
/**
 * Gutenberg block + shortcode: archive card for a completed tournament (image, standings, link).
 *
 * @package Chess_Podium
 */

if (!defined('ABSPATH')) {
    exit;
}

final class ChessPodium_Tournament_Archive_Card
{
    private const BLOCK_NAME = 'chess-podium/tournament-archive-card';
    private const STYLE_HANDLE = 'chess-podium-archive-card';

    public static function init(): void
    {
        add_action('init', [self::class, 'register_block']);
        add_shortcode('chess_podium_tournament_archive', [self::class, 'render_shortcode']);
    }

    public static function register_block(): void
    {
        if (!function_exists('register_block_type')) {
            return;
        }
        register_block_type(self::BLOCK_NAME, [
            'api_version' => 3,
            'attributes' => [
                'tournamentId' => ['type' => 'integer', 'default' => 0],
                'maxRows' => ['type' => 'integer', 'default' => 10],
                'showImage' => ['type' => 'boolean', 'default' => true],
                'linkMode' => ['type' => 'string', 'default' => 'auto'],
            ],
            'render_callback' => [self::class, 'render_block'],
        ]);
    }

    /**
     * @param array<string, mixed> $attributes
     */
    public static function render_block(array $attributes = []): string
    {
        return self::render_card(
            isset($attributes['tournamentId']) ? (int) $attributes['tournamentId'] : 0,
            isset($attributes['maxRows']) ? (int) $attributes['maxRows'] : 10,
            !empty($attributes['showImage']),
            isset($attributes['linkMode']) ? (string) $attributes['linkMode'] : 'auto'
        );
    }

    /**
     * @param array<string, mixed>|string $atts
     */
    public static function render_shortcode($atts = []): string
    {
        $atts = shortcode_atts([
            'id' => 0,
            'tournament_id' => 0,
            'rows' => 10,
            'show_image' => '1',
            'link' => 'auto',
        ], $atts, 'chess_podium_tournament_archive');
        $tid = (int) ($atts['id'] ?: $atts['tournament_id']);
        $showImage = in_array(strtolower((string) $atts['show_image']), ['0', 'false', 'no', 'off'], true) === false;

        return self::render_card($tid, (int) $atts['rows'], $showImage, (string) $atts['link']);
    }

    /**
     * Tournaments suitable for the block selector (has standings; finished tournaments listed first).
     *
     * @return list<array{id: int, name: string, finished: bool, label: string}>
     */
    public static function get_tournaments_for_editor(): array
    {
        if (!class_exists('ChessPodiumPlugin')) {
            return [];
        }
        $items = [];
        foreach (ChessPodiumPlugin::get_tournaments() as $t) {
            $tid = (int) ($t->id ?? 0);
            if ($tid <= 0) {
                continue;
            }
            $standings = ChessPodiumPlugin::compute_standings($tid);
            if ($standings === []) {
                continue;
            }
            $finished = self::is_tournament_finished($t);
            $name = (string) ($t->name ?? '');
            $suffix = $finished
                ? __('finished', 'chess-podium')
                : __('in progress', 'chess-podium');
            $items[] = [
                'id' => $tid,
                'name' => $name,
                'finished' => $finished,
                'label' => $name . ' (#' . $tid . ' — ' . $suffix . ')',
            ];
        }
        usort($items, static function ($a, $b) {
            if ($a['finished'] !== $b['finished']) {
                return $a['finished'] ? -1 : 1;
            }
            return strcasecmp($a['name'], $b['name']);
        });
        return $items;
    }

    public static function is_tournament_finished(object $tournament): bool
    {
        $total = (int) ($tournament->rounds_total ?? 0);
        $current = (int) ($tournament->current_round ?? 0);
        return $total > 0 && $current >= $total;
    }

    /**
     * Card image: gallery → venue photo → brochure logo → site default.
     */
    public static function get_card_image_url(object $tournament): string
    {
        $tid = (int) ($tournament->id ?? 0);
        if ($tid <= 0 || !class_exists('ChessPodiumPlugin')) {
            return '';
        }
        $photos = ChessPodiumPlugin::get_photos($tid);
        if (!empty($photos[0]->photo_url)) {
            return (string) $photos[0]->photo_url;
        }
        $venue = self::get_venue_photo_url($tid);
        if ($venue !== '') {
            return $venue;
        }
        if (class_exists('ChessPodium_PdfBrochure')) {
            $logo = ChessPodium_PdfBrochure::get_meta($tid, 'brochure_logo');
            if (is_string($logo) && $logo !== '') {
                return $logo;
            }
        }
        return ChessPodiumPlugin::get_default_logo_url();
    }

    private static function get_venue_photo_url(int $tournamentId): string
    {
        if (!class_exists('ChessPodium_PdfBrochure')) {
            return '';
        }
        $brochureMeta = ChessPodium_PdfBrochure::get_all_meta($tournamentId);
        $venuePhotos = isset($brochureMeta['brochure_venue_photos']) ? json_decode((string) $brochureMeta['brochure_venue_photos'], true) : [];
        if (!is_array($venuePhotos) || $venuePhotos === []) {
            return '';
        }
        $first = $venuePhotos[0];
        if (is_string($first)) {
            return $first;
        }
        if (is_array($first) && isset($first['url']) && is_string($first['url'])) {
            return $first['url'];
        }
        return '';
    }

    private static function format_standings_player_cell(array $row): string
    {
        $name = (string) ($row['name'] ?? '');
        $country = isset($row['country']) ? trim((string) $row['country']) : '';
        $rating = isset($row['rating']) ? (int) $row['rating'] : 0;
        $out = '';
        if ($country !== '' && class_exists('ChessPodium_CountryHelper')) {
            $out .= ChessPodium_CountryHelper::render_flag_img($country, $country, 18) . ' ';
        }
        $out .= '<span class="cp-archive-card__player-name">' . esc_html($name) . '</span>';
        if ($rating > 0) {
            $out .= ' <span class="cp-archive-card__player-rating">(' . esc_html((string) $rating) . ')</span>';
        }
        return $out;
    }

    /**
     * @return array{url: string, is_archive: bool}
     */
    public static function resolve_tournament_link(int $tournamentId, string $linkMode, object $tournament): array
    {
        $live = ChessPodiumPlugin::get_public_tournament_view_url($tournamentId);
        $archive = '';
        if (class_exists('ChessPodium_ExportEngine')) {
            $dir = ChessPodium_ExportEngine::get_export_dir($tournament);
            if (file_exists($dir . '/index.html')) {
                $archive = ChessPodium_ExportEngine::get_export_url($tournament) . '/index.html';
            }
        }
        $mode = strtolower(trim($linkMode));
        if ($mode === 'live') {
            return ['url' => $live, 'is_archive' => false];
        }
        if ($mode === 'archive' && $archive !== '') {
            return ['url' => $archive, 'is_archive' => true];
        }
        if ($mode === 'archive' && $archive === '') {
            return ['url' => $live, 'is_archive' => false];
        }
        if ($archive !== '') {
            return ['url' => $archive, 'is_archive' => true];
        }
        return ['url' => $live, 'is_archive' => false];
    }

    private static function render_card(int $tournamentId, int $maxRows, bool $showImage, string $linkMode): string
    {
        if ($tournamentId <= 0 || !class_exists('ChessPodiumPlugin')) {
            return '';
        }
        $tournament = ChessPodiumPlugin::get_tournament($tournamentId);
        if (!$tournament) {
            return '<p class="cp-archive-card-empty">' . esc_html__('Tournament not found.', 'chess-podium') . '</p>';
        }
        $standings = ChessPodiumPlugin::compute_standings($tournamentId);
        if ($standings === []) {
            return '<p class="cp-archive-card-empty">' . esc_html__('No standings for this tournament yet.', 'chess-podium') . '</p>';
        }
        $maxRows = max(3, min(25, $maxRows));
        $slice = array_slice($standings, 0, $maxRows);
        $total = count($standings);
        $link = self::resolve_tournament_link($tournamentId, $linkMode, $tournament);
        $imageUrl = $showImage ? self::get_card_image_url($tournament) : '';
        $city = isset($tournament->city) ? trim((string) $tournament->city) : '';
        $roundsTotal = (int) ($tournament->rounds_total ?? 0);
        $currentRound = (int) ($tournament->current_round ?? 0);
        $metaParts = [];
        if ($city !== '') {
            $metaParts[] = $city;
        }
        if ($roundsTotal > 0) {
            $metaParts[] = sprintf(
                /* translators: 1: current round, 2: total rounds */
                __('Round %1$d / %2$d', 'chess-podium'),
                min($currentRound, $roundsTotal),
                $roundsTotal
            );
        }
        if (self::is_tournament_finished($tournament)) {
            $metaParts[] = __('Final standings', 'chess-podium');
        }

        self::enqueue_card_styles();

        ob_start();
        ?>
        <article class="cp-archive-card" data-cp-archive-card="1">
            <a class="cp-archive-card__link" href="<?php echo esc_url($link['url']); ?>" target="_blank" rel="noopener noreferrer">
                <?php if ($imageUrl !== '') : ?>
                <div class="cp-archive-card__media">
                    <img src="<?php echo esc_url($imageUrl); ?>" alt="<?php echo esc_attr((string) $tournament->name); ?>" loading="lazy" decoding="async">
                </div>
                <?php endif; ?>
                <div class="cp-archive-card__body">
                    <h3 class="cp-archive-card__title"><?php echo esc_html((string) $tournament->name); ?></h3>
                    <?php if ($metaParts !== []) : ?>
                    <p class="cp-archive-card__meta"><?php echo esc_html(implode(' · ', $metaParts)); ?></p>
                    <?php endif; ?>
                    <div class="cp-archive-card__standings-wrap">
                        <table class="cp-archive-card__standings">
                            <thead>
                                <tr>
                                    <th scope="col"><?php esc_html_e('Pos', 'chess-podium'); ?></th>
                                    <th scope="col"><?php esc_html_e('Player', 'chess-podium'); ?></th>
                                    <th scope="col"><?php esc_html_e('Pts', 'chess-podium'); ?></th>
                                </tr>
                            </thead>
                            <tbody>
                                <?php foreach ($slice as $pos => $s) : ?>
                                <tr<?php echo $pos < 3 ? ' class="cp-archive-card__row-top"' : ''; ?>>
                                    <td><?php echo (int) ($pos + 1); ?></td>
                                    <td><?php echo wp_kses_post(self::format_standings_player_cell($s)); ?></td>
                                    <td><?php echo esc_html(number_format((float) ($s['points'] ?? 0), 1)); ?></td>
                                </tr>
                                <?php endforeach; ?>
                            </tbody>
                        </table>
                    </div>
                    <?php if ($total > $maxRows) : ?>
                    <p class="cp-archive-card__more"><?php echo esc_html(sprintf(
                        /* translators: %d: total players */
                        __('+%d more players in full standings', 'chess-podium'),
                        $total - $maxRows
                    )); ?></p>
                    <?php endif; ?>
                    <p class="cp-archive-card__cta">
                        <?php echo $link['is_archive']
                            ? esc_html__('Open published tournament archive', 'chess-podium')
                            : esc_html__('View full tournament page', 'chess-podium'); ?>
                        <span aria-hidden="true">→</span>
                    </p>
                </div>
            </a>
        </article>
        <?php
        return (string) ob_get_clean();
    }

    private static function enqueue_card_styles(): void
    {
        if (wp_style_is(self::STYLE_HANDLE, 'enqueued')) {
            return;
        }
        wp_register_style(self::STYLE_HANDLE, false, [], defined('CHESS_PODIUM_VERSION') ? CHESS_PODIUM_VERSION : '1.9.3');
        wp_enqueue_style(self::STYLE_HANDLE);
        $css = <<<'CSS'
.cp-archive-card{margin:1.5rem 0;font-family:inherit;color:#1e293b;}
.cp-archive-card__link{display:block;text-decoration:none;color:inherit;border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;background:#fff;box-shadow:0 2px 8px rgba(15,23,42,.06);transition:box-shadow .2s ease,transform .2s ease;}
.cp-archive-card__link:hover{box-shadow:0 8px 24px rgba(15,23,42,.12);transform:translateY(-2px);}
.cp-archive-card__media{aspect-ratio:16/9;background:#1e293b;overflow:hidden;}
.cp-archive-card__media img{width:100%;height:100%;object-fit:cover;display:block;}
.cp-archive-card__body{padding:1rem 1.15rem 1.1rem;}
.cp-archive-card__title{margin:0 0 .35rem;font-size:1.2rem;font-weight:700;line-height:1.3;color:#0f172a;}
.cp-archive-card__meta{margin:0 0 .85rem;font-size:.88rem;color:#64748b;}
.cp-archive-card__standings-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;}
.cp-archive-card__standings{width:100%;border-collapse:collapse;font-size:.9rem;}
.cp-archive-card__standings th,.cp-archive-card__standings td{padding:.4rem .5rem;text-align:left;border-bottom:1px solid #f1f5f9;}
.cp-archive-card__standings th{font-size:.75rem;text-transform:uppercase;letter-spacing:.03em;color:#64748b;font-weight:600;}
.cp-archive-card__standings td:last-child,.cp-archive-card__standings th:last-child{text-align:right;font-variant-numeric:tabular-nums;}
.cp-archive-card__row-top td{font-weight:600;}
.cp-archive-card__row-top td:first-child{color:#b45309;}
.cp-archive-card__player-rating{color:#64748b;font-size:.85em;}
.cp-archive-card__more{margin:.5rem 0 0;font-size:.82rem;color:#64748b;}
.cp-archive-card__cta{margin:.85rem 0 0;font-size:.95rem;font-weight:600;color:#1d4ed8;}
.cp-archive-card__link:hover .cp-archive-card__cta{text-decoration:underline;}
.cp-archive-card-empty{color:#64748b;font-style:italic;}
@media (max-width:480px){
.cp-archive-card__title{font-size:1.05rem;}
.cp-archive-card__standings{font-size:.85rem;}
}
CSS;
        wp_add_inline_style(self::STYLE_HANDLE, $css);
    }
}
