"""tests/dev7/test_tier_classifier.py — Tier 분류 + audit log 테스트 (task-2367 P1)"""
import json
import sys
from pathlib import Path

import pytest

sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "scripts"))

import importlib.util
SPEC = importlib.util.spec_from_file_location(
    "auto_merge",
    str(Path(__file__).resolve().parents[2] / "scripts" / "auto_merge.py"),
)
assert SPEC is not None and SPEC.loader is not None
auto_merge = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(auto_merge)


@pytest.fixture
def tmp_workspace(tmp_path, monkeypatch):
    """격리된 임시 workspace."""
    (tmp_path / "memory" / "events").mkdir(parents=True)
    (tmp_path / "memory" / "capabilities").mkdir(parents=True)
    (tmp_path / "memory" / "audit").mkdir(parents=True)
    (tmp_path / "memory" / "tasks").mkdir(parents=True)
    (tmp_path / "memory" / "reports").mkdir(parents=True)
    monkeypatch.setenv("WORKSPACE_ROOT", str(tmp_path))
    return tmp_path


def _make_capability(workspace, task_id, paths=None, forbidden=None, merge_policy="tiered"):
    """capability snapshot 생성."""
    cap = {
        "task_id": task_id,
        "captured_at": "2026-05-02T00:00:00",
        "source": f"memory/tasks/{task_id}.md",
        "source_sha256": "abc123",
        "allowed_resources": {
            "paths": paths or [],
            "forbidden_paths": forbidden or [],
            "commands": [],
            "merge_policy": merge_policy,
            "ttl_hours": 48,
        },
    }
    snap_file = workspace / "memory" / "capabilities" / f"{task_id}.json"
    snap_file.write_text(json.dumps(cap), encoding="utf-8")
    return snap_file


def _make_task_file(workspace, task_id, level=0):
    """task md 파일 생성 (frontmatter level)."""
    content = f"---\ntask_id: {task_id}\nlevel: {level}\n---\n\n# {task_id}\n"
    (workspace / "memory" / "tasks" / f"{task_id}.md").write_text(content)


def test_tier1_lv0_small_diff(tmp_workspace):
    """Tier 1: Lv.0 + 작은 diff + 보호 경로 미포함."""
    task_id = "task-test-tier1"
    _make_task_file(tmp_workspace, task_id, level=0)
    _make_capability(tmp_workspace, task_id, forbidden=["scripts/task-scope-guard.sh"])

    merger = auto_merge.AutoMerger(workspace_path=str(tmp_workspace), dry_run=True)
    tier = merger.classify_tier(task_id, ["src/utils/helper.py"], project_path="", branch="")
    assert tier == "tier1"


def test_tier3_lv3(tmp_workspace):
    """Tier 3: Lv.3 task → 자동으로 tier3."""
    task_id = "task-test-tier3-lv"
    _make_task_file(tmp_workspace, task_id, level=3)
    _make_capability(tmp_workspace, task_id)

    merger = auto_merge.AutoMerger(workspace_path=str(tmp_workspace), dry_run=True)
    tier = merger.classify_tier(task_id, ["src/utils/helper.py"], project_path="", branch="")
    assert tier == "tier3"


def test_tier3_protected_path(tmp_workspace):
    """Tier 3: forbidden_paths에 매칭되는 변경 → tier3."""
    task_id = "task-test-tier3-fp"
    _make_task_file(tmp_workspace, task_id, level=1)
    _make_capability(tmp_workspace, task_id, forbidden=["scripts/task-scope-guard.sh"])

    merger = auto_merge.AutoMerger(workspace_path=str(tmp_workspace), dry_run=True)
    # 보호 경로 변경 시도
    tier = merger.classify_tier(task_id, ["scripts/task-scope-guard.sh"], project_path="", branch="")
    assert tier == "tier3"


