"""Recovering canonical identity for existing task rows (STATE-WP-0083-T06).

The mapping exists only in the repository files, where a task declares both its
canonical id and the projection UUID it was registered under. Reading the pairing
is safe; inferring it from titles is not, which is the whole reason this exists.
"""

from __future__ import annotations

from pathlib import Path

import pytest

from api.services import task_record_id_backfill as bf


def _repo(tmp_path: Path, name: str, body: str) -> Path:
    root = tmp_path / name
    (root / "workplans").mkdir(parents=True)
    (root / "workplans" / "WP.md").write_text(body, encoding="utf-8")
    return root


def test_reads_the_pairing_a_file_declares(tmp_path):
    root = _repo(tmp_path, "a", (
        "---\nid: DEMO-WP-0001\ntype: workplan\n---\n\n"
        '```task\nid: DEMO-WP-0001-T01\nstate_hub_task_id: "11111111-1111-5111-8111-111111111111"\n```\n'
    ))
    pairs, rep = bf.collect_pairs([root])
    assert pairs == {"11111111-1111-5111-8111-111111111111": "DEMO-WP-0001-T01"}
    assert rep.pairs_found == 1


def test_task_without_a_projection_uuid_is_skipped(tmp_path):
    """No pairing to read means no identity to assign."""
    root = _repo(tmp_path, "b", (
        "---\nid: DEMO-WP-0001\ntype: workplan\n---\n\n"
        "```task\nid: DEMO-WP-0001-T01\nstatus: todo\n```\n"
    ))
    pairs, _ = bf.collect_pairs([root])
    assert pairs == {}


def test_one_uuid_claimed_twice_is_a_conflict_not_a_guess(tmp_path):
    """Duplicate registration: picking a winner would fabricate an identity."""
    dup = "22222222-2222-5222-8222-222222222222"
    a = _repo(tmp_path, "a", (
        "---\nid: A-WP-0001\ntype: workplan\n---\n\n"
        f'```task\nid: A-WP-0001-T01\nstate_hub_task_id: "{dup}"\n```\n'
    ))
    b = _repo(tmp_path, "b", (
        "---\nid: B-WP-0001\ntype: workplan\n---\n\n"
        f'```task\nid: B-WP-0001-T01\nstate_hub_task_id: "{dup}"\n```\n'
    ))
    pairs, rep = bf.collect_pairs([a, b])
    assert len(rep.conflicts) == 1
    assert pairs[dup] == "A-WP-0001-T01"  # first wins, second recorded not applied


class _Row:
    def __init__(self, tid, record_id=None):
        self.id = tid
        self.record_id = record_id


class _Session:
    def __init__(self, rows):
        self.rows = rows

    async def execute(self, *_a, **_k):
        rows = self.rows

        class R:
            def scalars(self_inner):
                return iter(rows)

        return R()


@pytest.mark.asyncio
async def test_dry_run_changes_nothing(tmp_path):
    root = _repo(tmp_path, "a", (
        "---\nid: DEMO-WP-0001\ntype: workplan\n---\n\n"
        '```task\nid: DEMO-WP-0001-T01\nstate_hub_task_id: "11111111-1111-5111-8111-111111111111"\n```\n'
    ))
    row = _Row("11111111-1111-5111-8111-111111111111")
    rep = await bf.backfill_task_record_ids(_Session([row]), [root], dry_run=True)
    assert rep.updated == 1 and row.record_id is None


@pytest.mark.asyncio
async def test_applies_the_identity_when_not_dry_run(tmp_path):
    root = _repo(tmp_path, "a", (
        "---\nid: DEMO-WP-0001\ntype: workplan\n---\n\n"
        '```task\nid: DEMO-WP-0001-T01\nstate_hub_task_id: "11111111-1111-5111-8111-111111111111"\n```\n'
    ))
    row = _Row("11111111-1111-5111-8111-111111111111")
    rep = await bf.backfill_task_record_ids(_Session([row]), [root], dry_run=False)
    assert rep.updated == 1 and row.record_id == "DEMO-WP-0001-T01"


@pytest.mark.asyncio
async def test_a_row_the_files_do_not_claim_keeps_no_identity(tmp_path):
    """Unknown must stay unknown; the reset then keeps refusing to act on it."""
    root = _repo(tmp_path, "a", (
        "---\nid: DEMO-WP-0001\ntype: workplan\n---\n\n"
        '```task\nid: DEMO-WP-0001-T01\nstate_hub_task_id: "11111111-1111-5111-8111-111111111111"\n```\n'
    ))
    orphan = _Row("99999999-9999-4999-8999-999999999999")
    await bf.backfill_task_record_ids(_Session([orphan]), [root], dry_run=False)
    assert orphan.record_id is None


@pytest.mark.asyncio
async def test_existing_identity_is_never_overwritten(tmp_path):
    root = _repo(tmp_path, "a", (
        "---\nid: DEMO-WP-0001\ntype: workplan\n---\n\n"
        '```task\nid: DEMO-WP-0001-T01\nstate_hub_task_id: "11111111-1111-5111-8111-111111111111"\n```\n'
    ))
    row = _Row("11111111-1111-5111-8111-111111111111", record_id="OTHER-WP-0001-T09")
    rep = await bf.backfill_task_record_ids(_Session([row]), [root], dry_run=False)
    assert row.record_id == "OTHER-WP-0001-T09"
    assert rep.conflicts and rep.updated == 0


def test_a_bare_task_id_is_qualified_by_its_workplan(tmp_path):
    """`T01` is unique inside one workplan and meaningless outside it.

    Stored raw, every workplan's first task shares one identity — 51 such ids
    were assigned to 148 rows on central before this was caught.
    """
    root = _repo(tmp_path, "a", (
        "---\nid: LLM-WP-0001\ntype: workplan\n---\n\n"
        '```task\nid: T01\nstate_hub_task_id: "11111111-1111-5111-8111-111111111111"\n```\n'
    ))
    pairs, _ = bf.collect_pairs([root])
    assert pairs == {"11111111-1111-5111-8111-111111111111": "LLM-WP-0001-T01"}


def test_two_workplans_first_tasks_do_not_collide(tmp_path):
    a = _repo(tmp_path, "a", (
        "---\nid: A-WP-0001\ntype: workplan\n---\n\n"
        '```task\nid: T01\nstate_hub_task_id: "11111111-1111-5111-8111-111111111111"\n```\n'
    ))
    b = _repo(tmp_path, "b", (
        "---\nid: B-WP-0001\ntype: workplan\n---\n\n"
        '```task\nid: T01\nstate_hub_task_id: "22222222-2222-5222-8222-222222222222"\n```\n'
    ))
    pairs, rep = bf.collect_pairs([a, b])
    assert set(pairs.values()) == {"A-WP-0001-T01", "B-WP-0001-T01"}
    assert rep.conflicts == []


def test_unqualifiable_short_id_gets_no_identity(tmp_path):
    """No identity beats a non-unique one."""
    root = _repo(tmp_path, "a", (
        "id: not-frontmatter\n\n"
        '```task\nid: T01\nstate_hub_task_id: "11111111-1111-5111-8111-111111111111"\n```\n'
    ))
    pairs, _ = bf.collect_pairs([root])
    assert pairs == {}
