"""G-15 — the branch/body subsystem is three-tier (project/collection) aware.

Before G-15 the branch-body GET resolved every meta-resident entry to the
default project's content repo at `rfcs/<slug>.md`, so an entry in a named
collection (subfolder) or a non-default project's repo rendered a BLANK
canonical body and its edit/PR/body-write paths hit the wrong file. These tests
seed entries outside the default collection and assert the collection-scoped
body-read routes (and the now-collection-aware slug-only routes) read the
correct repo + subfolder.
"""
from __future__ import annotations

import asyncio

from app import cache as cache_mod, db, gitea as gitea_mod
from app.config import load_config

from fastapi.testclient import TestClient  # noqa: E402
from test_propose_vertical import (  # noqa: E402,F401
    app_with_fake_gitea, tmp_env, provision_user_row, sign_in_as,
)


def _entry_md(slug, title, state="active"):
    return f"---\nslug: {slug}\ntitle: {title}\nstate: {state}\n---\nthe canonical body\n"


def _add_features_collection():
    """A named 'features' collection (subfolder 'features') under the seeded
    default project — same content repo ('meta'), distinct subfolder."""
    db.conn().execute(
        "INSERT OR REPLACE INTO collections (id, project_id, type, subfolder, "
        "initial_state, visibility, name, created_at, updated_at) VALUES "
        "('features','default','document','features','super-draft','public','Features', "
        "datetime('now'), datetime('now'))")


def _add_distinct_project():
    """A second project with its OWN content repo + a default (root) collection
    — the live OHM dogfood shape (rfc-app project at rfc-app-content)."""
    db.conn().execute(
        "INSERT OR REPLACE INTO projects (id, name, content_repo, visibility, updated_at) "
        "VALUES ('rfc-app','RFC App','rfc-app-content','public', datetime('now'))")
    db.conn().execute(
        "INSERT OR REPLACE INTO collections (id, project_id, type, subfolder, "
        "initial_state, visibility, name, created_at, updated_at) VALUES "
        "('rfc-app','rfc-app','document','','super-draft','public','RFC App', "
        "datetime('now'), datetime('now'))")


def _mirror():
    cfg = load_config()
    asyncio.run(cache_mod.refresh_meta_repo(cfg, gitea_mod.Gitea(cfg)))


# --- named collection (subfolder) under the default project -------------------

def test_branch_view_named_collection_reads_subfolder(app_with_fake_gitea):
    app, fake = app_with_fake_gitea
    with TestClient(app) as client:
        _add_features_collection()
        fake.files[("wiggleverse", "meta", "main", "features/rfcs/feat.md")] = {
            "content": _entry_md("feat", "Feature Entry"), "sha": "sf"}
        _mirror()
        # cached_rfcs is keyed by the named collection.
        assert db.conn().execute(
            "SELECT collection_id FROM cached_rfcs WHERE slug='feat'"
        ).fetchone()["collection_id"] == "features"

        # Collection-scoped branch view renders the body (was blank pre-G-15).
        r = client.get(
            "/api/projects/default/collections/features/rfcs/feat/branches/main")
        assert r.status_code == 200, r.text
        assert r.json()["body"] == "the canonical body\n"

        # The slug-only legacy route is now collection-aware too: it resolves
        # the entry's own subfolder via the cached row, so it also renders.
        r2 = client.get("/api/rfcs/feat/branches/main")
        assert r2.status_code == 200, r2.text
        assert r2.json()["body"] == "the canonical body\n"


def test_main_view_named_collection_scoped_route(app_with_fake_gitea):
    app, fake = app_with_fake_gitea
    with TestClient(app) as client:
        _add_features_collection()
        fake.files[("wiggleverse", "meta", "main", "features/rfcs/feat.md")] = {
            "content": _entry_md("feat", "Feature Entry"), "sha": "sf"}
        _mirror()
        r = client.get("/api/projects/default/collections/features/rfcs/feat/main")
        assert r.status_code == 200, r.text
        assert r.json()["title"] == "Feature Entry"


# --- non-default project with a DISTINCT content repo (the OHM dogfood) -------

