"""CrudRouterBuilder explicit multi-model loop tests."""

from __future__ import annotations

from typing import cast

import pytest
from fastapi import FastAPI
from httpx import ASGITransport, AsyncClient
from sqlmodel import Field, SQLModel
from tests.conftest import Book, SessionFactory

from auen import CrudRouterBuilder, CrudRouterSpec, Operation, build_crud_routers


class Author(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str


class NotAModel:
    pass


async def test_build_registers_multiple_routers(get_session: SessionFactory) -> None:
    app = FastAPI()
    for model in (Book, Author):
        app.include_router(
            CrudRouterBuilder()
            .with_operations({Operation.LIST})
            .build_routers(models=[model], session_dep=get_session)[0]
        )

    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as client:
        resp = await client.get("/books/")
        assert resp.status_code == 200
        assert resp.json() == []

        resp = await client.get("/authors/")
        assert resp.status_code == 200
        assert resp.json() == []


async def test_build_crud_routers_from_specs(
    get_session: SessionFactory,
) -> None:
    app = FastAPI()
    routers = build_crud_routers(
        specs=[
            CrudRouterSpec(
                model=Book,
                prefix="/books-v2",
                operations={Operation.LIST},
            ),
            CrudRouterSpec(
                model=Author,
                prefix="/authors-v2",
                operations={Operation.LIST},
            ),
        ],
        session_dep=get_session,
    )
    for router in routers:
        app.include_router(router)

    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as client:
        books = await client.get("/books-v2/")
        authors = await client.get("/authors-v2/")
        assert books.status_code == 200
        assert authors.status_code == 200


def test_build_crud_routers_requires_specs(get_session: SessionFactory) -> None:
    with pytest.raises(ValueError, match="at least one CrudRouterSpec"):
        build_crud_routers(specs=[], session_dep=get_session)


def test_build_crud_routers_requires_sqlmodel_model(
    get_session: SessionFactory,
) -> None:
    with pytest.raises(TypeError, match="SQLModel classes"):
        build_crud_routers(
            specs=[CrudRouterSpec(model=cast(type[SQLModel], NotAModel))],
            session_dep=get_session,
        )
