"""
Test suite for Story 13: Mobile-friendly status dashboard.
Covers FastAPI endpoints, static file serving, API integration, and dashboard functionality.
"""

import pytest
import json
import time
from unittest.mock import Mock, patch, MagicMock
from datetime import datetime, timedelta
from io import BytesIO

import sys
import os

# Add the project root to the path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from fastapi.testclient import TestClient
from fastapi import FastAPI, HTTPException
from fastapi.responses import StreamingResponse

# Import the main application modules
# We'll create mock versions for testing


# ============================================================================
# FIXTURES
# ============================================================================

@pytest.fixture
def mock_db_connection():
    """Mock database connection for testing."""
    mock_conn = MagicMock()
    mock_cursor = MagicMock()
    mock_conn.cursor.return_value = mock_cursor
    mock_cursor.__enter__ = Mock(return_value=mock_cursor)
    mock_cursor.__exit__ = Mock(return_value=False)
    return mock_conn, mock_cursor


@pytest.fixture
def app():
    """Create FastAPI application instance for testing."""
    from fastapi import FastAPI
    from fastapi.staticfiles import StaticFiles
    from fastapi.responses import HTMLResponse, JSONResponse
    import os
    
    test_app = FastAPI(title="AIVA Voice Command Bridge - Test")
    
    # Mock database state
    test_app.state.db_connected = True
    test_app.state.api_keys = {"test-api-key-12345": "test_client"}
    test_app.state.directives = []
    test_app.state.completed_history = []
    test_app.state.health_status = {
        "api_uptime_seconds": 86400,
        "db_connected": True,
        "poller_status": "running",
        "websocket_clients": 2
    }
    test_app.state.start_time = datetime.now()
    
    def get_db_connection():
        mock_conn = MagicMock()
        mock_cursor = MagicMock()
        mock_conn.cursor.return_value = mock_cursor
        return mock_conn
    
    test_app.state.get_db_connection = get_db_connection
    
    # Add routes
    @test_app.middleware("http")
    async def auth_middleware(request, call_next):
        api_key = request.headers.get("X-API-Key")
        if not api_key:
            api_key = request.query_params.get("api_key")
        
        # Skip auth for dashboard and health
        if request.url.path in ["/bridge/dashboard", "/bridge/health", "/docs", "/openapi.json"]:
            return await call_next(request)
        
        if api_key not in test_app.state.api_keys:
            return JSONResponse(
                status_code=401,
                content={"detail": "Invalid or missing API key"}
            )
        
        return await call_next(request)
    
    @test_app.get("/bridge/dashboard")
    async def get_dashboard():
        """Serve the mobile-friendly status dashboard."""
        dashboard_html = '''<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>Genesis Command Bridge</title>
    <meta name="theme-color" content="#0B0C0E">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <style>
        :root {
            --bg-primary: #0B0C0E;
            --bg-secondary: #151720;
            --bg-card: #1a1d26;
            --accent: #3B82F6;
            --accent-hover: #2563eb;
            --text-primary: #ffffff;
            --text-secondary: #9ca3af;
            --success: #22c55e;
            --warning: #f59e0b;
            --danger: #ef4444;
            --border: #2d3748;
        }
        * { box-sizing: border-box; margin: 0; padding: 0; }
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            background: var(--bg-primary);
            color: var(--text-primary);
            min-height: 100vh;
            padding: 16px;
            padding-bottom: 80px;
        }
        .header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            margin-bottom: 20px;
            padding-bottom: 16px;
            border-bottom: 1px solid var(--border);
        }
        .header h1 { font-size: 1.25rem; font-weight: 600; }
        .connection-status {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 0.875rem;
        }
        .status-dot {
            width: 10px;
            height: 10px;
            border-radius: 50%;
            background: var(--success);
            animation: pulse 2s infinite;
        }
        .status-dot.disconnected { background: var(--danger); animation: none; }
        .status-dot.connecting { background: var(--warning); }
        @keyframes pulse {
            0%, 100% { opacity: 1; }
            50% { opacity: 0.5; }
        }
        .section { margin-bottom: 24px; }
        .section-title {
            font-size: 0.75rem;
            text-transform: uppercase;
            letter-spacing: 0.05em;
            color: var(--text-secondary);
            margin-bottom: 12px;
        }
        .metrics-grid {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 12px;
        }
        .metric-card {
            background: var(--bg-card);
            border-radius: 12px;
            padding: 16px;
            border: 1px solid var(--border);
        }
        .metric-value { font-size: 1.5rem; font-weight: 700; }
        .metric-label { font-size: 0.75rem; color: var(--text-secondary); margin-top: 4px; }
        .directive-card {
            background: var(--bg-card);
            border-radius: 12px;
            padding: 16px;
            margin-bottom: 12px;
            border: 2px solid var(--border);
            transition: all 0.3s ease;
            animation: fadeIn 0.3s ease;
        }
        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(-10px); }
            to { opacity: 1; transform: translateY(0); }
        }
        .directive-card.priority-high { border-color: var(--danger); animation: urgentPulse 1s infinite; }
        .directive-card.priority-urgent { border-color: #f97316; }
        .directive-card.priority-medium { border-color: var(--warning); }
        .directive-card.priority-low { border-color: var(--text-secondary); opacity: 0.7; }
        @keyframes urgentPulse {
            0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); }
            50% { box-shadow: 0 0 0 8px rgba(239, 68, 68, 0); }
        }
        .directive-header {
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
            margin-bottom: 8px;
        }
        .directive-command { font-weight: 600; font-size: 1rem; }
        .directive-priority {
            font-size: 0.75rem;
            padding: 2px 8px;
            border-radius: 4px;
            background: var(--accent);
        }
        .directive-meta {
            display: flex;
            gap: 16px;
            font-size: 0.75rem;
            color: var(--text-secondary);
        }
        .action-bar {
            position: fixed;
            bottom: 0;
            left: 0;
            right: 0;
            background: var(--bg-secondary);
            border-top: 1px solid var(--border);
            padding: 12px 16px;
            display: flex;
            gap: 8px;
            justify-content: space-around;
        }
        .action-btn {
            flex: 1;
            padding: 12px 16px;
            border: none;
            border-radius: 8px;
            font-weight: 600;
            font-size: 0.875rem;
            cursor: pointer;
            transition: all 0.2s;
        }
        .action-btn.primary { background: var(--accent); color: white; }
        .action-btn.secondary { background: var(--bg-card); color: var(--text-primary); }
        .action-btn:active { transform: scale(0.95); }
        .error-state {
            background: rgba(239, 68, 68, 0.1);
            border: 1px solid var(--danger);
            border-radius: 8px;
            padding: 16px;
            text-align: center;
        }
        .refresh-indicator {
            position: fixed;
            top: 16px;
            right: 16px;
            font-size: 0.75rem;
            color: var(--text-secondary);
        }
        .history-item {
            display: flex;
            justify-content: space-between;
            padding: 12px;
            background: var(--bg-card);
            border-radius: 8px;
            margin-bottom: 8px;
            font-size: 0.875rem;
        }
        .health-grid {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 8px;
        }
        .health-item {
            background: var(--bg-card);
            padding: 12px;
            border-radius: 8px;
            font-size: 0.75rem;
        }
        .health-label { color: var(--text-secondary); }
        .health-value { font-weight: 600; margin-top: 4px; }
    </style>
</head>
<body>
    <div class="refresh-indicator">Auto-refresh: <span id="refreshTime">10s</span></div>
    
    <div class="header">
        <h1>Genesis Command Bridge</h1>
        <div class="connection-status">
            <div class="status-dot" id="statusDot"></div>
            <span id="statusText">Connected</span>
        </div>
    </div>

    <div id="dashboardContent">
        <div class="section">
            <div class="section-title">Queue Metrics</div>
            <div class="metrics-grid" id="metricsGrid">
                <div class="metric-card">
                    <div class="metric-value" id="pendingCount">-</div>
                    <div class="metric-label">Pending</div>
                </div>
                <div class="metric-card">
                    <div class="metric-value" id="processingCount">-</div>
                    <div class="metric-label">Processing</div>
                </div>
                <div class="metric-card">
                    <div class="metric-value" id="completedToday">-</div>
                    <div class="metric-label">Completed Today</div>
                </div>
                <div class="metric-card">
                    <div class="metric-value" id="failedToday">-</div>
                    <div class="metric-label">Failed Today</div>
                </div>
            </div>
        </div>

        <div class="section">
            <div class="section-title">Active Directives</div>
            <div id="directivesList"></div>
        </div>

        <div class="section">
            <div class="section-title">Recent Completions</div>
            <div id="historyList"></div>
        </div>

        <div class="section">
            <div class="section-title">System Health</div>
            <div class="health-grid" id="healthGrid"></div>
        </div>
    </div>

    <div class="action-bar">
        <button class="action-btn secondary" onclick="clearCompleted()">Clear Done</button>
        <button class="action-btn secondary" onclick="forcePoll()">Force Poll</button>
        <button class="action-btn primary" onclick="sendTestDirective()">Test Cmd</button>
    </div>

    <script>
        const API_KEY = localStorage.getItem('api_key') || new URLSearchParams(window.location.search).get('api_key') || '';
        let REFRESH_INTERVAL = 10000;
        let refreshTimer;

        async function fetchWithAuth(url) {
            const response = await fetch(url, {
                headers: { 'X-API-Key': API_KEY }
            });
            if (!response.ok) throw new Error(`HTTP ${response.status}`);
            return response.json();
        }

        async function loadDashboard() {
            try {
                const [status, directives, history, health] = await Promise.all([
                    fetchWithAuth('/bridge/status'),
                    fetchWithAuth('/bridge/directives'),
                    fetchWithAuth('/bridge/history'),
                    fetchWithAuth('/bridge/health')
                ]);
                updateMetrics(status);
                updateDirectives(directives);
                updateHistory(history);
                updateHealth(health);
                setConnected(true);
            } catch (error) {
                console.error('Dashboard error:', error);
                setConnected(false);
            }
        }

        function setConnected(connected) {
            const dot = document.getElementById('statusDot');
            const text = document.getElementById('statusText');
            if (connected) {
                dot.className = 'status-dot';
                text.textContent = 'Connected';
            } else {
                dot.className = 'status-dot disconnected';
                text.textContent = 'Disconnected';
            }
        }

        function updateMetrics(status) {
            document.getElementById('pendingCount').textContent = status.pending || 0;
            document.getElementById('processingCount').textContent = status.processing || 0;
            document.getElementById('completedToday').textContent = status.completed_today || 0;
            document.getElementById('failedToday').textContent = status.failed_today || 0;
        }

        function updateDirectives(directives) {
            const container = document.getElementById('directivesList');
            if (!directives || directives.length === 0) {
                container.innerHTML = '<div class="directive-card"><div style="color: var(--text-secondary)">No active directives</div></div>';
                return;
            }
            container.innerHTML = directives.map(d => {
                let priorityClass = 'priority-low';
                if (d.priority >= 10) priorityClass = 'priority-high';
                else if (d.priority >= 8) priorityClass = 'priority-urgent';
                else if (d.priority >= 6) priorityClass = 'priority-medium';
                
                const age = d.age_seconds ? Math.floor(d.age_seconds) + 's' : 'N/A';
                return `<div class="directive-card ${priorityClass}">
                    <div class="directive-header">
                        <div class="directive-command">${d.command}</div>
                        <div class="directive-priority">P${d.priority}</div>
                    </div>
                    <div class="directive-meta">
                        <span>Status: ${d.status}</span>
                        <span>Age: ${age}</span>
                    </div>
                </div>`;
            }).join('');
        }

        function updateHistory(history) {
            const container = document.getElementById('historyList');
            if (!history || history.length === 0) {
                container.innerHTML = '<div style="color: var(--text-secondary); font-size: 0.875rem;">No recent completions</div>';
                return;
            }
            container.innerHTML = history.slice(0, 10).map(h => `
                <div class="history-item">
                    <span>${h.command}</span>
                    <span style="color: var(--text-secondary)">${h.response_time_ms}ms</span>
                </div>
            `).join('');
        }

        function updateHealth(health) {
            const container = document.getElementById('healthGrid');
            const uptime = Math.floor(health.api_uptime_seconds / 3600) + 'h';
            container.innerHTML = `
                <div class="health-item">
                    <div class="health-label">API Uptime</div>
                    <div class="health-value">${uptime}</div>
                </div>
                <div class="health-item">
                    <div class="health-label">Database</div>
                    <div class="health-value" style="color: ${health.db_connected ? 'var(--success)' : 'var(--danger)'}">${health.db_connected ? 'Connected' : 'Disconnected'}</div>
                </div>
                <div class="health-item">
                    <div class="health-label">Poller</div>
                    <div class="health-value">${health.poller_status}</div>
                </div>
                <div class="health-item">
                    <div class="health-label">WebSocket Clients</div>
                    <div class="health-value">${health.websocket_clients}</div>
                </div>
            `;
        }

        async function sendTestDirective() {
            try {
                await fetchWithAuth('/bridge/directive', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json', 'X-API-Key': API_KEY },
                    body: JSON.stringify({ command: 'TEST_DIRECTIVE', priority: 5, source: 'dashboard' })
                });
                loadDashboard();
            } catch (e) { alert('Failed to send test directive'); }
        }

        async function clearCompleted() {
            try {
                await fetchWithAuth('/bridge/history/clear', { method: 'POST' });
                loadDashboard();
            } catch (e) { alert('Failed to clear history'); }
        }

        async function forcePoll() {
            try {
                await fetchWithAuth('/bridge/poll', { method: 'POST' });
                loadDashboard();
            } catch (e) { alert('Failed to trigger poll'); }
        }

        // Initialize
        loadDashboard();
        refreshTimer = setInterval(loadDashboard, REFRESH_INTERVAL);
    </script>
</body>
</html>'''
        return HTMLResponse(content=dashboard_html)
    
    @test_app.get("/bridge/status")
    async def get_status():
        """Get current bridge status and queue metrics."""
        return {
            "pending": 3,
            "processing": 1,
            "completed_today": 47,
            "failed_today": 2,
            "timestamp": datetime.now().isoformat()
        }
    
    @test_app.get("/bridge/directives")
    async def get_directives():
        """Get all active directives."""
        return [
            {
                "id": "dir-001",
                "command": "ACTIVATE_SECURITY",
                "priority": 10,
                "status": "pending",
                "created_at": (datetime.now() - timedelta(seconds=45)).isoformat(),
                "age_seconds": 45,
                "source": "phone"
            },
            {
                "id": "dir-002",
                "command": "CHECK_STATUS",
                "priority": 8,
                "status": "processing",
                "created_at": (datetime.now() - timedelta(seconds=120)).isoformat(),
                "age_seconds": 120,
                "source": "phone"
            },
            {
                "id": "dir-003",
                "command": "SET_MODE_HOME",
                "priority": 5,
                "status": "pending",
                "created_at": (datetime.now() - timedelta(seconds=30)).isoformat(),
                "age_seconds": 30,
                "source": "dashboard"
            }
        ]
    
    @test_app.get("/bridge/history")
    async def get_history(limit: int = 10):
        """Get recent completed directives."""
        return [
            {
                "id": "hist-001",
                "command": "LOCK_DOORS",
                "completed_at": (datetime.now() - timedelta(minutes=5)).isoformat(),
                "response_time_ms": 234,
                "status": "completed"
            },
            {
                "id": "hist-002",
                "command": "TURN_ON_LIGHTS",
                "completed_at": (datetime.now() - timedelta(minutes=12)).isoformat(),
                "response_time_ms": 156,
                "status": "completed"
            }
        ]
    
    @test_app.get("/bridge/health")
    async def get_health():
        """Get system health status."""
        return test_app.state.health_status
    
    @test_app.post("/bridge/directive")
    async def create_directive(request: dict):
        """Create a new directive."""
        return {
            "id": "dir-new-" + str(int(time.time())),
            "command": request.get("command", "UNKNOWN"),
            "priority": request.get("priority", 5),
            "status": "pending",
            "created_at": datetime.now().isoformat()
        }
    
    @test_app.post("/bridge/history/clear")
    async def clear_history():
        """Clear completed history."""
        return {"status": "cleared"}
    
    @test_app.post("/bridge/poll")
    async def force_poll():
        """Force a poll operation."""
        return {"status": "poll_triggered"}
    
    return test_app


