from __future__ import annotations

import copy
import json
from pathlib import Path

import pytest

from src.services.ai_agent_high_risk_owner_review_queue import (
    load_latest_ai_agent_high_risk_owner_review_queue,
)

_REPO_ROOT = Path(__file__).resolve().parents[3]
_COMMITTED_SNAPSHOT = (
    _REPO_ROOT
    / "docs"
    / "evaluations"
    / "ai_agent_high_risk_owner_review_queue_2026-06-19.json"
)


def test_load_latest_ai_agent_high_risk_owner_review_queue_reads_newest_file(tmp_path):
    older = _snapshot(generated_at="2026-06-18T00:00:00+08:00")
    newer = _snapshot(generated_at="2026-06-19T03:20:00+08:00")
    (tmp_path / "ai_agent_high_risk_owner_review_queue_2026-06-18.json").write_text(
        json.dumps(older),
        encoding="utf-8",
    )
    (tmp_path / "ai_agent_high_risk_owner_review_queue_2026-06-19.json").write_text(
        json.dumps(newer),
        encoding="utf-8",
    )

    loaded = load_latest_ai_agent_high_risk_owner_review_queue(tmp_path)

    assert loaded["generated_at"] == "2026-06-19T03:20:00+08:00"
    assert loaded["program_status"]["current_task_id"] == "P2-409"
    assert loaded["program_status"]["next_task_id"] == "P2-410"
    assert loaded["program_status"]["read_only_mode"] is True
    assert (
        loaded["program_status"]["runtime_authority"]
        == "controlled_apply_break_glass_queue_readback_no_live_execution"
    )
    assert loaded["queue_truth"]["all_high_risk_actions_paused"] is False
    assert loaded["queue_truth"]["high_risk_owner_review_required"] is False
    assert loaded["queue_truth"]["high_risk_controlled_apply_enabled"] is True
    assert loaded["queue_truth"]["critical_break_glass_required"] is True
    assert loaded["rollups"]["queue_item_count"] == 7
    assert loaded["rollups"]["approval_packet_count"] == 7
    assert loaded["rollups"]["rejection_guard_count"] == 8
    assert loaded["rollups"]["controlled_apply_queue_count"] == 5
    assert loaded["rollups"]["critical_break_glass_queue_count"] == 2
    assert loaded["rollups"]["owner_response_required_count"] == 2
    assert loaded["rollups"]["high_risk_owner_review_required_count"] == 0
    assert loaded["rollups"]["telegram_send_count"] == 0


def test_ai_agent_high_risk_owner_review_queue_requires_read_only_mode(tmp_path):
    snapshot = _snapshot()
    snapshot["program_status"]["read_only_mode"] = False
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="program_status"):
        load_latest_ai_agent_high_risk_owner_review_queue(tmp_path)


def test_ai_agent_high_risk_owner_review_queue_blocks_live_execution(tmp_path):
    snapshot = _snapshot()
    snapshot["owner_review_queue_items"][0]["live_execution_allowed"] = True
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="live_execution_allowed"):
        load_latest_ai_agent_high_risk_owner_review_queue(tmp_path)


def test_ai_agent_high_risk_owner_review_queue_blocks_telegram_send(tmp_path):
    snapshot = _snapshot()
    snapshot["telegram_policy"]["telegram_send_allowed"] = True
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="telegram_policy"):
        load_latest_ai_agent_high_risk_owner_review_queue(tmp_path)


def test_ai_agent_high_risk_owner_review_queue_requires_high_and_critical(tmp_path):
    snapshot = _snapshot()
    for item in snapshot["owner_review_queue_items"]:
        item["risk_tier"] = "high"
    snapshot["rollups"]["critical_queue_count"] = 0
    snapshot["rollups"]["high_risk_queue_count"] = len(snapshot["owner_review_queue_items"])
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="must include high and critical"):
        load_latest_ai_agent_high_risk_owner_review_queue(tmp_path)


def test_ai_agent_high_risk_owner_review_queue_requires_approval_packet(tmp_path):
    snapshot = _snapshot()
    snapshot["owner_review_queue_items"][0]["approval_packet_id"] = "missing_packet"
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="missing approval packets"):
        load_latest_ai_agent_high_risk_owner_review_queue(tmp_path)


def test_ai_agent_high_risk_owner_review_queue_requires_rejection_guard(tmp_path):
    snapshot = _snapshot()
    snapshot["owner_review_queue_items"][0]["rejection_guard_ids"] = ["missing_guard"]
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="missing rejection guards"):
        load_latest_ai_agent_high_risk_owner_review_queue(tmp_path)


def test_ai_agent_high_risk_owner_review_queue_requires_reviewer_checklist(tmp_path):
    snapshot = _snapshot()
    snapshot["owner_review_queue_items"][0]["reviewer_checklist_ids"] = ["missing_checklist"]
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="missing reviewer checklists"):
        load_latest_ai_agent_high_risk_owner_review_queue(tmp_path)


def test_ai_agent_high_risk_owner_review_queue_requires_rollback_owner(tmp_path):
    snapshot = _snapshot()
    snapshot["owner_review_queue_items"][0]["rollback_owner_required"] = False
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="rollback_owner_required"):
        load_latest_ai_agent_high_risk_owner_review_queue(tmp_path)


def test_ai_agent_high_risk_owner_review_queue_keeps_high_risk_on_controlled_apply(tmp_path):
    snapshot = _snapshot()
    high_item = next(item for item in snapshot["owner_review_queue_items"] if item["risk_tier"] == "high")
    high_item["owner_response_required"] = True
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="owner_response_required"):
        load_latest_ai_agent_high_risk_owner_review_queue(tmp_path)


def test_ai_agent_high_risk_owner_review_queue_keeps_critical_on_break_glass(tmp_path):
    snapshot = _snapshot()
    critical_item = next(item for item in snapshot["owner_review_queue_items"] if item["risk_tier"] == "critical")
    critical_item["owner_response_required"] = False
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="owner_response_required"):
        load_latest_ai_agent_high_risk_owner_review_queue(tmp_path)


def test_ai_agent_high_risk_owner_review_queue_requires_rollup_consistency(tmp_path):
    snapshot = _snapshot()
    snapshot["rollups"]["queue_item_count"] = 99
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="rollup counts"):
        load_latest_ai_agent_high_risk_owner_review_queue(tmp_path)


def test_ai_agent_high_risk_owner_review_queue_rejects_private_terms(tmp_path):
    snapshot = _snapshot()
    snapshot["owner_review_queue_items"][0]["display_name"] = "請把 In app browser 內容放進前端"
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="forbidden public terms"):
        load_latest_ai_agent_high_risk_owner_review_queue(tmp_path)


def test_ai_agent_high_risk_owner_review_queue_fails_when_missing(tmp_path):
    with pytest.raises(FileNotFoundError):
        load_latest_ai_agent_high_risk_owner_review_queue(tmp_path)


def _snapshot(*, generated_at: str = "2026-06-19T03:20:00+08:00") -> dict:
    payload = json.loads(_COMMITTED_SNAPSHOT.read_text(encoding="utf-8"))
    cloned = copy.deepcopy(payload)
    cloned["generated_at"] = generated_at
    return cloned


def _write_snapshot(tmp_path, payload: dict) -> None:
    (tmp_path / "ai_agent_high_risk_owner_review_queue_2026-06-19.json").write_text(
        json.dumps(payload),
        encoding="utf-8",
    )
