"""End-to-end integration test for the §19.2 "branch-name path routing"
candidate that Slice 8 settles.

Slice 2's `branches/<branch>` endpoints used FastAPI's default
`{branch}` matcher, which refuses slashes. Slice 2 worked around it
with dash-separated branch names (`<login>-draft-<hex>`); Slice 8
converts every `branches/<branch>` to `{branch:path}` and reorders
the routes so the bare GET is declared last — the more-specific
`threads` and `threads/{thread_id}/messages` GETs match first.

The tests prove:

  * A branch with a slash in the name reads correctly via
    `GET /api/rfcs/<slug>/branches/<branch:path>`.
  * The deeper threads GET still works for unslashed branches.
  * The deeper threads GET still works for slashed branches —
    the ordering discipline holds.
  * The POST routes for slashed branches still resolve (visibility,
    chat-seen, threads).
"""
from __future__ import annotations

import pytest

from test_propose_vertical import (  # noqa: F401
    FakeGitea,
    app_with_fake_gitea,
    provision_user_row,
    sign_in_as,
    tmp_env,
)
from test_rfc_view_vertical import SEED_BODY, seed_active_rfc  # noqa: F401


def _seed_slashed_branch(fake: FakeGitea, *, slug: str, branch: str, body: str) -> None:
    """Seed a branch with a slash in the name directly on FakeGitea +
    cached_branches so the GET / threads / etc. endpoints can read it."""
    from app import db

    repo_full = f"wiggleverse/rfc-0001-{slug}"
    owner, repo = repo_full.split("/", 1)
    sha = fake._next_sha()
    fake.branches[(owner, repo)][branch] = {"sha": sha, "ts": "2026-05-23T00:00:00Z"}
    fake.files[(owner, repo, branch, "RFC.md")] = {"content": body, "sha": sha}
    db.conn().execute(
        """
        INSERT OR IGNORE INTO cached_branches (rfc_slug, branch_name, head_sha, state, last_commit_at)
        VALUES (?, ?, ?, 'open', datetime('now'))
        """,
        (slug, branch, sha),
    )


def test_get_branch_view_reads_slashed_branch_name(app_with_fake_gitea):
    """The §19.1 brief's headline assertion: a branch with a slash in
    the name reads correctly via the `{branch:path}` route shape."""
    from fastapi.testclient import TestClient

    app, fake = app_with_fake_gitea
    with TestClient(app) as client:
        provision_user_row(user_id=2, login="alice", role="contributor")
        seed_active_rfc(fake, slug="ohm", title="OHM", body=SEED_BODY)
        _seed_slashed_branch(
            fake, slug="ohm", branch="alice/feature-rename",
            body="# Slashed branch body\n",
        )
        sign_in_as(client, user_id=2, gitea_login="alice",
                   display_name="Alice", role="contributor")

        r = client.get("/api/rfcs/ohm/branches/alice/feature-rename")
        assert r.status_code == 200, r.text
        view = r.json()
        assert view["branch_name"] == "alice/feature-rename"
        assert "Slashed branch body" in view["body"]


def test_deeper_threads_get_still_routes_for_unslashed_branch(app_with_fake_gitea):
    """Ordering discipline: declaring the bare GET last means the
    `threads` GET still wins for unslashed `branches/foo/threads`."""
    from fastapi.testclient import TestClient

    app, fake = app_with_fake_gitea
    with TestClient(app) as client:
        provision_user_row(user_id=2, login="alice", role="contributor")
        seed_active_rfc(fake, slug="ohm", title="OHM", body=SEED_BODY)
        _seed_slashed_branch(
            fake, slug="ohm", branch="plain-branch",
            body="# plain\n",
        )
        sign_in_as(client, user_id=2, gitea_login="alice",
                   display_name="Alice", role="contributor")

        r = client.get("/api/rfcs/ohm/branches/plain-branch/threads")
        assert r.status_code == 200, r.text
        # Empty until a thread is posted, but the route fired.
        assert "items" in r.json()


def test_deeper_threads_get_still_routes_for_slashed_branch(app_with_fake_gitea):
    """The branch name carries a slash; the threads GET must still
    match (branch={branch:path} captures `alice/feature`, threads
    is the literal anchor)."""
    from fastapi.testclient import TestClient

    app, fake = app_with_fake_gitea
    with TestClient(app) as client:
        provision_user_row(user_id=2, login="alice", role="contributor")
        seed_active_rfc(fake, slug="ohm", title="OHM", body=SEED_BODY)
        _seed_slashed_branch(
            fake, slug="ohm", branch="alice/feature",
            body="# slashed\n",
        )
        sign_in_as(client, user_id=2, gitea_login="alice",
                   display_name="Alice", role="contributor")

        r = client.get("/api/rfcs/ohm/branches/alice/feature/threads")
        assert r.status_code == 200, r.text
        assert "items" in r.json()


def test_post_visibility_resolves_for_slashed_branch(app_with_fake_gitea):
    """The §11.1 visibility POST must also route correctly for a
    slashed branch — proves the {branch:path} matcher applies to the
    write paths too."""
    from fastapi.testclient import TestClient

    app, fake = app_with_fake_gitea
    with TestClient(app) as client:
        provision_user_row(user_id=2, login="alice", role="contributor")
        seed_active_rfc(fake, slug="ohm", title="OHM", body=SEED_BODY)
        _seed_slashed_branch(
            fake, slug="ohm", branch="alice/private-work",
            body="# private\n",
        )
        # Materialize the creator row so alice can flip her own branch.
        from app import db
        db.conn().execute(
            """
            INSERT OR IGNORE INTO branch_visibility (rfc_slug, branch_name, read_public, contribute_mode)
            VALUES ('ohm', 'alice/private-work', 1, 'just-me')
            """
        )
        db.conn().execute(
            """
            INSERT OR IGNORE INTO actions (actor_user_id, on_behalf_of, action_kind, rfc_slug, branch_name)
            VALUES (2, 'alice', 'create_branch', 'ohm', 'alice/private-work')
            """
        )
        sign_in_as(client, user_id=2, gitea_login="alice",
                   display_name="Alice", role="contributor")

        r = client.post(
            "/api/rfcs/ohm/branches/alice/private-work/visibility",
            json={"read_public": False, "contribute_mode": "just-me"},
        )
        assert r.status_code == 200, r.text
        assert r.json()["ok"] is True
