"""Test that the path parameter uses the actual PK field name, not 'item_id'."""

from __future__ import annotations

from collections.abc import AsyncGenerator

import pytest
from fastapi import FastAPI
from httpx import ASGITransport, AsyncClient
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy.pool import StaticPool
from sqlmodel import Field, SQLModel
from sqlmodel.ext.asyncio.session import AsyncSession

from auen import CrudRouterBuilder, Operation, derive_schemas


class Catalog(SQLModel, table=True):
    """Model with a non-default PK name."""

    isbn: str = Field(primary_key=True)
    title: str


catalog_schemas = derive_schemas(Catalog, exclude_pk_from_create=False)


@pytest.fixture
async def pk_app() -> AsyncGenerator[FastAPI, None]:
    engine = create_async_engine(
        "sqlite+aiosqlite://",
        connect_args={"check_same_thread": False},
        poolclass=StaticPool,
    )
    async with engine.begin() as conn:
        await conn.run_sync(SQLModel.metadata.create_all)

    async def get_session() -> AsyncGenerator[AsyncSession, None]:
        async with AsyncSession(engine) as session:
            yield session

    app = FastAPI()
    app.include_router(
        CrudRouterBuilder.for_model(Catalog, get_session)
        .with_schemas(catalog_schemas)
        .with_operations(
            {Operation.CREATE, Operation.READ, Operation.UPDATE, Operation.DELETE}
        )
        .build()
    )
    yield app
    await engine.dispose()


async def test_path_param_uses_pk_name(pk_app: FastAPI) -> None:
    """The path parameter in OpenAPI should be 'isbn', not 'item_id'."""
    openapi = pk_app.openapi()
    paths = list(openapi["paths"].keys())
    detail_paths = [p for p in paths if "{" in p]
    # Should be /{isbn}, not /{item_id}
    for path in detail_paths:
        assert "{isbn}" in path, f"Expected {{isbn}} in path, got: {path}"
        assert "{item_id}" not in path, f"Found {{item_id}} in path: {path}"


async def test_roundtrip_with_custom_pk(pk_app: FastAPI) -> None:
    """CRUD round-trip using the actual PK field name in the URL."""
    transport = ASGITransport(app=pk_app)
    async with AsyncClient(transport=transport, base_url="http://test") as c:
        # Create
        resp = await c.post(
            "/catalogs/",
            json={"isbn": "978-0132350884", "title": "Clean Code"},
        )
        assert resp.status_code == 201

        # Read using PK name in path
        resp = await c.get("/catalogs/978-0132350884")
        assert resp.status_code == 200
        assert resp.json()["title"] == "Clean Code"

        # Update
        resp = await c.patch(
            "/catalogs/978-0132350884",
            json={"title": "Clean Code 2nd Ed"},
        )
        assert resp.status_code == 200
        assert resp.json()["title"] == "Clean Code 2nd Ed"

        # Delete
        resp = await c.delete("/catalogs/978-0132350884")
        assert resp.status_code == 200
