from __future__ import annotations

import asyncio

import httpx
from fastapi import FastAPI
from fastapi.testclient import TestClient

from services.api import app as api_app
from services.game import app as game_app
from services.analytics import app as analytics_app


def _install_asgi_clients() -> list[httpx.AsyncClient]:
    created: list[httpx.AsyncClient] = []

    def make_client(app: FastAPI, base_url: str) -> httpx.AsyncClient:
        client = httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url=base_url)
        created.append(client)
        return client

    api_app.clients["game"] = make_client(game_app.app, "http://game")
    api_app.clients["analytics"] = make_client(analytics_app.app, "http://analytics")

    dummy_ai = FastAPI()

    @dummy_ai.get("/models")
    def _models():
        return {"models": []}

    @dummy_ai.post("/act")
    def _act():
        return {"action": {"type": "end_turn", "payload": {}}, "debug": {}}

    api_app.clients["ai"] = make_client(dummy_ai, "http://ai")
    return created


def _close_clients(clients: list[httpx.AsyncClient]) -> None:
    for client in clients:
        try:
            asyncio.get_event_loop().run_until_complete(client.aclose())
        except RuntimeError:
            asyncio.run(client.aclose())


def test_api_game_flow() -> None:
    with TestClient(api_app.app) as client:
        created = _install_asgi_clients()
        response = client.post("/api/auth/register", json={"username": "eve", "password": "secret"})
        assert response.status_code == 200
        token = response.json()["token"]
        headers = {"Authorization": f"Bearer {token}"}

        response = client.post("/api/games", json={"name": "Arena", "max_players": 3}, headers=headers)
        assert response.status_code == 200
        game_id = response.json()["id"]

        response = client.post(f"/api/games/{game_id}/join", headers=headers)
        assert response.status_code == 200

        for _ in range(2):
            response = client.post(
                f"/api/games/{game_id}/add-ai",
                json={"ai_type": "random"},
                headers=headers,
            )
            assert response.status_code == 200

        response = client.post(f"/api/games/{game_id}/start", headers=headers)
        assert response.status_code == 200
        assert response.json()["status"] == "running"
        _close_clients(created)
