"""Tests for legacy-string scan in admin CLAUDE.md template endpoint.

The scanner flags admin-saved CLAUDE.md overrides that still reference the
pre-clean-bootstrap CLI surface (`da sync`, `da fetch`, `data/parquet/`,
`da analyst setup`, `da metrics list/show`). The admin UI surfaces the hits
as a yellow banner so operators know to re-author the override; the scanner
itself is informational only — saves with legacy strings are still accepted.
"""

from __future__ import annotations

import tempfile
import uuid

import pytest
from fastapi.testclient import TestClient

from app.api.claude_md import _LEGACY_STRINGS, _scan_legacy_strings


# ---------------------------------------------------------------------------
# Unit tests — pure-function behaviour
# ---------------------------------------------------------------------------


def test_scan_finds_all_known_legacy_strings():
    text = """
    Run `da sync` then `da fetch web_sessions --where ...`.
    Old workspace at data/parquet/ — see `da analyst setup`.
    Use `da metrics list` and `da metrics show <id>`.
    """
    hits = _scan_legacy_strings(text)
    assert "da sync" in hits
    assert "da fetch" in hits
    assert "data/parquet" in hits
    assert "da analyst setup" in hits
    assert "da metrics list" in hits
    assert "da metrics show" in hits


def test_scan_returns_empty_for_clean_text():
    text = "Use `agnes pull` to refresh, `agnes snapshot create` for ad-hoc, `server/parquet/`."
    assert _scan_legacy_strings(text) == []


def test_scan_returns_unique_sorted_hits():
    text = "da sync da sync data/parquet/ data/parquet/foo"
    hits = _scan_legacy_strings(text)
    assert hits == sorted(set(hits))


def test_legacy_strings_constant_shape():
    assert isinstance(_LEGACY_STRINGS, tuple)
    assert all(isinstance(s, str) for s in _LEGACY_STRINGS)
    assert "da sync" in _LEGACY_STRINGS
    assert "data/parquet" in _LEGACY_STRINGS


# ---------------------------------------------------------------------------
# HTTP-level tests — admin GET surfaces detected hits
#
# Lifts the Bearer-session pattern from tests/test_tokens_bootstrap_scope.py
# (Task 1) — Task 20's shared `web_session` cookie fixture isn't built yet,
# but the endpoint surface we're exercising is identical either way.
# ---------------------------------------------------------------------------


@pytest.fixture
def fresh_db(monkeypatch):
    with tempfile.TemporaryDirectory() as tmp:
        monkeypatch.setenv("DATA_DIR", tmp)
        monkeypatch.setenv("TESTING", "1")
        monkeypatch.setenv("JWT_SECRET_KEY", "test-jwt-secret-key-minimum-32-chars!!")
        yield tmp


@pytest.fixture
def web_session(fresh_db):
    """TestClient authenticated as an admin user via a Bearer session JWT."""
    from app.auth.jwt import create_access_token
    from app.main import app
    from src.db import close_system_db, get_system_db
    from src.repositories.users import UserRepository
    from tests.helpers.auth import grant_admin

    conn = get_system_db()
    try:
        uid = str(uuid.uuid4())
        UserRepository(conn).create(id=uid, email="admin@example.com", name="Admin")
        grant_admin(conn, uid)
        sess_token = create_access_token(user_id=uid, email="admin@example.com")
    finally:
        conn.close()
        close_system_db()

    client = TestClient(app)
    client.headers.update({"Authorization": f"Bearer {sess_token}"})
    return client


def test_admin_get_template_returns_legacy_strings_when_override_dirty(web_session):
    """Setting an override containing legacy strings populates the field."""
    put = web_session.put(
        "/api/admin/workspace-prompt-template",
        json={"content": "Run `da sync` and check data/parquet/."},
    )
    assert put.status_code == 200, put.text
    resp = web_session.get("/api/admin/workspace-prompt-template")
    assert resp.status_code == 200, resp.text
    body = resp.json()
    assert "da sync" in body["legacy_strings_detected"]
    assert "data/parquet" in body["legacy_strings_detected"]


def test_admin_get_template_returns_empty_when_clean(web_session):
    put = web_session.put(
        "/api/admin/workspace-prompt-template",
        json={"content": "Use `agnes pull` and check `server/parquet/`."},
    )
    assert put.status_code == 200, put.text
    resp = web_session.get("/api/admin/workspace-prompt-template")
    assert resp.status_code == 200, resp.text
    assert resp.json()["legacy_strings_detected"] == []


# ---------------------------------------------------------------------------
# HTML banner tests — admin /admin/workspace-prompt page renders a yellow
# warning banner above the editor when the saved override contains stale
# CLI verbs / paths.
# ---------------------------------------------------------------------------


def test_admin_workspace_prompt_page_renders_banner_when_legacy_present(web_session):
    """When the saved override contains legacy strings, the admin UI renders
    a yellow warning banner above the editor listing the hits."""
    web_session.put(
        "/api/admin/workspace-prompt-template",
        json={"content": "Run `da sync` and check data/parquet/."},
    )
    resp = web_session.get("/admin/workspace-prompt")
    assert resp.status_code == 200
    text = resp.text
    # Banner is rendered (id, class, or distinctive styling)
    assert "legacy-banner" in text or "renamed" in text.lower() or "warning" in text.lower()
    # Specific hits appear in the banner content
    assert "da sync" in text
    assert "data/parquet" in text


def test_admin_workspace_prompt_page_no_banner_when_clean(web_session):
    """When the override has no legacy strings, the banner block is absent
    (or rendered as empty/hidden)."""
    web_session.put(
        "/api/admin/workspace-prompt-template",
        json={"content": "Use `agnes pull` and `server/parquet/`."},
    )
    resp = web_session.get("/admin/workspace-prompt")
    assert resp.status_code == 200
    text = resp.text
    # The banner div should not appear (or its content should not list hits)
    # Pin to the legacy-banner id; the {% if %} guard means absent when clean
    assert "legacy-banner" not in text


def test_admin_workspace_prompt_page_no_banner_when_no_override(web_session):
    """No saved override at all → banner absent."""
    # Reset to default by deleting any existing override
    web_session.delete("/api/admin/workspace-prompt-template")
    resp = web_session.get("/admin/workspace-prompt")
    assert resp.status_code == 200
    assert "legacy-banner" not in resp.text
