"""SLICE-4 — write paths are sidecar-aware: a migrated (body-only `.md` +
sidecar) entry never crashes `entry.parse` nor re-grows frontmatter."""
from __future__ import annotations

import asyncio

from app import gitea as gitea_mod, metadata
from app.bot import Actor, Bot
from app.config import load_config

from test_propose_vertical import (  # noqa: F401
    app_with_fake_gitea,
    provision_user_row,
    tmp_env,
)

BODY_ONLY = "Alpha prose body.\n"
SIDECAR = ("slug: alpha\ntitle: Alpha\nstate: active\n"
           "owners:\n- ben.stull\ntags:\n- one\npriority: P1\n")


def _seed_migrated(fake, repo="meta"):
    fake.files[("wiggleverse", repo, "main", "rfcs/alpha.md")] = {
        "content": BODY_ONLY, "sha": "m1"}
    fake.files[("wiggleverse", repo, "main", "rfcs/alpha.meta.yaml")] = {
        "content": SIDECAR, "sha": "m2"}


def _actor():
    return Actor(user_id=1, gitea_login="ben.stull", display_name="Ben", email="ben@x.io")


def test_mark_entry_reviewed_on_migrated_entry(app_with_fake_gitea):
    from fastapi.testclient import TestClient

    app, fake = app_with_fake_gitea
    _seed_migrated(fake)
    gitea = gitea_mod.Gitea(load_config())
    bot = Bot(gitea)
    with TestClient(app):
        provision_user_row(user_id=1, login="ben.stull", role="owner")
        # Must not raise (legacy code parsed body-only .md → ValueError).
        asyncio.run(bot.mark_entry_reviewed(
            _actor(), org="wiggleverse", meta_repo="meta", slug="alpha",
            reviewed_by="ben.stull", reviewed_at="2026-06-07"))
    md = fake.files[("wiggleverse", "meta", "main", "rfcs/alpha.md")]["content"]
    sc = fake.files[("wiggleverse", "meta", "main", "rfcs/alpha.meta.yaml")]["content"]
    assert "---" not in md                 # body stays clean (no re-grown FM)
    assert "reviewed_by: ben.stull" in sc  # review stamp landed in the sidecar


# ---- Task 3.2: body extract/wrap helpers (api_branches) ----

def test_extract_wrap_body_on_body_only_md():
    from app import api_branches
    rfc = {"state": "super-draft", "repo": None, "slug": "alpha", "collection_id": "default"}
    body = api_branches._extract_body_pure(rfc, BODY_ONLY, "main", is_meta=True)
    assert body == BODY_ONLY
    wrapped = api_branches._wrap_body_pure(rfc, BODY_ONLY, "new body\n", "main", is_meta=True)
    assert wrapped == "new body\n"      # stays clean — no re-grown frontmatter


def test_wrap_body_preserves_legacy_frontmatter():
    from app import api_branches
    legacy = "---\nslug: alpha\ntitle: Alpha\nstate: active\n---\n\nold body\n"
    rfc = {"state": "super-draft", "repo": None, "slug": "alpha", "collection_id": "default"}
    wrapped = api_branches._wrap_body_pure(rfc, legacy, "new body\n", "main", is_meta=True)
    assert wrapped.startswith("---")          # legacy frontmatter preserved
    assert "new body" in wrapped


# ---- Task 3.3: PR-replay body wrappers (api_prs) ----

def test_replay_wrappers_on_body_only():
    from app import api_prs
    assert api_prs._extract_body_for_replay(True, BODY_ONLY) == BODY_ONLY
    out = api_prs._wrap_body_for_replay(True, BODY_ONLY, "new\n")
    assert out == "new\n"               # clean, no re-grown frontmatter
    legacy = "---\nslug: a\ntitle: A\nstate: active\n---\n\nold\n"
    out2 = api_prs._wrap_body_for_replay(True, legacy, "new\n")
    assert out2.startswith("---")       # legacy preserved


# ---- Task 3.4: retire a fully-migrated (body-only + sidecar) entry ----

def test_retire_already_migrated_entry_does_not_crash(app_with_fake_gitea):
    from fastapi.testclient import TestClient
    from app import cache, db
    from app.config import load_config

    app, fake = app_with_fake_gitea
    _seed_migrated(fake)
    with TestClient(app) as client:
        provision_user_row(user_id=1, login="ben", role="owner")
        from test_propose_vertical import sign_in_as
        sign_in_as(client, user_id=1, gitea_login="ben", display_name="Ben", role="owner")
        # Ingest the migrated entry so the catalog/cache knows it.
        asyncio.run(cache.refresh_meta_repo(load_config(), gitea_mod.Gitea(load_config())))
        assert db.conn().execute(
            "SELECT state FROM cached_rfcs WHERE slug='alpha'").fetchone()["state"] == "active"
        r = client.post("/api/rfcs/alpha/retire")
        assert r.status_code == 200, r.text
        assert r.json()["state"] == "retired"
    import yaml as _yaml
    sc = _yaml.safe_load(
        fake.files[("wiggleverse", "meta", "main", "rfcs/alpha.meta.yaml")]["content"])
    assert sc["state"] == "retired"
    md = fake.files[("wiggleverse", "meta", "main", "rfcs/alpha.md")]["content"]
    assert "---" not in md          # body stayed clean


# ---- Task 3.5: graduate a fully-migrated super-draft entry ----

SUPER_SIDECAR = ("slug: alpha\ntitle: Alpha\nstate: super-draft\n"
                 "owners:\n- ben\ntags:\n- one\npriority: P1\n")


def test_graduate_already_migrated_super_draft(app_with_fake_gitea):
    from fastapi.testclient import TestClient
    from app import cache, db
    from app.config import load_config

    app, fake = app_with_fake_gitea
    fake.files[("wiggleverse", "meta", "main", "rfcs/alpha.md")] = {
        "content": BODY_ONLY, "sha": "m1"}
    fake.files[("wiggleverse", "meta", "main", "rfcs/alpha.meta.yaml")] = {
        "content": SUPER_SIDECAR, "sha": "m2"}
    with TestClient(app) as client:
        from test_propose_vertical import sign_in_as
        provision_user_row(user_id=1, login="ben", role="owner")
        sign_in_as(client, user_id=1, gitea_login="ben", display_name="Ben", role="owner")
        asyncio.run(cache.refresh_meta_repo(load_config(), gitea_mod.Gitea(load_config())))
        assert db.conn().execute(
            "SELECT state FROM cached_rfcs WHERE slug='alpha'").fetchone()["state"] == "super-draft"
        r = client.post("/api/rfcs/alpha/graduate?_sync=1",
                        json={"rfc_id": "RFC-0007", "owners": ["ben"]})
        assert r.status_code == 200, r.text
    import yaml as _yaml
    sc = _yaml.safe_load(
        fake.files[("wiggleverse", "meta", "main", "rfcs/alpha.meta.yaml")]["content"])
    assert sc["state"] == "active"
    assert sc["id"] == "RFC-0007"
    assert sc.get("priority") == "P1"        # INV-7 carried through graduation
    md = fake.files[("wiggleverse", "meta", "main", "rfcs/alpha.md")]["content"]
    assert "---" not in md                    # body stayed clean