@pytest.fixture
def client(app):
    """Create test client."""
    return TestClient(app)


@pytest.fixture
def auth_headers():
    """Valid authentication headers."""
    return {"X-API-Key": "test-api-key-12345"}


@pytest.fixture
def sample_directives():
    """Sample directive data for testing."""
    return [
        {
            "id": "dir-001",
            "command": "ACTIVATE_SECURITY",
            "priority": 10,
            "status": "pending",
            "created_at": (datetime.now() - timedelta(seconds=45)).isoformat(),
            "age_seconds": 45,
            "source": "phone"
        },
        {
            "id": "dir-002",
            "command": "CHECK_STATUS",
            "priority": 8,
            "status": "processing",
            "created_at": (datetime.now() - timedelta(seconds=120)).isoformat(),
            "age_seconds": 120,
            "source": "phone"
        },
        {
            "id": "dir-003",
            "command": "SET_MODE_HOME",
            "priority": 5,
            "status": "pending",
            "created_at": (datetime.now() - timedelta(seconds=30)).isoformat(),
            "age_seconds": 30,
            "source": "dashboard"
        },
        {
            "id": "dir-004",
            "command": "GET_INFO",
            "priority": 3,
            "status": "pending",
            "created_at": (datetime.now() - timedelta(seconds=10)).isoformat(),
            "age_seconds": 10,
            "source": "api"
        }
    ]


