"""Deriving a projection from the forge (STATE-WP-0083-T01).

The properties that matter are identity and determinism: a forge-derived
projection must compute the same record identities as repo-manager, and the same
commit must always yield the same projection. Without both, the reset in T03
cannot be verified against anything.
"""

from __future__ import annotations

from pathlib import Path

import pytest

from api.services import forge_projection as fp


def test_identity_matches_the_fleet_derivation():
    """Same namespace as ADR-007, so overlay and forge agree on identity."""
    assert fp.derived_record_uuid("CUST-WP-0067") == "16249302-2767-55df-aec0-d92c2751c225"
    assert fp.derived_record_uuid("CUST-WP-0067-T01") == "f3608db4-20a5-58fb-a965-885eb14858af"


def _repo(tmp_path: Path) -> Path:
    root = tmp_path / "demo"
    (root / "workplans" / "archived").mkdir(parents=True)
    (root / "workplans" / "DEMO-WP-0001-a.md").write_text(
        "---\nid: DEMO-WP-0001\ntype: workplan\ntitle: \"First\"\nstatus: active\n---\n\n"
        "## Do the thing\n\n```task\nid: DEMO-WP-0001-T01\nstatus: todo\npriority: high\n```\n\n"
        "## Do the other\n\n```task\nid: DEMO-WP-0001-T02\nstatus: done\npriority: low\n```\n",
        encoding="utf-8",
    )
    (root / "workplans" / "archived" / "260101-DEMO-WP-0002-b.md").write_text(
        "---\nid: DEMO-WP-0002\ntype: workplan\ntitle: \"Second\"\nstatus: finished\n---\n\n# b\n",
        encoding="utf-8",
    )
    (root / "workplans" / "NOTES.md").write_text(
        "---\nid: NOT-A-WORKPLAN\ntype: note\n---\n\n# not a workplan\n", encoding="utf-8"
    )
    return root


def test_derives_workplans_tasks_and_archived_flag(tmp_path):
    p = fp.derive_from_checkout(_repo(tmp_path), "demo", "abc123")
    assert [w.record_id for w in p.workplans] == ["DEMO-WP-0001", "DEMO-WP-0002"]
    first, second = p.workplans
    assert first.status == "active" and first.archived is False
    assert second.archived is True
    assert p.task_count == 2
    assert [t.record_id for t in first.tasks] == ["DEMO-WP-0001-T01", "DEMO-WP-0001-T02"]


def test_ignores_files_that_are_not_workplans(tmp_path):
    """Selection is by `type: workplan`; anything else is not this hub's business."""
    p = fp.derive_from_checkout(_repo(tmp_path), "demo", "abc123")
    assert all(w.record_id != "NOT-A-WORKPLAN" for w in p.workplans)


def test_task_titles_fall_back_to_the_preceding_heading(tmp_path):
    p = fp.derive_from_checkout(_repo(tmp_path), "demo", "abc123")
    titles = [t.title for t in p.workplans[0].tasks]
    assert titles == ["Do the thing", "Do the other"]


def test_identifiers_are_derived_not_read_from_the_file(tmp_path):
    """A forge projection must not inherit whatever id a file happens to carry."""
    root = _repo(tmp_path)
    f = root / "workplans" / "DEMO-WP-0001-a.md"
    f.write_text(
        f.read_text(encoding="utf-8").replace(
            "status: active",
            'status: active\nstate_hub_workstream_id: "00000000-0000-4000-8000-000000000000"',
        ),
        encoding="utf-8",
    )
    p = fp.derive_from_checkout(root, "demo", "abc123")
    assert p.workplans[0].uuid == fp.derived_record_uuid("DEMO-WP-0001")
    assert p.workplans[0].uuid != "00000000-0000-4000-8000-000000000000"


def test_same_input_yields_identical_output(tmp_path):
    root = _repo(tmp_path)
    assert fp.derive_from_checkout(root, "demo", "abc").to_dict() == \
           fp.derive_from_checkout(root, "demo", "abc").to_dict()


def test_missing_workplans_directory_is_empty_not_an_error(tmp_path):
    (tmp_path / "bare").mkdir()
    p = fp.derive_from_checkout(tmp_path / "bare", "bare", "abc")
    assert p.workplans == [] and p.commit == "abc"


def test_clone_failure_is_reported_not_swallowed(monkeypatch):
    def boom(*a, **k):
        raise fp.ForgeDeriveError("repository not found")
    monkeypatch.setattr(fp, "_run_git", boom)
    with pytest.raises(fp.ForgeDeriveError, match="not found"):
        fp.derive_from_forge("nope")