def test_branch_view_distinct_project_repo(app_with_fake_gitea):
    app, fake = app_with_fake_gitea
    with TestClient(app) as client:
        _add_distinct_project()
        fake.files[("wiggleverse", "rfc-app-content", "main", "rfcs/scoped.md")] = {
            "content": _entry_md("scoped", "Scoped Admin IA"), "sha": "s1"}
        _mirror()
        assert db.conn().execute(
            "SELECT collection_id FROM cached_rfcs WHERE slug='scoped'"
        ).fetchone()["collection_id"] == "rfc-app"

        # Scoped read resolves the entry's OWN content repo (rfc-app-content).
        r = client.get(
            "/api/projects/rfc-app/collections/rfc-app/rfcs/scoped/branches/main")
        assert r.status_code == 200, r.text
        assert r.json()["body"] == "the canonical body\n"

        # And the slug-only route resolves the right repo via the cached row.
        r2 = client.get("/api/rfcs/scoped/branches/main")
        assert r2.status_code == 200, r2.text
        assert r2.json()["body"] == "the canonical body\n"


# --- guards + regression ------------------------------------------------------

def test_scoped_branch_route_404_for_collection_outside_project(app_with_fake_gitea):
    app, _ = app_with_fake_gitea
    with TestClient(app) as client:
        r = client.get(
            "/api/projects/default/collections/nope/rfcs/x/branches/main")
        assert r.status_code == 404


def _seed_super_draft_in_collection(fake, *, slug, collection_id, subfolder, owners):
    import json as _json

    import yaml
    md_path = f"{subfolder}/rfcs/{slug}.md" if subfolder else f"rfcs/{slug}.md"
    fm = {"slug": slug, "title": slug.title(), "state": "super-draft", "id": None,
          "repo": None, "proposed_by": owners[0], "proposed_at": "2026-05-23",
          "graduated_at": None, "graduated_by": None,
          "owners": owners, "arbiters": owners[:1], "tags": []}
    body = "the body\n"
    text = f"---\n{yaml.safe_dump(fm, sort_keys=False).rstrip()}\n---\n\n{body}"
    sha = fake._next_sha()
    fake.files[("wiggleverse", "meta", "main", md_path)] = {"content": text, "sha": sha}
    db.conn().execute(
        "INSERT OR REPLACE INTO cached_rfcs (slug, title, state, rfc_id, repo, "
        "proposed_by, proposed_at, owners_json, arbiters_json, tags_json, body, "
        "body_sha, collection_id, last_main_commit_at, last_entry_commit_at) "
        "VALUES (?,?, 'super-draft', NULL, NULL, ?, '2026-05-23', ?, ?, '[]', ?, ?, ?, "
        "datetime('now'), datetime('now'))",
        (slug, slug.title(), owners[0], _json.dumps(owners), _json.dumps(owners[:1]),
         body, sha, collection_id))


def test_graduate_in_named_collection_writes_to_subfolder(app_with_fake_gitea):
    """G-15 write path: graduating a super-draft that lives in a named
    collection flips the entry in that collection's `<subfolder>/rfcs/<slug>.md`,
    not the default `rfcs/<slug>.md`."""
    app, fake = app_with_fake_gitea
    with TestClient(app) as client:
        _add_features_collection()
        provision_user_row(user_id=1, login="ben", role="owner")
        _seed_super_draft_in_collection(
            fake, slug="gradme", collection_id="features", subfolder="features",
            owners=["ben"])
        sign_in_as(client, user_id=1, gitea_login="ben", display_name="Ben",
                   role="owner", email="ben@x")
        r = client.post("/api/rfcs/gradme/graduate?_sync=1",
                        json={"rfc_id": "RFC-0007", "owners": ["ben"]})
        assert r.status_code == 200, r.text
        # The flip landed in the collection's subfolder, not the repo root.
        sc = fake.files.get(
            ("wiggleverse", "meta", "main", "features/rfcs/gradme.meta.yaml"))
        assert sc is not None, "sidecar not written under the collection subfolder"
        import yaml as _yaml
        assert _yaml.safe_load(sc["content"])["state"] == "active"
        # Nothing was written to the default repo-root path.
        assert ("wiggleverse", "meta", "main", "rfcs/gradme.meta.yaml") not in fake.files


def test_default_collection_entry_still_renders(app_with_fake_gitea):
    """Regression: the default-collection path (repo root `rfcs/<slug>.md` in
    the default content repo) is unchanged by the G-15 resolution."""
    app, fake = app_with_fake_gitea
    with TestClient(app) as client:
        fake.files[("wiggleverse", "meta", "main", "rfcs/base.md")] = {
            "content": _entry_md("base", "Baseline"), "sha": "sb"}
        _mirror()
        r = client.get("/api/rfcs/base/branches/main")
        assert r.status_code == 200, r.text
        assert r.json()["body"] == "the canonical body\n"
        r2 = client.get("/api/projects/default/collections/default/rfcs/base/branches/main")
        assert r2.status_code == 200, r2.text
        assert r2.json()["body"] == "the canonical body\n"