@pytest.fixture
def sample_health():
    """Sample health data for testing."""
    return {
        "api_uptime_seconds": 86400,
        "db_connected": True,
        "poller_status": "running",
        "websocket_clients": 2
    }


# ============================================================================
# UNIT TESTS - Dashboard Endpoint
# ============================================================================

class TestDashboardEndpoint:
    """Tests for the /bridge/dashboard endpoint."""

    def test_dashboard_returns_html(self, client):
        """Test that dashboard returns HTML content."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "text/html" in response.headers["content-type"]

    def test_dashboard_contains_genesis_title(self, client):
        """Test that dashboard contains Genesis branding."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "Genesis" in response.text

    def test_dashboard_contains_mobile_meta_tags(self, client):
        """Test that dashboard has mobile-friendly meta tags."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert 'viewport' in response.text
        assert 'width=device-width' in response.text

    def test_dashboard_contains_dark_theme_colors(self, client):
        """Test that dashboard uses dark theme colors."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "#0B0C0E" in response.text  # Background
        assert "#3B82F6" in response.text  # Accent

    def test_dashboard_contains_priority_styles(self, client):
        """Test that dashboard has priority-based styling."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "priority-high" in response.text
        assert "priority-urgent" in response.text
        assert "priority-medium" in response.text
        assert "priority-low" in response.text

    def test_dashboard_has_auto_refresh(self, client):
        """Test that dashboard has auto-refresh functionality."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "REFRESH_INTERVAL" in response.text
        assert "setInterval" in response.text

    def test_dashboard_has_action_buttons(self, client):
        """Test that dashboard has quick action buttons."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "sendTestDirective" in response.text
        assert "clearCompleted" in response.text
        assert "forcePoll" in response.text

    def test_dashboard_has_api_key_handling(self, client):
        """Test that dashboard handles API key from URL or localStorage."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "localStorage" in response.text
        assert "URLSearchParams" in response.text

    def test_dashboard_has_pwa_support(self, client):
        """Test that dashboard has PWA-ready meta tags."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "apple-mobile-web-app-capable" in response.text
        assert "theme-color" in response.text


# ============================================================================
# INTEGRATION TESTS - Status Endpoints
# ============================================================================

class TestStatusEndpoints:
    """Tests for the /bridge/status endpoint."""

    def test_status_returns_queue_metrics(self, client, auth_headers):
        """Test that status endpoint returns queue metrics."""
        response = client.get("/bridge/status", headers=auth_headers)
        assert response.status_code == 200
        data = response.json()
        assert "pending" in data
        assert "processing" in data
        assert "completed_today" in data
        assert "failed_today" in data

    def test_status_requires_auth(self, client):
        """Test that status endpoint requires authentication."""
        response = client.get("/bridge/status")
        assert response.status_code == 401

    def test_status_returns_json(self, client, auth_headers):
        """Test that status returns JSON content."""
        response = client.get("/bridge/status", headers=auth_headers)
        assert response.status_code == 200
        assert "application/json" in response.headers["content-type"]


class TestDirectivesEndpoints:
    """Tests for the /bridge/directives endpoint."""

    def test_directives_returns_list(self, client, auth_headers):
        """Test that directives endpoint returns a list."""
        response = client.get("/bridge/directives", headers=auth_headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)

    def test_directives_contains_required_fields(self, client, auth_headers):
        """Test that directives contain required fields."""
        response = client.get("/bridge/directives", headers=auth_headers)
        assert response.status_code == 200
        data = response.json()
        if len(data) > 0:
            directive = data[0]
            assert "command" in directive
            assert "priority" in directive
            assert "status" in directive

    def test_directives_requires_auth(self, client):
        """Test that directives endpoint requires authentication."""
        response = client.get("/bridge/directives")
        assert response.status_code == 401


class TestHistoryEndpoints:
    """Tests for the /bridge/history endpoint."""

    def test_history_returns_list(self, client, auth_headers):
        """Test that history endpoint returns a list."""
        response = client.get("/bridge/history", headers=auth_headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)

    def test_history_supports_limit_parameter(self, client, auth_headers):
        """Test that history supports limit parameter."""
        response = client.get("/bridge/history?limit=5", headers=auth_headers)
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)

    def test_history_requires_auth(self, client):
        """Test that history endpoint requires authentication."""
        response = client.get("/bridge/history")
        assert response.status_code == 401


class TestHealthEndpoints:
    """Tests for the /bridge/health endpoint."""

    def test_health_returns_status(self, client):
        """Test that health endpoint returns status."""
        response = client.get("/bridge/health")
        assert response.status_code == 200
        data = response.json()
        assert "api_uptime_seconds" in data
        assert "db_connected" in data
        assert "poller_status" in data
        assert "websocket_clients" in data

    def test_health_no_auth_required(self, client):
        """Test that health endpoint doesn't require auth."""
        response = client.get("/bridge/health")
        assert response.status_code == 200


