<?php
// Public Event Dashboard - No authentication required
include 'includes/db.php';

// Handle AJAX requests
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax'])) {
    header('Content-Type: application/json');
    
    if (isset($_POST['action']) && $_POST['action'] === 'get_events_overview') {
        try {
            // Get all active events with basic info
            $events_stmt = $pdo->prepare("
                SELECT 
                    e.id, e.name, e.date, e.heats_total, e.runs_per_heat, e.status,
                    ehs.heat_number as current_heat, ehs.active_run as current_run,
                    COUNT(DISTINCT ep.id) as total_participants,
                    COUNT(DISTINCT ja.judge_id) as total_judges
                FROM events e
                LEFT JOIN event_participants ep ON e.id = ep.event_id
                LEFT JOIN judge_assignments ja ON e.id = ja.event_id
                LEFT JOIN event_heat_settings ehs ON e.id = ehs.event_id AND ehs.is_active = 1
                WHERE e.status IN ('active', 'upcoming', 'in_progress', 'live')
                GROUP BY e.id, e.name, e.date, e.heats_total, e.runs_per_heat, e.status, ehs.heat_number, ehs.active_run
                ORDER BY e.date DESC, e.name
            ");
            $events_stmt->execute();
            $events = $events_stmt->fetchAll(PDO::FETCH_ASSOC);
            
            // For each event, get additional details
            foreach ($events as &$event) {
                // Get latest score
                $latest_score_stmt = $pdo->prepare("
                    SELECT s.score_value, s.created_at, p.first_name, p.last_name, ep.bib_number
                    FROM scores s
                    JOIN runs r ON s.run_id = r.id
                    JOIN event_participants ep ON r.event_participant_id = ep.id
                    JOIN participants p ON ep.participant_id = p.id
                    WHERE ep.event_id = ?
                    ORDER BY s.created_at DESC
                    LIMIT 1
                ");
                $latest_score_stmt->execute([$event['id']]);
                $event['latest_score'] = $latest_score_stmt->fetch(PDO::FETCH_ASSOC);
                
                // Get current heat participants
                $current_heat_stmt = $pdo->prepare("
                    SELECT COUNT(*) as participants
                    FROM event_participants ep
                    WHERE ep.event_id = ? AND ep.heat_number = ?
                ");
                $current_heat_stmt->execute([$event['id'], $event['current_heat'] ?? 1]);
                $event['current_heat_participants'] = $current_heat_stmt->fetchColumn();
                
                // Get next BIB on start (lowest BIB number in current heat without all scores)
                $next_bib_stmt = $pdo->prepare("
                    SELECT ep.bib_number, p.first_name, p.last_name
                    FROM event_participants ep
                    JOIN participants p ON ep.participant_id = p.id
                    WHERE ep.event_id = ? AND ep.heat_number = ?
                    AND ep.id NOT IN (
                        SELECT DISTINCT r.event_participant_id
                        FROM runs r
                        JOIN scores s ON r.id = s.run_id
                        WHERE r.run_number = ?
                        GROUP BY r.event_participant_id
                        HAVING COUNT(s.id) >= ?
                    )
                    ORDER BY ep.bib_number
                    LIMIT 1
                ");
                $next_bib_stmt->execute([
                    $event['id'], 
                    $event['current_heat'] ?? 1, 
                    $event['current_run'] ?? 1,
                    $event['total_judges']
                ]);
                $event['next_bib'] = $next_bib_stmt->fetch(PDO::FETCH_ASSOC);
            }
            
            echo json_encode([
                'success' => true,
                'events' => $events
            ]);
            
        } catch (Exception $e) {
            echo json_encode([
                'success' => false,
                'message' => 'Database error: ' . $e->getMessage()
            ]);
        }
        exit;
    }
    
    if (isset($_POST['action']) && $_POST['action'] === 'get_event_heats') {
        $event_id = $_POST['event_id'] ?? null;
        
        if ($event_id) {
            try {
                $heats_stmt = $pdo->prepare("
                    SELECT 
                        ehs.id, ehs.event_id, ehs.heat_number, ehs.heat_name, 
                        ehs.scoring_type, ehs.runs_count, ehs.runs_scoring_method,
                        ehs.time_start, ehs.estimate_time_per_participant, ehs.categories,
                        ehs.flow_type, ehs.flow_source_heat, ehs.flow_participants_per_category,
                        ehs.is_active, ehs.active_run, ehs.bib_on_start, ehs.bib_latest_on_run,
                        COUNT(DISTINCT ep.id) as participants,
                        COUNT(DISTINCT s.id) as total_scores,
                        (COUNT(DISTINCT ep.id) * ehs.runs_count * ?) as expected_scores
                    FROM event_heat_settings ehs
                    LEFT JOIN event_participants ep ON ehs.event_id = ep.event_id AND ehs.heat_number = ep.heat_number
                    LEFT JOIN runs r ON ep.id = r.event_participant_id
                    LEFT JOIN scores s ON r.id = s.run_id
                    WHERE ehs.event_id = ?
                    GROUP BY ehs.id, ehs.event_id, ehs.heat_number, ehs.heat_name, 
                             ehs.scoring_type, ehs.runs_count, ehs.runs_scoring_method,
                             ehs.time_start, ehs.estimate_time_per_participant, ehs.categories,
                             ehs.flow_type, ehs.flow_source_heat, ehs.flow_participants_per_category,
                             ehs.is_active, ehs.active_run, ehs.bib_on_start, ehs.bib_latest_on_run
                    ORDER BY ehs.heat_number
                ");
                
                // Get judge count
                $judges_count_stmt = $pdo->prepare("SELECT COUNT(*) FROM judge_assignments WHERE event_id = ?");
                $judges_count_stmt->execute([$event_id]);
                $judges_count = $judges_count_stmt->fetchColumn();
                
                $heats_stmt->execute([$judges_count, $event_id]);
                $heats = $heats_stmt->fetchAll(PDO::FETCH_ASSOC);
                
                // Get configurations for each heat
                $configs_stmt = $pdo->prepare("
                    SELECT id, name, view_type, heat_number, category, display_order
                    FROM result_configurations
                    WHERE event_id = ? AND status = 'active'
                    ORDER BY heat_number, display_order, name
                ");
                $configs_stmt->execute([$event_id]);
                $configurations = $configs_stmt->fetchAll(PDO::FETCH_ASSOC);
                
                echo json_encode([
                    'success' => true,
                    'heats' => $heats,
                    'configurations' => $configurations
                ]);
                
            } catch (Exception $e) {
                echo json_encode([
                    'success' => false,
                    'message' => 'Database error: ' . $e->getMessage()
                ]);
            }
        } else {
            echo json_encode(['success' => false, 'message' => 'Missing event ID']);
        }
        exit;
    }
    
    if (isset($_POST['action']) && $_POST['action'] === 'get_configurations') {
        $event_id = $_POST['event_id'] ?? null;
        
        if ($event_id) {
            try {
                $configs_stmt = $pdo->prepare("
                    SELECT id, name, view_type, heat_number, category, display_order
                    FROM result_configurations
                    WHERE event_id = ? AND status = 'active'
                    ORDER BY display_order, name
                ");
                $configs_stmt->execute([$event_id]);
                $configurations = $configs_stmt->fetchAll(PDO::FETCH_ASSOC);
                
                echo json_encode([
                    'success' => true,
                    'configurations' => $configurations
                ]);
                
            } catch (Exception $e) {
                echo json_encode([
                    'success' => false,
                    'message' => 'Database error: ' . $e->getMessage()
                ]);
            }
        } else {
            echo json_encode(['success' => false, 'message' => 'Missing event ID']);
        }
        exit;
    }
    
    if (isset($_POST['action']) && $_POST['action'] === 'load_summary_table') {
        $config_id = $_POST['config_id'] ?? null;
        
        if ($config_id) {
            try {
                // Get configuration details
                $config_stmt = $pdo->prepare("
                    SELECT * FROM result_configurations WHERE id = ?
                ");
                $config_stmt->execute([$config_id]);
                $config = $config_stmt->fetch(PDO::FETCH_ASSOC);
                
                if ($config) {
                    // Use the same API endpoint as event_start_list.php
                    $configuration = json_decode($config['configuration'], true);
                    
                    // Build API URL with same parameters as event_start_list.php
                    $api_url = "api/summary_table_api.php?event_id=" . $config['event_id'];
                    
                    // Add category filter
                    if ($config['category'] && $config['category'] !== 'all') {
                        $api_url .= "&category=" . urlencode($config['category']);
                    } else {
                        $api_url .= "&category=all";
                    }
                    
                    // Add heat filter if specific heat selected
                    if ($config['heat_number']) {
                        $api_url .= "&heat_run_filter=" . urlencode('{"' . $config['heat_number'] . '":[1,2,3]}');
                    }
                    
                    // Add display options from configuration
                    if ($configuration && isset($configuration['filters'])) {
                        $filters = $configuration['filters'];
                        $api_url .= "&show_runs=" . ($filters['showRuns'] ?? 'true');
                        $api_url .= "&show_judges=" . ($filters['showJudges'] ?? 'false');
                        $api_url .= "&show_control_points=" . ($filters['showControlPoints'] ?? 'false');
                        $api_url .= "&show_heat_best=" . ($filters['showHeatBest'] ?? 'true');
                        $api_url .= "&show_heat_average=" . ($filters['showHeatAverage'] ?? 'false');
                        $api_url .= "&show_overall_best=" . ($filters['showOverallBest'] ?? 'false');
                        $api_url .= "&show_highest_average=" . ($filters['showHighestAverage'] ?? 'false');
                        $api_url .= "&sort=" . ($filters['sortBy'] ?? 'OverallAverage');
                        $api_url .= "&sort_direction=" . ($filters['sortDirection'] ?? 'desc');
                        $api_url .= "&gender=" . ($filters['genderFilter'] ?? 'all');
                    } else {
                        // Default parameters
                        $api_url .= "&show_runs=true&show_judges=false&show_control_points=false";
                        $api_url .= "&show_figures=false&show_heat_best=true&show_heat_average=false";
                        $api_url .= "&show_overall_best=false&show_highest_average=false";
                        $api_url .= "&sort=OverallAverage&sort_direction=desc&gender=all";
                    }
                    
                    // Make internal request to the API for JSON format
                    $full_url = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['REQUEST_URI']) . '/' . $api_url;
                    
                    $json_content = file_get_contents($full_url);
                    $data = json_decode($json_content, true);
                    
                    echo json_encode([
                        'success' => true,
                        'data' => $data,
                        'config_name' => $config['name'],
                        'type' => 'summary_table'
                    ]);
                } else {
                    echo json_encode(['success' => false, 'message' => 'Configuration not found']);
                }
                
            } catch (Exception $e) {
                echo json_encode([
                    'success' => false,
                    'message' => 'Error loading summary table: ' . $e->getMessage()
                ]);
            }
        } else {
            echo json_encode(['success' => false, 'message' => 'Missing configuration ID']);
        }
        exit;
    }
    
    if (isset($_POST['action']) && $_POST['action'] === 'load_start_list') {
        $event_id = $_POST['event_id'] ?? null;
        $heat_number = $_POST['heat_number'] ?? null;
        
        if ($event_id) {
            try {
                // Use the same API endpoint as event_start_list.php
                $api_url = "api/start_list_api.php?event_id=" . $event_id;
                
                // Add heat filter if specified
                if ($heat_number) {
                    $api_url .= "&heat_number=" . $heat_number;
                }
                
                // Add format parameter for HTML (same as event_start_list.php)
                $api_url .= "&format=html";
                
                // Make internal request to the API
                $full_url = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['REQUEST_URI']) . '/' . $api_url;
                
                $html_content = file_get_contents($full_url);
                
                // Also get JSON data for processing
                $json_url = str_replace('&format=html', '&format=json', $full_url);
                $json_content = file_get_contents($json_url);
                $json_data = json_decode($json_content, true);
                
                echo json_encode([
                    'success' => true,
                    'data' => $json_data,
                    'html_content' => $html_content,
                    'heat_number' => $heat_number,
                    'type' => 'start_list'
                ]);
                
            } catch (Exception $e) {
                echo json_encode([
                    'success' => false,
                    'message' => 'Error loading start list: ' . $e->getMessage()
                ]);
            }
        } else {
            echo json_encode(['success' => false, 'message' => 'Missing event ID']);
        }
        exit;
    }
    
    // If no action matched, return error
    echo json_encode(['success' => false, 'message' => 'Invalid action']);
    exit;
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Live Event Dashboard</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<!-- style skin holder -->
    
    <style>
        /* Apply consistent table styling */
        .table th {
            background-color: #343a40 !important;
            color: white !important;
            border-color: #454d55 !important;
            white-space: nowrap;
            position: sticky;
            top: 0;
            z-index: 10;
        }
        
        .table td {
            border-color: #dee2e6;
        }
        
        .table-striped > tbody > tr:nth-of-type(odd) > td {
            background-color: rgba(0,0,0,.05);
        }
        
        .table-hover > tbody > tr:hover > td {
            background-color: rgba(0,0,0,.075);
        }
        
        .summary-stats .badge {
            font-size: 0.75em;
        }
        
        /* Table responsive with max height */
        .table-responsive {
            max-height: 60vh;
            overflow-y: auto;
            border: 1px solid #dee2e6;
            border-radius: 6px;
        }
    </style>
</head>

<body class="body-bg-aurora-bright">
    <!-- Auto-refresh indicator -->
    <div class="auto-refresh-indicator">
        <div class="badge bg-success" id="refreshIndicator">
            <i class="fas fa-sync-alt me-1"></i>Auto-refresh: ON
        </div>
    </div>

    <div class="container-fluid container-StyleScore p-4">
        <div class="row mb-4">
            <div class="col-12">
                <div class="border-0 shadow-none card bg-primary text-white">
                    <div class="border-0 shadow-none card-body">
                        <div class="d-flex justify-content-between align-items-center">
                            <div>
                                <h1 class="card-title mb-1"><i class="fas fa-tv me-2"></i>Live Event Dashboard</h1>
                                <p class="card-text mb-0">Real-time event monitoring and results</p>
                            </div>
                            <div class="text-end">
                                <div class="btn-group" role="group">
                                    <button type="button" class="btn btn-outline-light" id="toggleRefresh"><i class="fas fa-pause me-1"></i>Pause Updates</button>
                                    <button type="button" class="btn btn-outline-light" onclick="refreshAllData()"><i class="fas fa-sync-alt me-1"></i>Refresh Now</button>
                                </div>
                                <div class="mt-2"><small>Last updated: <span id="lastUpdate">Loading...</span></small></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div id="eventsContainer">
            <div class="col-12 text-center py-5">
                <div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading events...</span></div>
                <p class="mt-3">Loading events...</p>
            </div>
        </div>

        <div class="modal fade" id="summaryTableModal" tabindex="-1">
            <div class="modal-dialog modal-xl">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title" id="modalSummaryTitle">Summary Table</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                    </div>
                    <div class="modal-body">
                        <div class="summary-display" id="summaryTableDisplay"></div>
                    </div>
                </div>
            </div>
        </div>
    </div>
<!-- Alpine Plugins -->
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/morph@3.x.x/dist/cdn.min.js"></script>
 
<!-- Alpine Core -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
     <script>
        // Minimal helper to patch only changed DOM instead of full re-render
        function morphHtml(targetEl, html) {
            if (!targetEl) return;
            // morphdom can take an HTML string; childrenOnly avoids touching the container element itself
            window.morphdom ? morphdom(targetEl, html, { childrenOnly: true }) : (targetEl.innerHTML = html);
        }
        let autoRefresh = true;
        let refreshInterval;
        let currentEventId = null;
        let currentConfigId = null;
        let openHeatContainers = new Set(); // Track which heat containers are open
        let activeReports = new Map(); // Track active reports in heat cards
        
        document.addEventListener('DOMContentLoaded', function() {
            // Start auto-refresh
            startAutoRefresh();
            
            // Initial load
            refreshAllData();
            
            // Toggle refresh button
            document.getElementById('toggleRefresh').addEventListener('click', function() {
                if (autoRefresh) {
                    stopAutoRefresh();
                    this.innerHTML = '<i class="fas fa-play me-1"></i>Resume Updates';
                    document.getElementById('refreshIndicator').innerHTML = '<i class="fas fa-pause me-1"></i>Auto-refresh: OFF';
                    document.getElementById('refreshIndicator').className = 'badge bg-warning';
                } else {
                    startAutoRefresh();
                    this.innerHTML = '<i class="fas fa-pause me-1"></i>Pause Updates';
                    document.getElementById('refreshIndicator').innerHTML = '<i class="fas fa-sync-alt me-1"></i>Auto-refresh: ON';
                    document.getElementById('refreshIndicator').className = 'badge bg-success';
                }
                autoRefresh = !autoRefresh;
            });
        });
        
        function startAutoRefresh() {
            refreshInterval = setInterval(function() {
                refreshAllData();
                if (currentConfigId) {
                    refreshSummaryTable();
                }
            }, 30000); // Refresh every 30 seconds
        }
        
        function stopAutoRefresh() {
            if (refreshInterval) {
                clearInterval(refreshInterval);
            }
        }
        
        function refreshAllData() {
            loadEventsOverview();
            updateLastUpdateTime();
        }
        
        function updateLastUpdateTime() {
            document.getElementById('lastUpdate').textContent = new Date().toLocaleTimeString();
        }
        
        function loadEventsOverview() {
            fetch(window.location.href, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: 'ajax=1&action=get_events_overview'
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    displayEvents(data.events);
                } else {
                    console.error('Error loading events:', data.message);
                    morphHtml(document.getElementById('eventsContainer'),
                        '<div class="col-12 py-4"><div class="alert alert-danger">Error loading events: ' + data.message + '</div></div>');
                }
            })
            .catch(error => {
                console.error('Error:', error);
                morphHtml(document.getElementById('eventsContainer'),
                    '<div class="col-12 py-4"><div class="alert alert-danger">Network error loading events</div></div>');
            });
        }
        
        function displayEvents(events) {
            const container = document.getElementById('eventsContainer');
            // Preserve existing heat container contents for open events to avoid flicker & reload delay
            const existingHeats = {};
            openHeatContainers.forEach(id => {
                const el = document.getElementById('heats-' + id);
                if (el) existingHeats[id] = el.innerHTML;
            });

            if (events.length === 0) {
                morphHtml(container, '<div class="col-12 py-4"><div class="alert alert-info">No active events found</div></div>');
                return;
            }

            let html = '';
            events.forEach(event => {
                const isLive = ['in_progress','live'].includes(event.status);
                const latestScore = event.latest_score;
                const nextBip = event.next_bib;
                const isHeatContainerOpen = openHeatContainers.has(event.id);
                html += `
                <div class="border-0 shadow-none card mb-4" id="event-${event.id}">
                    <div class="border-0 shadow-none card-header d-flex justify-content-between align-items-center">
                        <div>
                            <h5 class="mb-0"><i class="fas fa-calendar-alt me-2"></i>${event.name}</h5>
                            <small class="text-muted">Event Date: ${new Date(event.date).toLocaleDateString()}</small>
                        </div>
                        <div class="text-end">
                            ${isLive ? '<span class="badge bg-danger me-2"><i class="fas fa-circle me-1"></i>LIVE</span>' : ''}
                            <span class="badge bg-secondary">${event.status.replace('_',' ').toUpperCase()}</span>
                        </div>
                    </div>
                    <div class="border-0 shadow-none card-body">
                        <div class="row g-3 mb-3">
                            <div class="col-6 col-md-3"><div class="text-center"><div class="fw-bold">${event.current_heat || '—'}</div><small class="text-muted">Active Heat</small></div></div>
                            <div class="col-6 col-md-3"><div class="text-center"><div class="fw-bold">${event.current_run || '—'}</div><small class="text-muted">Current Run</small></div></div>
                            <div class="col-6 col-md-3"><div class="text-center"><div class="fw-bold">${event.total_participants || 0}</div><small class="text-muted">Participants</small></div></div>
                            <div class="col-6 col-md-3"><div class="text-center"><div class="fw-bold">${event.total_judges || 0}</div><small class="text-muted">Judges</small></div></div>
                        </div>
                        <div class="row g-3 mb-3">
                            <div class="col-md-6">
                                ${latestScore ? `
                                <div class="col-md-12"><div class="alert alert-light mb-0"><strong><i class=\"fas fa-trophy me-1\"></i>Latest Score:</strong><br><strong>${latestScore.score_value}</strong> - BIB ${latestScore.bib_number} (${latestScore.first_name} ${latestScore.last_name})<br><small class=\"text-muted\">${new Date(latestScore.created_at).toLocaleTimeString()}</small></div></div>` : ''}
                                ${nextBip ? `
                                <div class="col-md-12"><div class="alert alert-warning mb-0"><strong><i class=\"fas fa-play me-1\"></i>Next on Start:</strong><br>BIB ${nextBip.bib_number} - ${nextBip.first_name} ${nextBip.last_name}</div></div>` : ''}
                            </div>
                            <div class="col-md-6" id="load-heats-${event.id}">
                            <!-- active heat card  -->
                            </div>
                        </div>
                        <div class="text-center">
                            <button class="btn btn-primary" onclick="loadEventHeats(${event.id}, '${event.name.replace(/'/g,"&apos;")}')"><i class="fas fa-fire me-1"></i>${isHeatContainerOpen ? 'Hide' : 'Load'} Heat Details</button>
                        </div>
                    </div>
                </div>
                <div id="heats-${event.id}" class="mb-4" style="display:${isHeatContainerOpen ? 'block' : 'none'};">
                    ${isHeatContainerOpen ? (existingHeats[event.id] || "<div class='text-center py-3'><div class='spinner-border' role='status'></div><p class='mt-2'>Loading heat details...</p></div>") : ''}
                </div>`;
            });

            morphHtml(container, html);

            // Reload heat details for open containers (if they were not preserved or need refresh)
            openHeatContainers.forEach(eventId => {
                const event = events.find(e => e.id == eventId);
                if (event) {
                    // Only trigger refresh if preserved content looks like loading or empty
                    const el = document.getElementById('heats-' + eventId);
                    if (el && /Loading heat details|Refreshing heat details|spinner/.test(el.innerHTML)) {
                        loadEventHeatsData(eventId, event.name);
                    }
                }
            });
        }
        
        function showEventDetails(eventId, eventName) {
            // This function is kept for backward compatibility but redirects to loadEventHeats
            loadEventHeats(eventId, eventName);
        }
        
        function loadEventHeats(eventId, eventName) {
            const container = document.getElementById(`heats-${eventId}`);
            if (container.style.display === 'none') {
                openHeatContainers.add(eventId);
                container.style.display = 'block';
                loadEventHeatsData(eventId, eventName);
            } else {
                openHeatContainers.delete(eventId);
                activeReports.delete(`${eventId}`);
                container.style.display = 'none';
            }
        }
        
        function loadEventHeatsData(eventId, eventName) {
            const container = document.getElementById(`heats-${eventId}`);
            morphHtml(container, '<div class="text-center py-3"><div class="spinner-border" role="status"></div><p class="mt-2">Loading heat details...</p></div>');
            
            fetch(window.location.href, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: `ajax=1&action=get_event_heats&event_id=${eventId}`
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    displayHeats(eventId, data.heats, data.configurations);
                } else {
                    morphHtml(container, '<div class="alert alert-danger">Error loading heats: ' + data.message + '</div>');
                }
            })
            .catch(error => {
                console.error('Error:', error);
                morphHtml(container, '<div class="alert alert-danger">Network error loading heats</div>');
            });
        }
        
        function displayHeats(eventId, heats, configurations) {
            const container = document.getElementById(`heats-${eventId}`);
            
            if (heats.length === 0) {
                morphHtml(container, '<div class="alert alert-info">No heats configured for this event</div>');
                return;
            }
            
            // Group configurations by heat
            const configsByHeat = {};
            configurations.forEach(config => {
                const heatNum = config.heat_number || 'all';
                if (!configsByHeat[heatNum]) configsByHeat[heatNum] = [];
                configsByHeat[heatNum].push(config);
            });
            
            let html = '<h5 class="text-uppercase text-muted small"><i class="fas fa-fire me-1"></i> Heat Details & Flow</h5>';
            
            // Create heat flow visualization
            if (heats.length > 1) {
                html += '<div class="d-flex flex-wrap align-items-center mb-3">';
                
                heats.forEach((heat, index) => {
                    const flowClass = `flow-${heat.flow_type}`;
                    html += `
                        <div class="flow-indicator ${flowClass}">
                            Heat ${heat.heat_number}: ${heat.heat_name}
                        </div>
                    `;
                    
                    if (index < heats.length - 1) {
                        html += '<i class="fas fa-arrow-right mx-2 text-muted"></i>';
                    }
                });
                
                html += '</div>';
            }
            
            heats.forEach(heat => {
                const completion = heat.expected_scores > 0 ? Math.round((heat.total_scores / heat.expected_scores) * 100) : 0;
                const progressClass = completion >= 100 ? 'bg-success' : (completion >= 50 ? 'bg-warning' : 'bg-primary');
                
                let heatStatusBadge = '<span class="badge bg-secondary">Upcoming</span>';
                if (heat.is_active == 1) heatStatusBadge = '<span class="badge bg-danger">Live</span>';
                else if (completion >= 100) heatStatusBadge = '<span class="badge bg-success">Completed</span>';
                
                const categories = heat.categories ? JSON.parse(heat.categories) : [];
                const flowSourceText = heat.flow_source_heat ? `from Heat ${heat.flow_source_heat}` : 'direct entry';
                
                html += `
                    <div class="border-0 shadow-none card mb-3" id="heat-${eventId}-${heat.heat_number}">
                        <div class="border-0 shadow-none card-body">
                            <div class="d-flex justify-content-between align-items-start flex-wrap gap-2">
                                <div>
                                    <h6 class="mb-1">Heat ${heat.heat_number}: ${heat.heat_name} ${heat.is_active == 1 ? '<i class="fas fa-circle text-danger"></i>' : ''}</h6>
                                    <small class="text-muted">${heat.time_start ? new Date('1970-01-01T' + heat.time_start).toLocaleTimeString([], {hour:'2-digit',minute:'2-digit'}) : 'No start time'} • ${heat.scoring_type} • ${heat.runs_scoring_method.replace('_',' ')}</small>
                                </div>
                                <div class="text-end">
                                    <div class="mb-1"><span class="badge bg-secondary me-2">${heat.participants || 0} participants</span>${heatStatusBadge}</div>
                                    <div class="progress" style="width:160px; height:8px;"><div class="progress-bar ${progressClass}" style="width:${completion}%"></div></div>
                                    <small class="text-muted">${completion}% complete</small>
                                </div>
                            </div>
                            <div class="row mt-3 g-3">
                                <div class="col-lg-8">
                                    <div class="row g-2">
                                        <div class="col-6"><small><strong>Runs:</strong> ${heat.runs_count}</small></div>
                                        <div class="col-6"><small><strong>Flow:</strong> ${heat.flow_type}</small></div>
                                        ${heat.flow_type !== 'none' ? `<div class='col-12'><small><strong>Source:</strong> ${flowSourceText}</small></div>` : ''}
                                        ${heat.is_active == 1 ? `<div class='col-6'><small><strong>Active Run:</strong> ${heat.active_run || 1}</small></div>` : ''}
                                        ${heat.is_active == 1 && heat.bib_on_start ? `<div class='col-6'><small><strong>BIB Start:</strong> ${heat.bib_on_start}</small></div>` : ''}
                                        ${heat.is_active == 1 && heat.bib_latest_on_run ? `<div class='col-6'><small><strong>Latest BIB:</strong> ${heat.bib_latest_on_run}</small></div>` : ''}
                                    </div>
                                    ${categories.length > 0 ? `<div class="mt-2">${categories.map(cat => `<span class='badge bg-light text-dark me-1 mb-1'>${cat}</span>`).join('')}</div>` : ''}
                                </div>
                                <div class="col-lg-4">
                                    <p class="text-muted text-uppercase small mb-2"><i class="fas fa-chart-bar me-1"></i> Reports</p>
                                    ${configsByHeat[heat.heat_number] ? configsByHeat[heat.heat_number].map(config => `
                                        <div class='d-flex justify-content-between align-items-center border rounded p-2 mb-2'>
                                            <div class='me-2'>
                                                <strong class='small d-block'>${config.name}</strong>
                                                <span class='badge ${config.view_type === 'start_list' ? 'bg-info' : 'bg-success'}'>${config.view_type.replace('_',' ')}</span>
                                                ${config.category && config.category !== 'all' ? `<small class='text-muted'> • ${config.category}</small>` : ''}
                                            </div>
                                            <div>
                                                ${config.view_type === 'summary_table' ? `
                                                    <button class='btn btn-sm btn-success' onclick="loadSummaryTableCard(${eventId}, ${heat.heat_number}, ${config.id}, '${config.name.replace(/'/g,"&apos;")}')"><i class='fas fa-eye'></i></button>` : `
                                                    <button class='btn btn-sm btn-info' onclick="loadStartListCard(${eventId}, ${heat.heat_number})"><i class='fas fa-list'></i></button>`}
                                            </div>
                                        </div>`).join('') : '<div class="text-muted small">No heat-specific reports</div>'}
                                    ${configsByHeat['all'] ? `<p class='text-muted small text-uppercase mt-3 mb-1'>General:</p>${configsByHeat['all'].map(config => `
                                        <div class='d-flex justify-content-between align-items-center border rounded p-2 mb-2'>
                                            <div class='me-2'>
                                                <strong class='small d-block'>${config.name}</strong>
                                                <span class='badge ${config.view_type === 'start_list' ? 'bg-info' : 'bg-success'}'>${config.view_type.replace('_',' ')}</span>
                                            </div>
                                            <div>
                                                ${config.view_type === 'summary_table' ? `<button class='btn btn-sm btn-success' onclick=\"loadSummaryTableCard(${eventId}, null, ${config.id}, '${config.name.replace(/'/g,"&apos;")}' )\"><i class='fas fa-eye'></i></button>` : `<button class='btn btn-sm btn-info' onclick=\"loadStartListCard(${eventId}, null)\"><i class='fas fa-list'></i></button>`}
                                            </div>
                                        </div>`).join('')}` : ''}
                                </div>
                            </div>
                            <div id="report-cards-${eventId}-${heat.heat_number}" class="mt-3"></div>
                        </div>
                    </div>
                `;
            });
            
            morphHtml(container, html);
            
            // Restore active reports
            activeReports.forEach((reportData, key) => {
                if (key.startsWith(`${eventId}-`)) {
                    const parts = key.split('-');
                    const heatNum = parts[1];
                    
                    // Handle 'all' case - try to find first available container
                    let reportContainer;
                    if (heatNum === 'all') {
                        const eventContainers = document.querySelectorAll(`[id^="report-cards-${eventId}-"]`);
                        if (eventContainers.length > 0) {
                            reportContainer = eventContainers[0];
                        }
                    } else {
                        reportContainer = document.getElementById(`report-cards-${eventId}-${heatNum}`);
                    }
                    
                    if (reportContainer && reportData.html) {
                        morphHtml(reportContainer, reportData.html);
                    }
                }
            });
        }
        
        function loadSummaryTableCard(eventId, heatNumber, configId, configName) {
            // Handle null heat number case - use 'all' as key for general reports
            const reportKey = `${eventId}-${heatNumber || 'all'}`;
            const containerSelector = heatNumber ? `report-cards-${eventId}-${heatNumber}` : `report-cards-${eventId}-all`;
            const container = document.getElementById(containerSelector);
            
            // If container doesn't exist, try to find the first available container for this event
            let actualContainer = container;
            if (!actualContainer && !heatNumber) {
                // For general reports, use the first heat container
                const eventContainers = document.querySelectorAll(`[id^="report-cards-${eventId}-"]`);
                if (eventContainers.length > 0) {
                    actualContainer = eventContainers[0];
                } else {
                    console.error('No container found for event', eventId);
                    return;
                }
            }
            
            if (!actualContainer) {
                console.error('Container not found:', containerSelector);
                return;
            }
            
            // Check if this report is already active
            if (activeReports.has(reportKey)) {
                // Close the report
                activeReports.delete(reportKey);
                morphHtml(actualContainer, '');
                return;
            }
            
            // Store configId for refresh functionality
            window.lastConfigId = configId;
            
            // Show loading
            morphHtml(actualContainer, `
                <div class="border-0 shadow-none card mb-3">
                    <div class="border-0 shadow-none card-header d-flex justify-content-between align-items-center">
                        <h6 class="mb-0"><i class="fas fa-table me-2"></i>${configName}</h6>
                        <button class="btn btn-sm btn-outline-danger" onclick="closeReportCard(${eventId}, ${heatNumber || "'all'"})"><i class="fas fa-times"></i></button>
                    </div>
                    <div class="border-0 shadow-none card-body text-center">
                        <div class="spinner-border" role="status"></div>
                        <p class="mt-2 mb-0">Loading summary table...</p>
                    </div>
                </div>`);
            
            fetch(window.location.href, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: `ajax=1&action=load_summary_table&config_id=${configId}`
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    const html = convertSummaryTableToHTML(data.data, configName, eventId, heatNumber);
                    morphHtml(actualContainer, html);
                    activeReports.set(reportKey, { html: html, type: 'summary_table', configId: configId, configName: configName });
                } else {
                    morphHtml(actualContainer, `
                        <div class="border-0 shadow-none card mb-3"><div class="border-0 shadow-none card-header d-flex justify-content-between align-items-center"><h6 class="mb-0"><i class="fas fa-table me-2"></i>${configName}</h6><button class="btn btn-sm btn-outline-danger" onclick="closeReportCard(${eventId}, ${heatNumber || "'all'"})"><i class="fas fa-times"></i></button></div><div class="border-0 shadow-none card-body"><div class="alert alert-danger">Error: ${data.message}</div></div></div>
                    `);
                }
            })
            .catch(error => {
                console.error('Error:', error);
                morphHtml(actualContainer, `
                    <div class="border-0 shadow-none card mb-3"><div class="border-0 shadow-none card-header d-flex justify-content-between align-items-center"><h6 class="mb-0"><i class="fas fa-table me-2"></i>${configName}</h6><button class="btn btn-sm btn-outline-danger" onclick="closeReportCard(${eventId}, ${heatNumber || "'all'"})"><i class="fas fa-times"></i></button></div><div class="border-0 shadow-none card-body"><div class="alert alert-danger">Network error loading summary table</div></div></div>
                `);
            });
        }
        
        function refreshSummaryTableCard(eventId, heatNumber, configId, configName) {
            // Simply reload the summary table card
            loadSummaryTableCard(eventId, heatNumber, configId, configName);
        }
        
        function loadStartListCard(eventId, heatNumber) {
            // Handle null heat number case - use 'all' as key for general reports
            const reportKey = `${eventId}-${heatNumber || 'all'}`;
            const containerSelector = heatNumber ? `report-cards-${eventId}-${heatNumber}` : `report-cards-${eventId}-all`;
            const container = document.getElementById(containerSelector);
            const heatText = heatNumber ? `Heat ${heatNumber}` : 'All Heats';
            
            // If container doesn't exist, try to find the first available container for this event
            let actualContainer = container;
            if (!actualContainer && !heatNumber) {
                // For "All Heats" reports, use the first heat container or create a general one
                const eventContainers = document.querySelectorAll(`[id^="report-cards-${eventId}-"]`);
                if (eventContainers.length > 0) {
                    actualContainer = eventContainers[0];
                } else {
                    console.error('No container found for event', eventId);
                    return;
                }
            }
            
            if (!actualContainer) {
                console.error('Container not found:', containerSelector);
                return;
            }
            
            // Check if this report is already active
            if (activeReports.has(reportKey)) {
                // Close the report
                activeReports.delete(reportKey);
                morphHtml(actualContainer, '');
                return;
            }
            
            // Show loading
            morphHtml(actualContainer, `
                <div class="border-0 shadow-none card mb-3">
                    <div class="border-0 shadow-none card-header d-flex justify-content-between align-items-center">
                        <h6 class="mb-0"><i class="fas fa-list me-2"></i>Start List - ${heatText}</h6>
                        <button class="btn btn-sm btn-outline-danger" onclick="closeReportCard(${eventId}, ${heatNumber || "'all'"})"><i class="fas fa-times"></i></button>
                    </div>
                    <div class="border-0 shadow-none card-body text-center">
                        <div class="spinner-border" role="status"></div>
                        <p class="mt-2 mb-0">Loading start list...</p>
                    </div>
                </div>`);
            
            fetch(window.location.href, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: `ajax=1&action=load_start_list&event_id=${eventId}${heatNumber ? '&heat_number=' + heatNumber : ''}`
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    const html = convertStartListToHTML(data.data, heatText, eventId, heatNumber);
                    morphHtml(actualContainer, html);
                    activeReports.set(reportKey, { html: html, type: 'start_list' });
                } else {
                    morphHtml(actualContainer, `
                        <div class="border-0 shadow-none card mb-3"><div class="border-0 shadow-none card-header d-flex justify-content-between align-items-center"><h6 class="mb-0"><i class="fas fa-list me-2"></i>Start List - ${heatText}</h6><button class="btn btn-sm btn-outline-danger" onclick="closeReportCard(${eventId}, ${heatNumber || "'all'"})"><i class="fas fa-times"></i></button></div><div class="border-0 shadow-none card-body"><div class="alert alert-danger">Error: ${data.message}</div></div></div>
                    `);
                }
            })
            .catch(error => {
                console.error('Error:', error);
                morphHtml(actualContainer, `
                    <div class="border-0 shadow-none card mb-3"><div class="border-0 shadow-none card-header d-flex justify-content-between align-items-center"><h6 class="mb-0"><i class="fas fa-list me-2"></i>Start List - ${heatText}</h6><button class="btn btn-sm btn-outline-danger" onclick="closeReportCard(${eventId}, ${heatNumber || "'all'"})"><i class="fas fa-times"></i></button></div><div class="border-0 shadow-none card-body"><div class="alert alert-danger">Network error loading start list</div></div></div>
                `);
            });
        }
        
        function convertSummaryTableToHTML(data, configName, eventId, heatNumber) {
            if (!data || !data.success) {
                return `
                    <div class="report-panel"><div class="report-panel-head"><h6><i class="fas fa-table"></i> ${configName}</h6><div class="panel-actions"><button class="danger" onclick="closeReportCard(${eventId}, ${heatNumber})"><i class="fas fa-times"></i></button></div></div><div class="report-panel-body"><div class="no-data-note">No results available</div></div></div>
                `;
            }
            
            // Use the table_head and table_body from the API response (same as event_start_list.php)
            let tableContent = '';
            
            if (data.table_head && data.table_body) {
                // Apply consistent styling (same as event_start_list.php)
                let styledTableHead = data.table_head.replace(/<table[^>]*>/g, '<table class="table table-striped table-hover">');
                
                tableContent = `
                    <div>
                        <div class="d-flex justify-content-between align-items-center mb-2">
                            <h5 class="mb-0" style="font-size:1rem;">Summary Results</h5>
                            <div>
                                <span class="badge bg-primary me-2">${data.participant_count || 0} Participants</span>
                                ${data.is_grouped ? '<span class="badge bg-info text-dark">Grouped</span>' : ''}
                            </div>
                        </div>
                        ${data.filter_summary ? `<div class="text-muted small mb-2">${data.filter_summary}</div>` : ''}
                        <div class="table-responsive">
                            <style>${data.table_badge_colors || ''}</style>
                            <table class="table table-striped table-hover mb-0">
                                ${styledTableHead || ''}
                                ${data.table_body || ''}
                            </table>
                        </div>
                    </div>
                `;
            } else {
                tableContent = '<div class="alert alert-info">No summary data available</div>';
            }
            
            // Store the config ID for refresh functionality
            const configId = window.lastConfigId || 'unknown';
            
            return `
                <div class="border-0 shadow-none card mb-3">
                    <div class="border-0 shadow-none card-header d-flex justify-content-between align-items-center">
                        <h6 class="mb-0"><i class="fas fa-table me-2"></i>${configName}</h6>
                        <div>
                            <button class="btn btn-sm btn-outline-secondary me-2" onclick="refreshSummaryTableCard(${eventId}, ${heatNumber}, ${configId}, '${configName}')"><i class="fas fa-sync-alt"></i></button>
                            <button class="btn btn-sm btn-outline-danger" onclick="closeReportCard(${eventId}, ${heatNumber})"><i class="fas fa-times"></i></button>
                        </div>
                    </div>
                    <div class="border-0 shadow-none card-body">${tableContent}</div>
                </div>
            `;
        }
        
        function convertStartListToHTML(data, heatText, eventId, heatNumber) {
            // Check if we have HTML content from the API (same as event_start_list.php)
            let listContent = '';
            
            if (data && data.html_content) {
                // Use the HTML content directly from the API
                listContent = data.html_content;
            } else if (data && data.participants && data.participants.length > 0) {
                // Fallback to manual generation if HTML not available
                let listHTML = '';
                data.participants.forEach(participant => {
                    listHTML += `
                        <div class="start-list-item">
                            <div>
                                <span class="bib-number">BIB ${participant.bib_number}</span>
                                <strong>${participant.first_name} ${participant.last_name}</strong>
                                <br><small class="text-muted">${participant.category || 'No category'}</small>
                            </div>
                            <div class="text-end">
                                ${participant.club ? `<small>${participant.club}</small><br>` : ''}
                                <small class="text-muted">Heat ${participant.heat_number || 'N/A'}</small>
                            </div>
                        </div>
                    `;
                });
                listContent = listHTML;
            } else {
                listContent = '<div class="alert alert-info mb-0">No participants found for this selection</div>';
            }
            
            return `
                <div class="border-0 shadow-none card mb-3">
                    <div class="border-0 shadow-none card-header d-flex justify-content-between align-items-center">
                        <h6 class="mb-0"><i class="fas fa-list me-2"></i>Start List - ${heatText}</h6>
                        <div>
                            <button class="btn btn-sm btn-outline-secondary me-2" onclick="refreshStartListCard(${eventId}, ${heatNumber})"><i class="fas fa-sync-alt"></i></button>
                            <button class="btn btn-sm btn-outline-danger" onclick="closeReportCard(${eventId}, ${heatNumber})"><i class="fas fa-times"></i></button>
                        </div>
                    </div>
                    <div class="border-0 shadow-none card-body">${listContent}</div>
                </div>
            `;
        }
        
        function refreshStartListCard(eventId, heatNumber) {
            // Simply reload the start list card
            loadStartListCard(eventId, heatNumber);
        }
        
        function closeReportCard(eventId, heatNumber) {
            const reportKey = `${eventId}-${heatNumber || 'all'}`;
            activeReports.delete(reportKey);
            
            const containerSelector = heatNumber && heatNumber !== 'all' ? `report-cards-${eventId}-${heatNumber}` : `report-cards-${eventId}-all`;
            let container = document.getElementById(containerSelector);
            
            // If container doesn't exist, try to find it by other means
            if (!container && (heatNumber === null || heatNumber === 'all')) {
                const eventContainers = document.querySelectorAll(`[id^="report-cards-${eventId}-"]`);
                if (eventContainers.length > 0) {
                    container = eventContainers[0];
                }
            }
            
            if (container) {
                morphHtml(container, '');
            }
        }
        
        function loadSummaryTable(configId, configName) {
            // Backward compatibility - opens in modal (uses same API as event_start_list.php)
            currentConfigId = configId;
            document.getElementById('modalSummaryTitle').textContent = configName;
            morphHtml(document.getElementById('summaryTableDisplay'),
                '<div class="text-center py-3"><div class="spinner-border" role="status"></div><p class="mt-2">Loading summary table...</p></div>');
            
            // Show modal
            const modal = new bootstrap.Modal(document.getElementById('summaryTableModal'));
            modal.show();
            
            fetch(window.location.href, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: `ajax=1&action=load_summary_table&config_id=${configId}`
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    // Use the API response format (same as event_start_list.php)
                    let tableContent = '';
                    
                    if (data.data && data.data.table_head && data.data.table_body) {
                        let styledTableHead = data.data.table_head.replace(
                            /<table[^>]*>/g, 
                            '<table class="table table-striped table-hover">'
                        );
                        
                        tableContent = `
                            <div class="summary-table-section">
                                <div class="summary-header mb-3">
                                    <div class="d-flex justify-content-between align-items-center">
                                        <h5 class="mb-0">Summary Results</h5>
                                        <div class="summary-stats">
                                            <span class="badge bg-primary me-2">${data.data.participant_count || 0} Participants</span>
                                            ${data.data.is_grouped ? '<span class="badge bg-info">Grouped by Category</span>' : ''}
                                        </div>
                                    </div>
                                    ${data.data.filter_summary ? `<small class="text-muted">${data.data.filter_summary}</small>` : ''}
                                </div>
                                <div class="table-responsive">
                                    <style>${data.data.table_badge_colors || ''}</style>
                                    <table class="table table-striped table-hover">
                                        ${styledTableHead || ''}
                                        ${data.data.table_body || ''}
                                    </table>
                                </div>
                            </div>
                        `;
                    } else {
                        tableContent = '<div class="alert alert-info">No summary data available</div>';
                    }
                    
                    morphHtml(document.getElementById('summaryTableDisplay'), tableContent);
                } else {
                    morphHtml(document.getElementById('summaryTableDisplay'),
                        '<div class="alert alert-danger">Error loading summary table: ' + data.message + '</div>');
                }
            })
            .catch(error => {
                console.error('Error:', error);
                morphHtml(document.getElementById('summaryTableDisplay'),
                    '<div class="alert alert-danger">Network error loading summary table</div>');
            });
        }
        
        function refreshSummaryTable() {
            if (currentConfigId) {
                const configName = document.getElementById('modalSummaryTitle').textContent;
                loadSummaryTable(currentConfigId, configName);
            }
        }
        
        function closeSummaryTable() {
            const modal = bootstrap.Modal.getInstance(document.getElementById('summaryTableModal'));
            if (modal) modal.hide();
            currentConfigId = null;
        }
        
        function loadStartList(eventId, heatNumber) {
            // Backward compatibility - opens in new tab
            const url = `api/start_list_api.php?event_id=${eventId}${heatNumber ? '&heat_number=' + heatNumber : ''}&format=html`;
            window.open(url, '_blank');
        }
    </script>
</body>
</html>