"""Unit tests for Phase-2 discovery additions (plan §4.1).

Proves the `custom_tests` discovery covers exactly the per-recipe `custom/` dir, still honors the
deprecated `functional/` + `playwright/` aliases, excludes top-level lifecycle `test_<op>.py`
names, and honors the HC2 repo-local approval gate.

Run with: `cc-ci-run -m pytest tests/unit`. Located under tests/unit/ so the orchestrator never
picks these up as overlays/custom tests.
"""

from __future__ import annotations

import os
import sys

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "runner"))
from harness import discovery  # noqa: E402


def _approve(tmp_path, *recipes):
    f = tmp_path / "approved.txt"
    f.write_text("".join(f"{r}\n" for r in recipes))
    os.environ["CCCI_REPO_LOCAL_APPROVED_FILE"] = str(f)


def teardown_function():
    os.environ.pop("CCCI_REPO_LOCAL_APPROVED_FILE", None)


def test_custom_tests_placement_rule_custom_only(tmp_path, monkeypatch):
    """Placement rule (cfold): custom tests are discovered under custom/. A top-level
    non-lifecycle test_*.py is NOT discovered (top level is reserved for lifecycle overlays);
    lifecycle names inside custom/ stay excluded (defensive)."""
    fake_recipe = "ccci-phase2-fixture"
    fake_dir = tmp_path / "tests" / fake_recipe
    (fake_dir / "custom").mkdir(parents=True)
    (fake_dir / "test_sso_smoke.py").write_text("# top-level — NOT discovered since P4\n")
    (fake_dir / "custom" / "test_health_check.py").write_text("# parity port\n")
    (fake_dir / "custom" / "test_content_roundtrip.py").write_text("# recipe-specific\n")
    (fake_dir / "custom" / "test_login_flow.py").write_text("# UI flow\n")
    (fake_dir / "custom" / "test_install.py").write_text("# misfiled lifecycle name\n")

    monkeypatch.setattr(discovery, "cc_ci_dir", lambda r: str(tmp_path / "tests" / r))

    customs = discovery.custom_tests(fake_recipe, None)
    names = sorted((src, os.path.basename(p)) for src, p in customs)

    assert ("cc-ci", "test_health_check.py") in names
    assert ("cc-ci", "test_content_roundtrip.py") in names
    assert ("cc-ci", "test_login_flow.py") in names
    assert ("cc-ci", "test_sso_smoke.py") not in names
    assert ("cc-ci", "test_install.py") not in names


def test_custom_tests_repo_local_subdirs_gated(tmp_path, monkeypatch):
    """HC2 gate still applies to custom/ under repo-local: not approved -> the repo-local
    subdir contents are ignored even if they exist."""
    fake_recipe = "ccci-phase2-fixture"
    monkeypatch.setattr(discovery, "cc_ci_dir", lambda r: str(tmp_path / "cc-ci" / r))
    (tmp_path / "cc-ci" / fake_recipe).mkdir(parents=True)

    rl = tmp_path / "repo"
    (rl / "custom").mkdir(parents=True)
    (rl / "custom" / "test_repo_local_specific.py").write_text("# repo-local custom\n")

    _approve(tmp_path)
    assert discovery.custom_tests(fake_recipe, str(rl)) == []

    _approve(tmp_path, fake_recipe)
    customs = discovery.custom_tests(fake_recipe, str(rl))
    names = {(src, os.path.basename(p)) for src, p in customs}
    assert ("repo-local", "test_repo_local_specific.py") in names