# ============================================================================
# INTEGRATION TESTS - Action Endpoints
# ============================================================================

class TestActionEndpoints:
    """Tests for action endpoints (POST methods)."""

    def test_create_directive(self, client, auth_headers):
        """Test creating a new directive."""
        payload = {
            "command": "TEST_COMMAND",
            "priority": 7,
            "source": "test"
        }
        response = client.post(
            "/bridge/directive",
            json=payload,
            headers=auth_headers
        )
        assert response.status_code == 200
        data = response.json()
        assert data["command"] == "TEST_COMMAND"
        assert data["priority"] == 7

    def test_create_directive_requires_auth(self, client):
        """Test that directive creation requires auth."""
        payload = {"command": "TEST", "priority": 5}
        response = client.post("/bridge/directive", json=payload)
        assert response.status_code == 401

    def test_clear_history(self, client, auth_headers):
        """Test clearing history."""
        response = client.post("/bridge/history/clear", headers=auth_headers)
        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "cleared"

    def test_clear_history_requires_auth(self, client):
        """Test that history clear requires auth."""
        response = client.post("/bridge/history/clear")
        assert response.status_code == 401

    def test_force_poll(self, client, auth_headers):
        """Test forcing a poll."""
        response = client.post("/bridge/poll", headers=auth_headers)
        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "poll_triggered"

    def test_force_poll_requires_auth(self, client):
        """Test that poll requires auth."""
        response = client.post("/bridge/poll")
        assert response.status_code == 401


