"""
GET /sales/contracts had no way to scope results to a single plot, so the
Cemetery Map's plot detail panel had no endpoint to power its "Contracts"
tab and shipped a hardcoded "No contracts linked to this plot." placeholder
regardless of whether a contract actually existed.
"""
from __future__ import annotations

import pytest
from httpx import AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession

from src.apps.plots.models.plot import Plot
from src.apps.sections.models.section import Section

CONTRACTS_URL = "/api/v1/sales/contracts"


def _headers(token: str, tenant_id) -> dict:
    return {"Authorization": f"Bearer {token}", "X-Tenant-ID": str(tenant_id)}


async def _make_plot(db: AsyncSession, account, ref: str) -> Plot:
    section = Section(tenant_id=account.id, code=ref[0], name=f"Section {ref[0]}")
    db.add(section)
    await db.flush()
    plot = Plot(tenant_id=account.id, plot_ref=ref, section_id=section.id, status="vacant")
    db.add(plot)
    await db.flush()
    return plot


async def _create_contract(client, token, tenant_id, plot_id) -> dict:
    resp = await client.post(
        CONTRACTS_URL,
        json={
            "plot_id": str(plot_id),
            "contract_type": "pre_need",
            "purchaser_name": "Test Purchaser",
            "line_items": [
                {"description": "Burial plot", "quantity": 1, "unit_price": "1000.00"},
            ],
        },
        headers=_headers(token, tenant_id),
    )
    assert resp.status_code == 201, resp.text
    return resp.json()["data"]


@pytest.mark.asyncio
async def test_list_contracts_filters_by_plot_id(
    client: AsyncClient, admin_token: str, test_account, db_session: AsyncSession
):
    plot_a = await _make_plot(db_session, test_account, "A-1")
    plot_b = await _make_plot(db_session, test_account, "B-1")
    contract_a = await _create_contract(client, admin_token, test_account.id, plot_a.id)
    await _create_contract(client, admin_token, test_account.id, plot_b.id)

    resp = await client.get(
        CONTRACTS_URL,
        params={"plot_id": str(plot_a.id)},
        headers=_headers(admin_token, test_account.id),
    )
    assert resp.status_code == 200, resp.text
    body = resp.json()
    ids = [c["id"] for c in body["data"]]
    assert ids == [contract_a["id"]]


@pytest.mark.asyncio
async def test_list_contracts_without_plot_id_returns_all(
    client: AsyncClient, admin_token: str, test_account, db_session: AsyncSession
):
    plot_a = await _make_plot(db_session, test_account, "A-1")
    plot_b = await _make_plot(db_session, test_account, "B-1")
    await _create_contract(client, admin_token, test_account.id, plot_a.id)
    await _create_contract(client, admin_token, test_account.id, plot_b.id)

    resp = await client.get(CONTRACTS_URL, headers=_headers(admin_token, test_account.id))
    assert resp.status_code == 200, resp.text
    assert resp.json()["total"] == 2


@pytest.mark.asyncio
async def test_list_contracts_by_plot_with_no_contracts_returns_empty(
    client: AsyncClient, admin_token: str, test_account, db_session: AsyncSession
):
    plot = await _make_plot(db_session, test_account, "C-1")

    resp = await client.get(
        CONTRACTS_URL,
        params={"plot_id": str(plot.id)},
        headers=_headers(admin_token, test_account.id),
    )
    assert resp.status_code == 200, resp.text
    body = resp.json()
    assert body["data"] == []
    assert body["total"] == 0
