from __future__ import annotations

import uuid
from typing import TYPE_CHECKING
from unittest.mock import AsyncMock, MagicMock

import httpx
import pytest
from fastapi import FastAPI

from codeflash_api.auth._deps import (
    check_rate_limit,
    require_auth,
    track_usage,
)
from codeflash_api.auth.models import AuthenticatedUser
from codeflash_api.llm._client import LLMResponse, LLMUsage

if TYPE_CHECKING:
    from collections.abc import AsyncIterator


FAKE_USER = AuthenticatedUser(
    user_id="github|999",
    tier="PRO",
    api_key_id=1,
    organization_id=None,
    should_log_features=True,
)


def _stub_llm_response(content: str) -> LLMResponse:
    """
    Build a minimal LLMResponse with the given *content*.
    """
    return LLMResponse(
        content=content,
        usage=LLMUsage(input_tokens=100, output_tokens=200),
        raw_response=None,
        cost=0.001,
    )


@pytest.fixture(name="mock_llm_client")
def _mock_llm_client() -> MagicMock:
    """
    Mock object standing in for LLMClient.
    """
    client = MagicMock()
    client.call = AsyncMock(
        return_value=_stub_llm_response("default mock response"),
    )
    return client


@pytest.fixture(name="app")
def _app(mock_llm_client: MagicMock) -> FastAPI:
    """
    FastAPI app with auth deps overridden and mock LLM client.

    Builds the app without the production lifespan (which needs
    a real database) and sets ``app.state`` directly.
    """
    from codeflash_api._app import _register_routes

    application = FastAPI()
    _register_routes(application)

    application.state.llm_client = mock_llm_client
    application.state.rate_limit_cache = {}
    application.state.queries = None

    async def _fake_auth() -> AuthenticatedUser:
        return FAKE_USER

    async def _fake_rate() -> None:
        return None

    async def _fake_usage() -> None:
        return None

    application.dependency_overrides[require_auth] = _fake_auth
    application.dependency_overrides[check_rate_limit] = _fake_rate
    application.dependency_overrides[track_usage] = _fake_usage

    return application


@pytest.fixture(name="client")
async def _client(app: FastAPI) -> AsyncIterator[httpx.AsyncClient]:
    """
    Authenticated async HTTP client.
    """
    transport = httpx.ASGITransport(app=app)
    async with httpx.AsyncClient(
        transport=transport, base_url="http://test"
    ) as c:
        yield c


def make_trace_id() -> str:
    """
    Return a valid UUIDv4 for use as ``trace_id``.
    """
    return str(uuid.uuid4())
