from __future__ import annotations

import json

import pytest

from src.services.ai_agent_version_lifecycle_update_proposal import (
    load_latest_ai_agent_version_lifecycle_update_proposal,
)


def test_load_latest_ai_agent_version_lifecycle_update_proposal_reads_committed_snapshot():
    data = load_latest_ai_agent_version_lifecycle_update_proposal()

    assert data["schema_version"] == "ai_agent_version_lifecycle_update_proposal_v1"
    assert data["program_status"]["overall_completion_percent"] == 78
    assert data["program_status"]["current_task_id"] == "P2-413"
    assert data["program_status"]["next_task_id"] == "P2-414"
    assert data["program_status"]["read_only_mode"] is True
    assert data["program_status"]["runtime_authority"] == (
        "version_lifecycle_update_proposal_only_no_write_or_upgrade"
    )
    assert data["runtime_boundaries"]["read_only_update_proposal_allowed"] is True
    assert data["runtime_boundaries"]["package_upgrade_allowed"] is False
    assert data["runtime_boundaries"]["host_upgrade_allowed"] is False
    assert data["runtime_boundaries"]["k3s_upgrade_allowed"] is False
    assert data["runtime_boundaries"]["telegram_direct_send_allowed"] is False
    assert data["runtime_boundaries"]["production_write_allowed"] is False
    assert data["runtime_boundaries"]["openclaw_replacement_allowed"] is False
    assert data["telegram_digest_contract"]["direct_send_allowed"] is False
    assert data["telegram_digest_contract"]["gateway_queue_write_allowed"] is False
    assert data["telegram_digest_contract"]["bot_api_call_allowed"] is False
    assert data["rollups"]["domain_count"] == len(data["lifecycle_domains"]) == 12
    assert data["rollups"]["proposal_count"] == len(data["update_proposals"]) == 12
    assert data["rollups"]["cadence_count"] == len(data["cadence_matrix"]) == 6
    assert data["rollups"]["approval_gate_count"] == len(data["approval_gate_matrix"]) == 9
    assert data["rollups"]["false_runtime_boundary_count"] == 29
    assert data["rollups"]["auto_execution_allowed_count"] == 0
    assert data["rollups"]["telegram_direct_send_count"] == 0
    assert data["rollups"]["production_write_count"] == 0
    assert data["rollups"]["update_allowed_count"] == 0
    assert any(
        proposal["proposal_id"] == "openclaw_challenger_replay_bench"
        for proposal in data["update_proposals"]
    )
    assert all(proposal["requires_owner_approval"] is True for proposal in data["update_proposals"])
    assert all(proposal["direct_update_allowed"] is False for proposal in data["update_proposals"])


def test_ai_agent_version_lifecycle_update_proposal_rejects_runtime_upgrade(tmp_path):
    snapshot = _snapshot()
    snapshot["runtime_boundaries"]["package_upgrade_allowed"] = True
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="runtime boundaries"):
        load_latest_ai_agent_version_lifecycle_update_proposal(tmp_path)


def test_ai_agent_version_lifecycle_update_proposal_rejects_rollup_mismatch(tmp_path):
    snapshot = _snapshot()
    snapshot["rollups"]["proposal_count"] = 99
    _write_snapshot(tmp_path, snapshot)

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


def test_ai_agent_version_lifecycle_update_proposal_rejects_direct_update(tmp_path):
    snapshot = _snapshot()
    snapshot["update_proposals"][0]["direct_update_allowed"] = True
    snapshot["rollups"]["read_only_proposal_count"] = 11
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="direct update"):
        load_latest_ai_agent_version_lifecycle_update_proposal(tmp_path)


def test_ai_agent_version_lifecycle_update_proposal_rejects_missing_evidence(tmp_path):
    snapshot = _snapshot()
    snapshot["update_proposals"][0]["evidence_refs"] = []
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="evidence_refs"):
        load_latest_ai_agent_version_lifecycle_update_proposal(tmp_path)


def test_ai_agent_version_lifecycle_update_proposal_rejects_work_window_markers(tmp_path):
    snapshot = _snapshot()
    snapshot["program_status"]["status_note"] = "不可放入 My request for Codex"
    _write_snapshot(tmp_path, snapshot)

    with pytest.raises(ValueError, match="forbidden work-window conversation content"):
        load_latest_ai_agent_version_lifecycle_update_proposal(tmp_path)


def _write_snapshot(tmp_path, snapshot: dict) -> None:
    (tmp_path / "ai_agent_version_lifecycle_update_proposal_2026-06-26.json").write_text(
        json.dumps(snapshot),
        encoding="utf-8",
    )


def _snapshot() -> dict:
    return json.loads(json.dumps(load_latest_ai_agent_version_lifecycle_update_proposal()))
