"""Tests for dashboard API endpoints."""

import hashlib
import json
import pytest
from unittest.mock import AsyncMock, MagicMock, patch

from aiohttp import web
from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop

from backend.config import EcateConfig, ProviderConfig, ModelConfig, RoutingConfig
from backend.dashboard.api import (
    _check_api_key,
    handle_overview,
    handle_get_models,
    handle_health,
    register_dashboard_routes,
)


@pytest.fixture
def mock_config():
    return EcateConfig(
        routing=RoutingConfig(vectors_path="data/model_vectors.json"),
        providers=[
            ProviderConfig(
                id="openai",
                type="openai",
                base_url="https://api.openai.com/v1",
                api_key="sk-test",
                models=[
                    ModelConfig(
                        id="gpt-4o",
                        input_cost_per_mtok=2.5,
                        output_cost_per_mtok=10.0,
                        supports_tools=True,
                        supports_vision=True,
                    ),
                ],
            ),
        ],
    )


@pytest.fixture
def mock_db():
    db = AsyncMock()
    db.execute_fetchall = AsyncMock(return_value=[])
    return db


class TestCheckApiKey:
    @pytest.mark.asyncio
    async def test_missing_header(self, mock_db):
        request = MagicMock()
        request.headers = {}
        
        with patch("backend.dashboard.api.get_db", return_value=mock_db):
            result = await _check_api_key(request)
        
        assert result is False

    @pytest.mark.asyncio
    async def test_invalid_format(self, mock_db):
        request = MagicMock()
        request.headers = {"Authorization": "Basic abc"}
        
        with patch("backend.dashboard.api.get_db", return_value=mock_db):
            result = await _check_api_key(request)
        
        assert result is False

    @pytest.mark.asyncio
    async def test_empty_token(self, mock_db):
        request = MagicMock()
        request.headers = {"Authorization": "Bearer "}
        
        with patch("backend.dashboard.api.get_db", return_value=mock_db):
            result = await _check_api_key(request)
        
        assert result is False

    @pytest.mark.asyncio
    async def test_invalid_key(self, mock_db):
        request = MagicMock()
        request.headers = {"Authorization": "Bearer invalid-key"}
        mock_db.execute_fetchall = AsyncMock(return_value=[])
        
        with patch("backend.dashboard.api.get_db", return_value=mock_db):
            result = await _check_api_key(request)
        
        assert result is False

    @pytest.mark.asyncio
    async def test_valid_key(self, mock_db):
        token = "ek-valid123"
        request = MagicMock()
        request.headers = {"Authorization": f"Bearer {token}"}
        mock_db.execute_fetchall = AsyncMock(return_value=[{"id": "key1"}])
        
        with patch("backend.dashboard.api.get_db", return_value=mock_db):
            result = await _check_api_key(request)
        
        assert result is True


class TestHandleOverview:
    @pytest.mark.asyncio
    async def test_overview_returns_data(self, mock_db):
        request = MagicMock()
        request.query = {"days": "30"}
        
        mock_db.execute_fetchall = AsyncMock(return_value=[{
            "total_requests": 100,
            "total_cost": 5.50,
            "total_tokens": 50000,
            "avg_latency": 250.5,
        }])
        
        with patch("backend.db.queries.get_db", return_value=mock_db):
            response = await handle_overview(request)
        
        assert response.status == 200
        data = json.loads(response.body)
        assert "total_requests" in data
        assert "total_cost" in data


class TestHandleGetModels:
    @pytest.mark.asyncio
    async def test_get_models_returns_list(self, mock_config):
        request = MagicMock()
        request.app = {"config": mock_config}
        
        response = await handle_get_models(request)
        
        assert response.status == 200
        data = json.loads(response.body)
        assert isinstance(data, list)
        assert len(data) == 1
        assert data[0]["model_id"] == "gpt-4o"
        assert data[0]["provider_id"] == "openai"
        assert data[0]["full_id"] == "openai/gpt-4o"


class TestHandleHealth:
    @pytest.mark.asyncio
    async def test_health_without_circuit_breaker(self):
        request = MagicMock()
        request.app = {}
        
        response = await handle_health(request)
        
        assert response.status == 200
        data = json.loads(response.body)
        assert data["status"] == "healthy"
        assert data["service"] == "ecate"

    @pytest.mark.asyncio
    async def test_health_with_circuit_breaker(self):
        mock_cb = MagicMock()
        mock_cb.get_status.return_value = {"model-a": "closed", "model-b": "open"}
        
        request = MagicMock()
        request.app = {"circuit_breaker": mock_cb}
        
        response = await handle_health(request)
        
        data = json.loads(response.body)
        assert data["circuit_breakers"] == {"model-a": "closed", "model-b": "open"}


class TestRegisterRoutes:
    def test_routes_registered(self):
        app = web.Application()
        register_dashboard_routes(app)
        
        # Check key routes exist
        routes = [r.resource.canonical for r in app.router.routes()]
        
        assert "/api/overview" in routes
        assert "/api/models" in routes
        assert "/health" in routes
        assert "/api/calibration/start" in routes
        assert "/api/routing/vectors" in routes
