"""
Integration tests for the proxy FastAPI app.

Tests the full request flow through the proxy: cache check, provider
forwarding, metrics recording, and savings API.

Uses httpx.AsyncClient with the FastAPI TestClient pattern.
"""

import json
import os
import tempfile
from unittest.mock import AsyncMock, MagicMock, patch

import pytest
from fastapi.testclient import TestClient

# Set test config before importing app
os.environ["PROXY_PROVIDER"] = "openai"
os.environ["PROXY_DB_PATH"] = ":memory:"

from proxy.app import app
from proxy.schemas import ChatCompletionResponse, Choice, ChoiceMessage, Usage


@pytest.fixture
def client():
    """FastAPI TestClient with a temporary database."""
    with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as f:
        os.environ["PROXY_DB_PATH"] = f.name

    # Reset config cache so lifespan get_config() uses this test's PROXY_DB_PATH
    import proxy.config as config_module

    config_module._config = None

    with TestClient(app) as c:
        yield c


class TestHealth:
    def test_health_endpoint(self, client):
        response = client.get("/health")
        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "healthy"
        assert "provider" in data
        assert "cache_size" in data
        assert "circuit_breaker" in data


class TestSavingsAPI:
    def test_savings_summary_empty(self, client):
        response = client.get("/api/v1/savings/summary")
        assert response.status_code == 200
        data = response.json()
        assert data["tokens_saved_total"] == 0
        assert data["messages_gained"] == 0
        assert data["dollars_saved"] == 0.0
        assert data["total_requests"] == 0

    def test_savings_history_empty(self, client):
        response = client.get("/api/v1/savings/history?days=7")
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)

    def test_usage_by_model_empty(self, client):
        response = client.get("/api/v1/usage/by-model")
        assert response.status_code == 200
        data = response.json()
        assert isinstance(data, list)

    def test_badge_endpoint(self, client):
        response = client.get("/api/v1/badge")
        assert response.status_code == 200
        data = response.json()
        assert "tokens_saved_today" in data
        assert "messages_gained" in data
        assert "dollars_saved" in data
        assert "cache_hit_rate" in data


class TestChatCompletions:
    @patch("proxy.app._http_client")
    def test_non_streaming_request(self, mock_http, client):
        """Test a basic non-streaming chat completion through the proxy."""
        # Mock the provider response
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            "id": "chatcmpl-test",
            "object": "chat.completion",
            "created": 1700000000,
            "model": "gpt-4o",
            "choices": [
                {
                    "index": 0,
                    "message": {"role": "assistant", "content": "Hello!"},
                    "finish_reason": "stop",
                }
            ],
            "usage": {
                "prompt_tokens": 10,
                "completion_tokens": 5,
                "total_tokens": 15,
            },
        }
        mock_response.headers = {}

        mock_http.post = AsyncMock(return_value=mock_response)

        response = client.post(
            "/v1/chat/completions",
            json={
                "model": "gpt-4o",
                "messages": [{"role": "user", "content": "Hello"}],
            },
            headers={"Authorization": "Bearer sk-test123"},
        )

        assert response.status_code == 200
        data = response.json()
        assert data["choices"][0]["message"]["content"] == "Hello!"

    def test_missing_model_returns_error(self, client):
        """Request without required 'model' field should fail."""
        response = client.post(
            "/v1/chat/completions",
            json={"messages": [{"role": "user", "content": "Hello"}]},
            headers={"Authorization": "Bearer sk-test"},
        )
        assert response.status_code == 422  # Validation error