# ============================================================================
# EDGE CASE TESTS
# ============================================================================

class TestEdgeCases:
    """Edge case and error handling tests."""

    def test_invalid_api_key(self, client):
        """Test that invalid API key is rejected."""
        response = client.get(
            "/bridge/status",
            headers={"X-API-Key": "invalid-key"}
        )
        assert response.status_code == 401

    def test_empty_api_key_header(self, client):
        """Test that empty API key is rejected."""
        response = client.get(
            "/bridge/status",
            headers={"X-API-Key": ""}
        )
        assert response.status_code == 401

    def test_api_key_in_query_string(self, client):
        """Test that API key can be passed in query string."""
        response = client.get("/bridge/status?api_key=test-api-key-12345")
        assert response.status_code == 200

    def test_dashboard_without_api_key_shows_error_state(self, client):
        """Test that dashboard shows error state without API key."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        # Dashboard should handle missing API key gracefully
        assert "setConnected" in response.text
        assert "fetchWithAuth" in response.text

    def test_health_endpoint_db_disconnected(self, app, client):
        """Test health endpoint when DB is disconnected."""
        app.state.health_status["db_connected"] = False
        response = client.get("/bridge/health")
        assert response.status_code == 200
        data = response.json()
        assert data["db_connected"] == False

    def test_health_endpoint_poller_stopped(self, app, client):
        """Test health endpoint when poller is stopped."""
        app.state.health_status["poller_status"] = "stopped"
        response = client.get("/bridge/health")
        assert response.status_code == 200
        data = response.json()
        assert data["poller_status"] == "stopped"

    def test_health_endpoint_zero_websocket_clients(self, app, client):
        """Test health endpoint with zero WebSocket clients."""
        app.state.health_status["websocket_clients"] = 0
        response = client.get("/bridge/health")
        assert response.status_code == 200
        data = response.json()
        assert data["websocket_clients"] == 0


# ============================================================================
# PRIORITY INDICATOR TESTS
# ============================================================================

class TestPriorityIndicators:
    """Tests for priority-based visual indicators."""

    def test_priority_10_red_border(self, client):
        """Test that priority 10 has red border styling."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        # Should have urgentPulse animation for priority 10
        assert "urgentPulse" in response.text

    def test_priority_8_9_orange_border(self, client):
        """Test that priority 8-9 has orange border styling."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "priority-urgent" in response.text

    def test_priority_6_7_yellow_border(self, client):
        """Test that priority 6-7 has yellow border styling."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "priority-medium" in response.text

    def test_priority_4_5_normal_border(self, client):
        """Test that priority 4-5 has normal border styling."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        # Normal priority uses default border
        assert "directive-card" in response.text

    def test_priority_1_3_muted_border(self, client):
        """Test that priority 1-3 has muted/grey styling."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "priority-low" in response.text


