"""Tests for the FastAPI integration."""

from __future__ import annotations

import asyncio
import json
from typing import Any
from unittest.mock import MagicMock, patch

import httpx
import pytest

from kanban_analytics.async_client import (
    AsyncAnalyticsClient,
    AsyncScopedAnalyticsClient,
)
from kanban_analytics.integrations.fastapi import get_analytics


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------


def _make_initialized_async_analytics() -> AsyncAnalyticsClient:
    """Return an initialised AsyncAnalyticsClient with a mock transport."""

    async def _handler(request: httpx.Request) -> httpx.Response:
        return httpx.Response(200, json={})

    transport = httpx.MockTransport(_handler)
    client = AsyncAnalyticsClient()
    client._client = httpx.AsyncClient(transport=transport)
    client._api_key = "test-key"
    client._endpoint = "https://example.com/api/ingest"

    from kanban_analytics.context import build_server_context

    client._context = build_server_context({})  # type: ignore[arg-type]
    client._api_key_validated = True
    client._initialized = True
    return client


def _make_request(
    user_id: str | None = None,
    request_id: str | None = None,
) -> MagicMock:
    """Create a mock FastAPI/Starlette request object."""
    request = MagicMock()
    request.state = MagicMock()
    if user_id is not None:
        request.state.user_id = user_id
    else:
        del request.state.user_id
    request.headers = {}
    if request_id:
        request.headers["X-Request-ID"] = request_id
    return request


# ---------------------------------------------------------------------------
# Tests
# ---------------------------------------------------------------------------


class TestFastAPIDependency:
    @pytest.mark.asyncio
    async def test_provides_scoped_client(self) -> None:
        client = _make_initialized_async_analytics()

        with patch("kanban_analytics.async_analytics", client):
            request = _make_request(user_id="u1", request_id="req-123")
            scoped = await get_analytics(request)

            assert isinstance(scoped, AsyncScopedAnalyticsClient)

    @pytest.mark.asyncio
    async def test_scoped_client_includes_user_id(self) -> None:
        client = _make_initialized_async_analytics()

        with patch("kanban_analytics.async_analytics", client):
            request = _make_request(user_id="u42")
            scoped = await get_analytics(request)

            assert scoped._context["user_id"] == "u42"

    @pytest.mark.asyncio
    async def test_scoped_client_includes_request_id(self) -> None:
        client = _make_initialized_async_analytics()

        with patch("kanban_analytics.async_analytics", client):
            request = _make_request(request_id="req-abc")
            scoped = await get_analytics(request)

            assert scoped._context["request_id"] == "req-abc"

    @pytest.mark.asyncio
    async def test_handles_missing_user_id(self) -> None:
        client = _make_initialized_async_analytics()

        with patch("kanban_analytics.async_analytics", client):
            request = _make_request()
            scoped = await get_analytics(request)

            assert scoped._context["user_id"] is None
