<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Test Filters - Ward</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            background: #111827;
            color: #e5e7eb;
            min-height: 100vh;
        }

        .container {
            max-width: 1400px;
            margin: 0 auto;
            padding: 20px;
        }

        header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            padding-bottom: 20px;
            border-bottom: 1px solid #374151;
        }

        h1 {
            font-size: 1.5rem;
            font-weight: 600;
            color: #f9fafb;
        }

        .nav-links {
            display: flex;
            gap: 12px;
            font-size: 0.875rem;
        }

        .nav-links a {
            color: #60a5fa;
            text-decoration: none;
            padding: 6px 12px;
            border-radius: 4px;
            transition: background 0.2s;
        }

        .nav-links a:hover {
            background: #374151;
        }

        .nav-links a.active {
            background: #2563eb;
            color: white;
        }

        /* Filter Panel */
        .filter-panel {
            background: #1f2937;
            border-radius: 8px;
            padding: 20px;
            margin-bottom: 20px;
        }

        .filter-section {
            margin-bottom: 20px;
        }

        .filter-section:last-child {
            margin-bottom: 0;
        }

        .filter-label {
            font-weight: 600;
            font-size: 0.875rem;
            color: #9ca3af;
            text-transform: uppercase;
            margin-bottom: 10px;
            display: block;
        }

        .filter-group {
            display: flex;
            gap: 8px;
            flex-wrap: wrap;
        }

        .filter-chip {
            padding: 6px 12px;
            border-radius: 6px;
            font-size: 0.875rem;
            cursor: pointer;
            transition: all 0.2s;
            background: #374151;
            color: #e5e7eb;
            border: 2px solid transparent;
        }

        .filter-chip:hover {
            background: #4b5563;
        }

        .filter-chip.active {
            background: #2563eb;
            color: white;
            border-color: #1d4ed8;
        }

        .search-box {
            width: 100%;
            padding: 10px 12px;
            background: #374151;
            border: 2px solid #4b5563;
            border-radius: 6px;
            color: #e5e7eb;
            font-size: 0.875rem;
            transition: border-color 0.2s;
        }

        .search-box:focus {
            outline: none;
            border-color: #2563eb;
        }

        .search-box::placeholder {
            color: #6b7280;
        }

        /* Test List */
        .test-list {
            background: #1f2937;
            border-radius: 8px;
            overflow: hidden;
        }

        .list-header {
            padding: 12px 16px;
            background: #374151;
            font-weight: 600;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .test-count {
            font-size: 0.75rem;
            color: #9ca3af;
            background: #1f2937;
            padding: 4px 10px;
            border-radius: 10px;
        }

        .list-body {
            padding: 16px;
            max-height: 600px;
            overflow-y: auto;
        }

        .test-card {
            background: #374151;
            border-radius: 6px;
            padding: 12px;
            margin-bottom: 8px;
            cursor: pointer;
            transition: all 0.2s;
            border: 2px solid transparent;
        }

        .test-card:hover {
            background: #4b5563;
            border-color: #2563eb;
        }

        .test-card.selected {
            border-color: #2563eb;
            background: #1e3a8a;
        }

        .test-header {
            display: flex;
            justify-content: space-between;
            align-items: start;
            margin-bottom: 8px;
        }

        .test-title {
            font-weight: 600;
            color: #f9fafb;
            font-size: 0.95rem;
        }

        .test-status-badge {
            padding: 2px 8px;
            border-radius: 4px;
            font-size: 0.75rem;
            font-weight: 600;
            text-transform: uppercase;
        }

        .status-passed {
            background: #065f46;
            color: #34d399;
        }

        .status-failed {
            background: #7f1d1d;
            color: #f87171;
        }

        .status-skipped {
            background: #78350f;
            color: #fbbf24;
        }

        .status-unknown {
            background: #374151;
            color: #9ca3af;
        }

        .test-path {
            font-size: 0.75rem;
            color: #9ca3af;
            font-family: monospace;
            margin-bottom: 6px;
        }

        .test-doc {
            font-size: 0.875rem;
            color: #d1d5db;
            line-height: 1.4;
        }

        .test-meta {
            display: flex;
            gap: 12px;
            margin-top: 8px;
            font-size: 0.75rem;
            color: #6b7280;
        }

        .test-meta span {
            display: flex;
            align-items: center;
            gap: 4px;
        }

        .empty-state {
            text-align: center;
            padding: 60px 20px;
            color: #6b7280;
        }

        .empty-state-icon {
            font-size: 3rem;
            margin-bottom: 16px;
            opacity: 0.5;
        }

        /* Action Bar */
        .action-bar {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 12px 16px;
            background: #1f2937;
            border-radius: 8px;
            margin-bottom: 20px;
        }

        .btn {
            padding: 8px 16px;
            border: none;
            border-radius: 6px;
            font-size: 0.875rem;
            cursor: pointer;
            transition: all 0.2s;
        }

        .btn-primary {
            background: #2563eb;
            color: white;
        }

        .btn-primary:hover {
            background: #1d4ed8;
        }

        .btn-primary:disabled {
            background: #4b5563;
            cursor: not-allowed;
        }

        .btn-secondary {
            background: #374151;
            color: #e5e7eb;
        }

        .btn-secondary:hover {
            background: #4b5563;
        }

        .selection-info {
            font-size: 0.875rem;
            color: #9ca3af;
        }

        .selection-info strong {
            color: #60a5fa;
        }

        /* Responsive */
        @media (max-width: 768px) {
            .filter-section {
                margin-bottom: 16px;
            }

            .action-bar {
                flex-direction: column;
                gap: 12px;
                align-items: stretch;
            }

            .selection-info {
                text-align: center;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <div>
                <h1>Contract HTTP Tests - Filters</h1>
                <div class="nav-links">
                    <a href="/tools/tester/">Runner</a>
                    <a href="/tools/tester/filters" class="active">Filters</a>
                </div>
            </div>
            <div style="display: flex; align-items: center; gap: 12px; font-size: 0.875rem; color: #9ca3af;">
                <span>Target:</span>
                <select id="environmentSelector" style="background: #374151; color: #e5e7eb; border: 1px solid #4b5563; border-radius: 4px; padding: 4px 8px; font-size: 0.875rem; cursor: pointer;">
                    <option value="">Loading...</option>
                </select>
                <strong id="currentUrl" style="color: #60a5fa;">Loading...</strong>
            </div>
        </header>

        <div class="filter-panel">
            <div class="filter-section">
                <label class="filter-label">Search</label>
                <input
                    type="text"
                    class="search-box"
                    id="searchInput"
                    placeholder="Search by test name, class, or description..."
                    autocomplete="off"
                >
            </div>

            <div class="filter-section">
                <label class="filter-label">Domain</label>
                <div class="filter-group" id="domainFilters">
                    <div class="filter-chip active" data-filter="all" onclick="toggleDomainFilter(this)">
                        All Domains
                    </div>
                </div>
            </div>

            <div class="filter-section">
                <label class="filter-label">Module</label>
                <div class="filter-group" id="moduleFilters">
                    <div class="filter-chip active" data-filter="all" onclick="toggleModuleFilter(this)">
                        All Modules
                    </div>
                </div>
            </div>

            <div class="filter-section">
                <label class="filter-label">Status (from last run)</label>
                <div class="filter-group">
                    <div class="filter-chip active" data-status="all" onclick="toggleStatusFilter(this)">
                        All
                    </div>
                    <div class="filter-chip" data-status="passed" onclick="toggleStatusFilter(this)">
                        Passed
                    </div>
                    <div class="filter-chip" data-status="failed" onclick="toggleStatusFilter(this)">
                        Failed
                    </div>
                    <div class="filter-chip" data-status="skipped" onclick="toggleStatusFilter(this)">
                        Skipped
                    </div>
                    <div class="filter-chip" data-status="unknown" onclick="toggleStatusFilter(this)">
                        Not Run
                    </div>
                </div>
            </div>

            <div class="filter-section">
                <button class="btn btn-secondary" onclick="clearFilters()">Clear All Filters</button>
            </div>
        </div>

        <div class="action-bar">
            <div class="selection-info">
                <span id="selectedCount">0</span> tests selected
            </div>
            <div style="display: flex; gap: 10px;">
                <button class="btn btn-secondary" onclick="selectAll()">Select All Visible</button>
                <button class="btn btn-secondary" onclick="deselectAll()">Deselect All</button>
                <button class="btn btn-primary" id="runSelectedBtn" onclick="runSelected()">Run Selected</button>
            </div>
        </div>

        <div class="test-list">
            <div class="list-header">
                <span>Tests</span>
                <span class="test-count" id="testCount">Loading...</span>
            </div>
            <div class="list-body" id="testListBody">
                <div class="empty-state">
                    <div class="empty-state-icon">🔍</div>
                    <div>Loading tests...</div>
                </div>
            </div>
        </div>
    </div>

    <script>
        let allTests = [];
        let selectedTests = new Set();
        let lastRunResults = {};

        // Filter state
        let filters = {
            search: '',
            domains: new Set(['all']),
            modules: new Set(['all']),
            status: new Set(['all'])
        };

        // Load tests on page load
        async function loadTests() {
            try {
                const response = await fetch('/tools/tester/api/tests');
                const data = await response.json();
                allTests = data.tests;

                // Extract unique domains and modules
                const domains = new Set();
                const modules = new Set();

                allTests.forEach(test => {
                    const parts = test.id.split('.');
                    if (parts.length >= 2) {
                        domains.add(parts[0]);
                        modules.add(parts[1]);
                    }
                });

                // Populate domain filters
                const domainFilters = document.getElementById('domainFilters');
                domains.forEach(domain => {
                    const chip = document.createElement('div');
                    chip.className = 'filter-chip';
                    chip.dataset.filter = domain;
                    chip.textContent = domain;
                    chip.onclick = function() { toggleDomainFilter(this); };
                    domainFilters.appendChild(chip);
                });

                // Populate module filters
                const moduleFilters = document.getElementById('moduleFilters');
                modules.forEach(module => {
                    const chip = document.createElement('div');
                    chip.className = 'filter-chip';
                    chip.dataset.filter = module;
                    chip.textContent = module.replace('test_', '');
                    chip.onclick = function() { toggleModuleFilter(this); };
                    moduleFilters.appendChild(chip);
                });

                // Try to load last run results
                await loadLastRunResults();

                renderTests();
            } catch (error) {
                console.error('Failed to load tests:', error);
                document.getElementById('testListBody').innerHTML = `
                    <div class="empty-state">
                        <div class="empty-state-icon">⚠️</div>
                        <div>Failed to load tests</div>
                    </div>
                `;
            }
        }

        async function loadLastRunResults() {
            try {
                const response = await fetch('/tools/tester/api/runs');
                const data = await response.json();

                if (data.runs && data.runs.length > 0) {
                    const lastRunId = data.runs[0];
                    const runResponse = await fetch(`/tools/tester/api/run/${lastRunId}`);
                    const runData = await runResponse.json();

                    runData.results.forEach(result => {
                        lastRunResults[result.test_id] = result.status;
                    });
                }
            } catch (error) {
                console.error('Failed to load last run results:', error);
            }
        }

        function getTestStatus(testId) {
            return lastRunResults[testId] || 'unknown';
        }

        function toggleDomainFilter(chip) {
            const filter = chip.dataset.filter;

            if (filter === 'all') {
                // Deselect all others
                document.querySelectorAll('#domainFilters .filter-chip').forEach(c => {
                    c.classList.remove('active');
                });
                chip.classList.add('active');
                filters.domains = new Set(['all']);
            } else {
                // Remove 'all'
                document.querySelector('#domainFilters [data-filter="all"]').classList.remove('active');

                if (filters.domains.has(filter)) {
                    filters.domains.delete(filter);
                    chip.classList.remove('active');
                } else {
                    filters.domains.add(filter);
                    chip.classList.add('active');
                }

                // If nothing selected, select all
                if (filters.domains.size === 0 || filters.domains.has('all')) {
                    document.querySelector('#domainFilters [data-filter="all"]').classList.add('active');
                    document.querySelectorAll('#domainFilters .filter-chip:not([data-filter="all"])').forEach(c => {
                        c.classList.remove('active');
                    });
                    filters.domains = new Set(['all']);
                }
            }

            renderTests();
        }

        function toggleModuleFilter(chip) {
            const filter = chip.dataset.filter;

            if (filter === 'all') {
                document.querySelectorAll('#moduleFilters .filter-chip').forEach(c => {
                    c.classList.remove('active');
                });
                chip.classList.add('active');
                filters.modules = new Set(['all']);
            } else {
                document.querySelector('#moduleFilters [data-filter="all"]').classList.remove('active');

                if (filters.modules.has(filter)) {
                    filters.modules.delete(filter);
                    chip.classList.remove('active');
                } else {
                    filters.modules.add(filter);
                    chip.classList.add('active');
                }

                if (filters.modules.size === 0 || filters.modules.has('all')) {
                    document.querySelector('#moduleFilters [data-filter="all"]').classList.add('active');
                    document.querySelectorAll('#moduleFilters .filter-chip:not([data-filter="all"])').forEach(c => {
                        c.classList.remove('active');
                    });
                    filters.modules = new Set(['all']);
                }
            }

            renderTests();
        }

        function toggleStatusFilter(chip) {
            const status = chip.dataset.status;

            if (status === 'all') {
                document.querySelectorAll('[data-status]').forEach(c => {
                    c.classList.remove('active');
                });
                chip.classList.add('active');
                filters.status = new Set(['all']);
            } else {
                document.querySelector('[data-status="all"]').classList.remove('active');

                if (filters.status.has(status)) {
                    filters.status.delete(status);
                    chip.classList.remove('active');
                } else {
                    filters.status.add(status);
                    chip.classList.add('active');
                }

                if (filters.status.size === 0 || filters.status.has('all')) {
                    document.querySelector('[data-status="all"]').classList.add('active');
                    document.querySelectorAll('[data-status]:not([data-status="all"])').forEach(c => {
                        c.classList.remove('active');
                    });
                    filters.status = new Set(['all']);
                }
            }

            renderTests();
        }

        function clearFilters() {
            // Reset search
            document.getElementById('searchInput').value = '';
            filters.search = '';

            // Reset domains
            document.querySelectorAll('#domainFilters .filter-chip').forEach(c => c.classList.remove('active'));
            document.querySelector('#domainFilters [data-filter="all"]').classList.add('active');
            filters.domains = new Set(['all']);

            // Reset modules
            document.querySelectorAll('#moduleFilters .filter-chip').forEach(c => c.classList.remove('active'));
            document.querySelector('#moduleFilters [data-filter="all"]').classList.add('active');
            filters.modules = new Set(['all']);

            // Reset status
            document.querySelectorAll('[data-status]').forEach(c => c.classList.remove('active'));
            document.querySelector('[data-status="all"]').classList.add('active');
            filters.status = new Set(['all']);

            renderTests();
        }

        function filterTests() {
            return allTests.filter(test => {
                const parts = test.id.split('.');
                const domain = parts[0];
                const module = parts[1];
                const status = getTestStatus(test.id);

                // Search filter
                if (filters.search) {
                    const searchLower = filters.search.toLowerCase();
                    const matchesSearch =
                        test.name.toLowerCase().includes(searchLower) ||
                        test.class_name.toLowerCase().includes(searchLower) ||
                        (test.doc && test.doc.toLowerCase().includes(searchLower)) ||
                        test.id.toLowerCase().includes(searchLower);

                    if (!matchesSearch) return false;
                }

                // Domain filter
                if (!filters.domains.has('all') && !filters.domains.has(domain)) {
                    return false;
                }

                // Module filter
                if (!filters.modules.has('all') && !filters.modules.has(module)) {
                    return false;
                }

                // Status filter
                if (!filters.status.has('all') && !filters.status.has(status)) {
                    return false;
                }

                return true;
            });
        }

        function renderTests() {
            const filteredTests = filterTests();
            const container = document.getElementById('testListBody');

            document.getElementById('testCount').textContent = `${filteredTests.length} of ${allTests.length}`;

            if (filteredTests.length === 0) {
                container.innerHTML = `
                    <div class="empty-state">
                        <div class="empty-state-icon">🔍</div>
                        <div>No tests match your filters</div>
                    </div>
                `;
                return;
            }

            container.innerHTML = filteredTests.map(test => {
                const status = getTestStatus(test.id);
                const isSelected = selectedTests.has(test.id);
                const parts = test.id.split('.');
                const domain = parts[0];
                const module = parts[1];

                return `
                    <div class="test-card ${isSelected ? 'selected' : ''}" onclick="toggleTestSelection('${test.id}')" data-test-id="${test.id}">
                        <div class="test-header">
                            <div class="test-title">${formatTestName(test.method_name)}</div>
                            <div class="test-status-badge status-${status}">${status}</div>
                        </div>
                        <div class="test-path">${test.id}</div>
                        <div class="test-doc">${test.doc || 'No description'}</div>
                        <div class="test-meta">
                            <span>📁 ${domain}</span>
                            <span>📄 ${module}</span>
                            <span>🏷️ ${test.class_name}</span>
                        </div>
                    </div>
                `;
            }).join('');

            updateSelectionInfo();
        }

        function formatTestName(name) {
            return name.replace(/^test_/, '').replace(/_/g, ' ');
        }

        function toggleTestSelection(testId) {
            if (selectedTests.has(testId)) {
                selectedTests.delete(testId);
            } else {
                selectedTests.add(testId);
            }

            // Update UI
            const card = document.querySelector(`[data-test-id="${testId}"]`);
            if (card) {
                card.classList.toggle('selected');
            }

            updateSelectionInfo();
        }

        function selectAll() {
            const filteredTests = filterTests();
            filteredTests.forEach(test => selectedTests.add(test.id));
            renderTests();
        }

        function deselectAll() {
            selectedTests.clear();
            renderTests();
        }

        function updateSelectionInfo() {
            document.getElementById('selectedCount').textContent = selectedTests.size;
            document.getElementById('runSelectedBtn').disabled = selectedTests.size === 0;
        }

        async function runSelected() {
            if (selectedTests.size === 0) {
                alert('No tests selected');
                return;
            }

            const testIds = Array.from(selectedTests);

            try {
                const response = await fetch('/tools/tester/api/run', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ test_ids: testIds }),
                });
                const data = await response.json();

                // Build URL params to preserve filter state in runner
                const params = new URLSearchParams();
                params.set('run', data.run_id);

                // Pass filter state
                if (filters.search) params.set('search', filters.search);
                if (!filters.domains.has('all')) {
                    params.set('domains', Array.from(filters.domains).join(','));
                }
                if (!filters.modules.has('all')) {
                    params.set('modules', Array.from(filters.modules).join(','));
                }
                if (!filters.status.has('all')) {
                    params.set('status', Array.from(filters.status).join(','));
                }

                // Redirect to main runner with filters applied
                window.location.href = `/tools/tester/?${params.toString()}`;
            } catch (error) {
                console.error('Failed to start run:', error);
                alert('Failed to start test run');
            }
        }

        // Search input handler
        document.getElementById('searchInput').addEventListener('input', (e) => {
            filters.search = e.target.value;
            renderTests();
        });

        // Load environments
        async function loadEnvironments() {
            try {
                const response = await fetch('/tools/tester/api/environments');
                const data = await response.json();
                const selector = document.getElementById('environmentSelector');
                const currentUrl = document.getElementById('currentUrl');

                const savedEnvId = localStorage.getItem('selectedEnvironment');
                let selectedEnv = null;

                selector.innerHTML = data.environments.map(env => {
                    const isDefault = env.default || env.id === savedEnvId;
                    if (isDefault) selectedEnv = env;
                    return `<option value="${env.id}" ${isDefault ? 'selected' : ''}>${env.name} ${env.has_api_key ? '🔑' : ''}</option>`;
                }).join('');

                if (selectedEnv) {
                    currentUrl.textContent = selectedEnv.url;
                }

                selector.addEventListener('change', async (e) => {
                    const envId = e.target.value;
                    try {
                        const response = await fetch(`/tools/tester/api/environment/select?env_id=${envId}`, {
                            method: 'POST'
                        });
                        const data = await response.json();

                        if (data.success) {
                            currentUrl.textContent = data.environment.url;
                            localStorage.setItem('selectedEnvironment', envId);
                        }
                    } catch (error) {
                        console.error('Failed to switch environment:', error);
                        alert('Failed to switch environment');
                    }
                });
            } catch (error) {
                console.error('Failed to load environments:', error);
            }
        }

        // Load tests on page load
        loadEnvironments();
        loadTests();
    </script>
</body>
</html>