def test_tier3_global_protected(tmp_workspace):
    """Tier 3: 글로벌 보호 경로(CLAUDE.md, .github/) → tier3 (capability 없어도)."""
    task_id = "task-test-tier3-global"
    _make_task_file(tmp_workspace, task_id, level=0)
    # capability 없음

    merger = auto_merge.AutoMerger(workspace_path=str(tmp_workspace), dry_run=True)
    tier = merger.classify_tier(task_id, ["CLAUDE.md"], project_path="", branch="")
    assert tier == "tier3"


def test_tier2_multifile(tmp_workspace):
    """Tier 2: 다중 파일(>5)."""
    task_id = "task-test-tier2-multi"
    _make_task_file(tmp_workspace, task_id, level=1)
    _make_capability(tmp_workspace, task_id)

    merger = auto_merge.AutoMerger(workspace_path=str(tmp_workspace), dry_run=True)
    diff = [f"src/file{i}.py" for i in range(6)]
    tier = merger.classify_tier(task_id, diff, project_path="", branch="")
    assert tier == "tier2"


def test_tier2_dependency_change(tmp_workspace):
    """Tier 2: package.json 변경 → 의존성 변경."""
    task_id = "task-test-tier2-dep"
    _make_task_file(tmp_workspace, task_id, level=1)
    _make_capability(tmp_workspace, task_id)

    merger = auto_merge.AutoMerger(workspace_path=str(tmp_workspace), dry_run=True)
    tier = merger.classify_tier(task_id, ["package.json"], project_path="", branch="")
    assert tier == "tier2"


def test_tier2_lv2(tmp_workspace):
    """Tier 2: Lv.2 task."""
    task_id = "task-test-tier2-lv"
    _make_task_file(tmp_workspace, task_id, level=2)
    _make_capability(tmp_workspace, task_id)

    merger = auto_merge.AutoMerger(workspace_path=str(tmp_workspace), dry_run=True)
    tier = merger.classify_tier(task_id, ["src/utils/helper.py"], project_path="", branch="")
    assert tier == "tier2"


def test_self_bypass_prevention(tmp_workspace):
    """★ 본 task-2367 자체가 Tier 3로 분류되는지 (auto_merge.py 변경 — 보호 경로)."""
    task_id = "task-2367"
    _make_task_file(tmp_workspace, task_id, level=3)
    _make_capability(
        tmp_workspace,
        task_id,
        forbidden=["scripts/task-scope-guard.sh", "memory/capabilities/**"],
    )

    merger = auto_merge.AutoMerger(workspace_path=str(tmp_workspace), dry_run=True)
    tier = merger.classify_tier(task_id, ["scripts/auto_merge.py"], project_path="", branch="")
    assert tier == "tier3", "본 task가 자기 자신을 Tier 1으로 머지하면 self-bypass 사고"


def test_audit_log_append(tmp_workspace):
    """audit log JSONL append-only 동작 + sequence 단조 증가."""
    merger = auto_merge.AutoMerger(workspace_path=str(tmp_workspace), dry_run=True)

    merger._append_audit({"task_id": "t1", "outcome": "merged", "tier": "tier1",
                          "qc_result": "pass", "scope_guard": "pass", "merger": "auto",
                          "merge_sha": "abc", "diff_files": [], "diff_loc": 0,
                          "pr_number": None, "capability_sha": ""})
    merger._append_audit({"task_id": "t2", "outcome": "escalated", "tier": "tier3",
                          "qc_result": "skipped", "scope_guard": "skipped", "merger": "auto",
                          "merge_sha": "", "diff_files": [], "diff_loc": 0,
                          "pr_number": None, "capability_sha": ""})

    log_file = tmp_workspace / "memory" / "audit" / "auto-merge.log"
    assert log_file.exists()
    lines = log_file.read_text(encoding="utf-8").strip().split("\n")
    assert len(lines) == 2
    r1 = json.loads(lines[0])
    r2 = json.loads(lines[1])
    assert r1["sequence"] == 1
    assert r2["sequence"] == 2
    assert r1["task_id"] == "t1"
    assert r2["task_id"] == "t2"
