"""Contract tests: verify routes exist and CRUD roundtrip works."""

from __future__ import annotations

from httpx import AsyncClient
from tests.conftest import Book, SessionFactory

from auen import CrudRouterBuilder, Operation


async def test_routes_exist(client: AsyncClient) -> None:
    """All five CRUD routes should be registered."""
    resp = await client.get("/books/")
    assert resp.status_code == 200

    resp = await client.post(
        "/books/",
        json={"title": "Clean Code", "isbn": "978-0132350884"},
    )
    assert resp.status_code == 201


async def test_crud_roundtrip(client: AsyncClient) -> None:
    """Create -> Read -> List -> Update -> Delete roundtrip."""
    # Create
    resp = await client.post(
        "/books/",
        json={
            "title": "Design Patterns",
            "isbn": "978-0201633610",
            "pages": 395,
        },
    )
    assert resp.status_code == 201
    book = resp.json()
    book_id = book["id"]
    assert book["title"] == "Design Patterns"

    # Read
    resp = await client.get(f"/books/{book_id}")
    assert resp.status_code == 200
    assert resp.json()["isbn"] == "978-0201633610"

    # List
    resp = await client.get("/books/")
    assert resp.status_code == 200
    books = resp.json()
    assert any(b["id"] == book_id for b in books)

    # Update (partial - exclude_unset)
    resp = await client.patch(f"/books/{book_id}", json={"pages": 416})
    assert resp.status_code == 200
    updated = resp.json()
    assert updated["pages"] == 416
    assert updated["title"] == "Design Patterns"  # not overwritten

    # Delete
    resp = await client.delete(f"/books/{book_id}")
    assert resp.status_code == 200

    # Verify 404
    resp = await client.get(f"/books/{book_id}")
    assert resp.status_code == 404


async def test_not_found(client: AsyncClient) -> None:
    resp = await client.get("/books/99999")
    assert resp.status_code == 404


async def test_subset_operations(get_session: SessionFactory) -> None:
    """Only requested operations should be generated."""
    from fastapi import FastAPI
    from httpx import ASGITransport, AsyncClient

    app = FastAPI()
    app.include_router(
        CrudRouterBuilder.for_model(Book, get_session)
        .with_operations({Operation.LIST, Operation.READ})
        .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

        resp = await c.post(
            "/books/",
            json={
                "title": "X",
                "isbn": "Y",
            },
        )
        assert resp.status_code == 405
