from __future__ import annotations

from api.services import forge_projection as fp
from tests.conftest import create_test_domain, create_test_repo


def _derived(commit: str) -> fp.DerivedProjection:
    workplan_id = "TEST-WP-ADHOC-2026-08-30"
    task_id = f"{workplan_id}-T01"
    return fp.DerivedProjection(
        repo_slug="projection-test",
        commit=commit,
        workplans=[
            fp.DerivedWorkplan(
                record_id=workplan_id,
                uuid=fp.derived_record_uuid(workplan_id),
                title="Ad Hoc — 2026-08-30",
                status="active",
                relative_path="workplans/ADHOC-2026-08-30.md",
                archived=False,
                owner="codex",
                description="Small opportunistic fixes.",
                tasks=[
                    fp.DerivedTask(
                        record_id=task_id,
                        uuid=fp.derived_record_uuid(task_id),
                        title="Repair registration",
                        status="progress",
                        priority="high",
                        description="Make registration deterministic.",
                        needs_human=True,
                        intervention_note="Review the rollout.",
                        blocking_reason="Waiting for rollout approval.",
                    )
                ],
            )
        ],
    )


async def test_primary_reconciles_exact_commit_and_replays(client, monkeypatch) -> None:
    await create_test_domain(client)
    repo = await create_test_repo(client, slug="projection-test")
    commit = "a" * 40
    calls = 0

    def derive(_slug: str):
        nonlocal calls
        calls += 1
        return _derived(commit)

    from api.config import settings
    from api.routers import work_record_projection as route

    monkeypatch.setattr(settings, "state_hub_instance_role", "primary")
    monkeypatch.setattr(settings, "state_hub_instance_label", "railliance01")
    monkeypatch.setattr(route, "derive_from_forge", derive)
    headers = {"Idempotency-Key": f"projection-test:{commit}"}
    response = await client.post(
        "/repos/projection-test/work-record-projection/reconcile",
        json={"expected_commit": commit},
        headers=headers,
    )
    assert response.status_code == 200, response.text
    assert response.json()["outcome"]["status"] == "applied"

    replay = await client.post(
        "/repos/projection-test/work-record-projection/reconcile",
        json={"expected_commit": commit},
        headers=headers,
    )
    assert replay.status_code == 200
    assert replay.headers["X-StateHub-Idempotency-Replay"] == "true"
    assert calls == 1

    workplan_id = fp.derived_record_uuid("TEST-WP-ADHOC-2026-08-30")
    workplan = await client.get(f"/workplans/{workplan_id}")
    assert workplan.status_code == 200
    assert workplan.json()["repo_id"] == repo["id"]
    assert workplan.json()["owner"] == "codex"
    assert workplan.json()["description"] == "Small opportunistic fixes."

    tasks = await client.get("/tasks/", params={"workplan_id": workplan_id})
    assert tasks.status_code == 200
    task = tasks.json()[0]
    assert task["record_id"] == "TEST-WP-ADHOC-2026-08-30-T01"
    assert task["status"] == "progress"
    assert task["priority"] == "high"
    assert task["needs_human"] is True
    assert task["intervention_note"] == "Review the rollout."

    snapshot = await client.get(
        "/repos/projection-test/work-record-projection/snapshot"
    )
    assert snapshot.status_code == 200, snapshot.text
    payload = snapshot.json()
    assert payload["schema"] == "state-hub.repository-projection-snapshot.v1"
    assert payload["repo_id"] == repo["id"]
    assert [row["id"] for row in payload["workplans"]] == [str(workplan_id)]
    assert [row["record_id"] for row in payload["tasks"]] == [
        "TEST-WP-ADHOC-2026-08-30-T01"
    ]
    assert payload["dependencies"] == []


async def test_reconcile_rejects_non_primary_before_forge_access(
    client, monkeypatch
) -> None:
    from api.config import settings
    from api.routers import work_record_projection as route

    monkeypatch.setattr(settings, "state_hub_instance_role", "cache")
    monkeypatch.setattr(settings, "state_hub_instance_label", "workstation")

    def forbidden(_slug: str):
        raise AssertionError("forge must not be read by a non-primary endpoint")

    monkeypatch.setattr(route, "derive_from_forge", forbidden)
    response = await client.post(
        "/repos/projection-test/work-record-projection/reconcile",
        json={"expected_commit": "a" * 40},
    )
    assert response.status_code == 409
    assert response.json()["detail"]["instance_role"] == "cache"


async def test_reconcile_rejects_commit_mismatch_without_db_changes(
    client, monkeypatch
) -> None:
    await create_test_domain(client)
    await create_test_repo(client, slug="projection-test")
    from api.config import settings
    from api.routers import work_record_projection as route

    monkeypatch.setattr(settings, "state_hub_instance_role", "primary")
    monkeypatch.setattr(settings, "state_hub_instance_label", "railliance01")
    monkeypatch.setattr(route, "derive_from_forge", lambda _slug: _derived("b" * 40))
    response = await client.post(
        "/repos/projection-test/work-record-projection/reconcile",
        json={"expected_commit": "a" * 40},
    )
    assert response.status_code == 409
    rows = await client.get(
        "/workplans/",
        params={"repo_id": (await client.get("/repos/projection-test")).json()["id"]},
    )
    assert rows.status_code == 200
    assert rows.json() == []