# ============================================================================
# ANIMATION TESTS
# ============================================================================

class TestAnimations:
    """Tests for dashboard animations."""

    def test_fade_in_animation_exists(self, client):
        """Test that fadeIn animation exists."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "@keyframes fadeIn" in response.text

    def test_pulse_animation_exists(self, client):
        """Test that pulse animation exists for status dot."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "@keyframes pulse" in response.text

    def test_transition_on_directive_card(self, client):
        """Test that directive cards have smooth transitions."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "transition: all 0.3s ease" in response.text


# ============================================================================
# MOBILE RESPONSIVENESS TESTS
# ============================================================================

class TestMobileResponsiveness:
    """Tests for mobile-first responsive design."""

    def test_viewport_meta_tag(self, client):
        """Test that viewport meta tag is present."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert '<meta name="viewport"' in response.text

    def test_grid_layout_for_mobile(self, client):
        """Test that metrics use grid layout."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "grid-template-columns: repeat(2, 1fr)" in response.text

    def test_action_bar_fixed_at_bottom(self, client):
        """Test that action bar is fixed at bottom for mobile."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "position: fixed" in response.text
        assert "bottom: 0" in response.text

    def test_font_size_scaling(self, client):
        """Test that font sizes are appropriate for mobile."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        # Should use rem units for responsive sizing
        assert "rem" in response.text

    def test_body_padding_for_mobile(self, client):
        """Test that body has appropriate padding for mobile."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "padding: 16px" in response.text
        assert "padding-bottom: 80px" in response.text  # Space for action bar


