"""Router builder configuration tests."""

from __future__ import annotations

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

from auen import CrudRouterBuilder, Operation, derive_schemas
from auen.repository import AsyncSqlModelRepository


async def test_build_raises_for_multiple_models(get_session: SessionFactory) -> None:
    builder = CrudRouterBuilder.for_model([Book], get_session)
    with pytest.raises(ValueError, match="build_all"):
        builder.build()


async def test_prefix_without_slash(get_session: SessionFactory) -> None:
    app = FastAPI()
    app.include_router(
        CrudRouterBuilder.for_model(Book, get_session)
        .with_prefix("mybooks")
        .with_operations({Operation.LIST})
        .build()
    )
    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as c:
        resp = await c.get("/mybooks/")
        assert resp.status_code == 200


async def test_prefix_with_slash(get_session: SessionFactory) -> None:
    app = FastAPI()
    app.include_router(
        CrudRouterBuilder.for_model(Book, get_session)
        .with_prefix("/mybooks")
        .with_operations({Operation.LIST})
        .build()
    )
    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as c:
        resp = await c.get("/mybooks/")
        assert resp.status_code == 200


async def test_include_in_schema(get_session: SessionFactory) -> None:
    app = FastAPI()
    app.include_router(
        CrudRouterBuilder.for_model(Book, get_session)
        .with_operations({Operation.LIST, Operation.CREATE})
        .with_include_in_schema({Operation.LIST})
        .build()
    )
    schema = app.openapi()
    assert "post" not in schema["paths"]["/books/"]
    assert "get" in schema["paths"]["/books/"]


async def test_operation_id_prefix(get_session: SessionFactory) -> None:
    app = FastAPI()
    app.include_router(
        CrudRouterBuilder.for_model(Book, get_session)
        .with_operations({Operation.LIST})
        .with_operation_id_prefix("custom")
        .build()
    )
    schema = app.openapi()
    get_op = schema["paths"]["/books/"]["get"]
    assert get_op["operationId"] == "custom_list"


async def test_with_tags(get_session: SessionFactory) -> None:
    app = FastAPI()
    app.include_router(
        CrudRouterBuilder.for_model(Book, get_session)
        .with_tags(["MyTag"])
        .with_operations({Operation.LIST})
        .build()
    )
    schema = app.openapi()
    get_op = schema["paths"]["/books/"]["get"]
    assert "MyTag" in get_op["tags"]


async def test_with_custom_schemas(get_session: SessionFactory) -> None:
    schemas = derive_schemas(Book)
    app = FastAPI()
    app.include_router(
        CrudRouterBuilder.for_model(Book, get_session)
        .with_schemas(schemas)
        .with_operations({Operation.LIST})
        .build()
    )
    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as c:
        resp = await c.get("/books/")
        assert resp.status_code == 200


async def test_with_id_field(get_session: SessionFactory) -> None:
    app = FastAPI()
    app.include_router(
        CrudRouterBuilder.for_model(Book, get_session)
        .with_id_field("id")
        .with_operations({Operation.LIST})
        .build()
    )
    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as c:
        resp = await c.get("/books/")
        assert resp.status_code == 200


async def test_with_repository_factory(get_session: SessionFactory) -> None:
    app = FastAPI()
    app.include_router(
        CrudRouterBuilder.for_model(Book, get_session)
        .with_repository_factory(AsyncSqlModelRepository)
        .with_operations({Operation.LIST})
        .build()
    )
    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as c:
        resp = await c.get("/books/")
        assert resp.status_code == 200