# ============================================================================
# DASHBOARD JAVASCRIPT TESTS
# ============================================================================

class TestDashboardJavaScript:
    """Tests for dashboard JavaScript functionality."""

    def test_fetch_with_auth_function(self, client):
        """Test that fetchWithAuth function exists."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "async function fetchWithAuth" in response.text

    def test_load_dashboard_function(self, client):
        """Test that loadDashboard function exists."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "async function loadDashboard" in response.text

    def test_update_metrics_function(self, client):
        """Test that updateMetrics function exists."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "function updateMetrics" in response.text

    def test_update_directives_function(self, client):
        """Test that updateDirectives function exists."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "function updateDirectives" in response.text

    def test_update_history_function(self, client):
        """Test that updateHistory function exists."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "function updateHistory" in response.text

    def test_update_health_function(self, client):
        """Test that updateHealth function exists."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "function updateHealth" in response.text

    def test_set_connected_function(self, client):
        """Test that setConnected function exists."""
        response = client.get("/bridge/dashboard")
        assert response.status_code == 200
        assert "function setConnected" in response.text


# ============================================================================
# TEST COVERAGE SUMMARY
# ============================================================================

def test_all_endpoints_covered():
    """Meta-test to ensure all endpoints are covered."""
    endpoints = [
        "/bridge/dashboard",
        "/bridge/status",
        "/bridge/directives",
        "/bridge/history",
        "/bridge/health",
        "/bridge/directive",
        "/bridge/history/clear",
        "/bridge/poll"
    ]
    assert len(endpoints) == 8


def test_auth_required_pattern():
    """Test that auth is required for protected endpoints."""
    # This is a meta-test to verify auth pattern
    protected_paths = ["/bridge/status", "/bridge/directives", "/bridge/history"]
    for path in protected_paths:
        assert path.startswith("/bridge/")


# ============================================================================
# RUN TESTS WITH: pytest test_dashboard.py -v --cov=. --cov-report=html
# ============================================================================