from __future__ import annotations

import json

import pytest

from src.services.ai_agent_live_read_model_gate import (
    load_latest_ai_agent_live_read_model_gate,
)


def test_load_latest_ai_agent_live_read_model_gate_reads_committed_snapshot():
    data = load_latest_ai_agent_live_read_model_gate()

    assert data["schema_version"] == "ai_agent_live_read_model_gate_v1"
    assert data["program_status"]["overall_completion_percent"] == 55
    assert data["program_status"]["current_task_id"] == "P2-403B"
    assert data["program_status"]["next_task_id"] == "P2-403C"
    assert data["program_status"]["read_only_mode"] is True
    assert data["program_status"]["runtime_authority"] == "gate_plan_only_no_live_worker"
    assert data["existing_storage_contract"]["db_table"] == "agent_sessions"
    assert data["existing_storage_contract"]["approved_for_live_query"] is False
    assert data["existing_storage_contract"]["migration_delta_required"] is False
    assert "output_json" not in data["existing_storage_contract"]["safe_selected_fields"]
    assert data["redis_stream_contract"]["consumer_group_allowed"] is False
    assert data["redis_stream_contract"]["xadd_allowed"] is False
    assert data["live_truth"]["active_live_agent_sessions"] == 0
    assert data["live_truth"]["live_redis_events_24h"] == 0
    assert data["approval_boundaries"]["runtime_worker_allowed"] is False
    assert data["approval_boundaries"]["telegram_direct_send_allowed"] is False
    assert data["display_redaction_contract"]["work_window_conversation_display_allowed"] is False
    assert data["display_redaction_contract"]["agent_raw_output_display_allowed"] is False
    assert data["rollups"]["read_model_card_count"] == len(data["read_model_cards"]) == 5
    assert data["rollups"]["gate_count"] == len(data["worker_gate_plan"]) == 5
    assert data["rollups"]["rollback_step_count"] == len(data["rollback_plan"]) == 4
    assert data["rollups"]["no_write_smoke_count"] == len(data["no_write_smoke_plan"]) == 5
    assert data["rollups"]["live_truth_count_total"] == 0
    assert set(data["rollups"]["query_contract_ready_card_ids"]) == {
        "agent_heartbeat_readback",
        "agent_vote_quality",
        "agent_role_turns",
    }


def test_load_latest_ai_agent_live_read_model_gate_rejects_live_db_query(tmp_path):
    snapshot = _snapshot()
    snapshot["approval_boundaries"]["live_db_query_allowed"] = True
    (tmp_path / "ai_agent_live_read_model_gate_2026-06-11.json").write_text(
        json.dumps(snapshot),
        encoding="utf-8",
    )

    with pytest.raises(ValueError, match="approval boundaries"):
        load_latest_ai_agent_live_read_model_gate(tmp_path)


def test_load_latest_ai_agent_live_read_model_gate_rejects_unsafe_field_projection(tmp_path):
    snapshot = _snapshot()
    snapshot["existing_storage_contract"]["safe_selected_fields"].append("output_json")
    (tmp_path / "ai_agent_live_read_model_gate_2026-06-11.json").write_text(
        json.dumps(snapshot),
        encoding="utf-8",
    )

    with pytest.raises(ValueError, match="forbidden fields"):
        load_latest_ai_agent_live_read_model_gate(tmp_path)


def test_load_latest_ai_agent_live_read_model_gate_rejects_redis_consumer_group(tmp_path):
    snapshot = _snapshot()
    snapshot["redis_stream_contract"]["consumer_group_allowed"] = True
    (tmp_path / "ai_agent_live_read_model_gate_2026-06-11.json").write_text(
        json.dumps(snapshot),
        encoding="utf-8",
    )

    with pytest.raises(ValueError, match="Redis consumer group"):
        load_latest_ai_agent_live_read_model_gate(tmp_path)


def test_load_latest_ai_agent_live_read_model_gate_rejects_write_smoke(tmp_path):
    snapshot = _snapshot()
    snapshot["no_write_smoke_plan"][0]["writes_allowed"] = True
    (tmp_path / "ai_agent_live_read_model_gate_2026-06-11.json").write_text(
        json.dumps(snapshot),
        encoding="utf-8",
    )

    with pytest.raises(ValueError, match="no-write smoke"):
        load_latest_ai_agent_live_read_model_gate(tmp_path)


def test_load_latest_ai_agent_live_read_model_gate_rejects_rollup_mismatch(tmp_path):
    snapshot = _snapshot()
    snapshot["rollups"]["gate_count"] = 99
    (tmp_path / "ai_agent_live_read_model_gate_2026-06-11.json").write_text(
        json.dumps(snapshot),
        encoding="utf-8",
    )

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


def _snapshot() -> dict:
    return {
        "schema_version": "ai_agent_live_read_model_gate_v1",
        "generated_at": "2026-06-11T23:50:00+08:00",
        "program_status": {
            "overall_completion_percent": 55,
            "current_priority": "P2",
            "current_task_id": "P2-403B",
            "next_task_id": "P2-403C",
            "read_only_mode": True,
            "runtime_authority": "gate_plan_only_no_live_worker",
        },
        "source_refs": ["test"],
        "live_truth": {
            "live_agent_session_readback_enabled": False,
            "live_redis_stream_read_enabled": False,
            "runtime_worker_enabled": False,
            "telegram_receipt_send_enabled": False,
            "learning_writeback_enabled": False,
            "active_live_agent_sessions": 0,
            "live_redis_events_24h": 0,
            "live_handoffs_24h": 0,
            "live_learning_writes_24h": 0,
            "telegram_digest_receipts_24h": 0,
        },
        "existing_storage_contract": {
            "db_table": "agent_sessions",
            "schema_status": "existing",
            "migration_delta_required": False,
            "approved_for_live_query": False,
            "safe_read_query_defined": True,
            "safe_selected_fields": ["id", "session_id", "agent_role", "created_at"],
            "forbidden_selected_fields": ["output_json", "raw_prompt", "secret_plaintext"],
            "required_indexes": ["ix_agent_sessions_created_at"],
            "read_query_contract": "SELECT id FROM agent_sessions LIMIT :safe_limit",
        },
        "redis_stream_contract": {
            "stream_namespace": "awoooi:agent:*",
            "candidate_streams": ["awoooi:agent:events"],
            "consumer_group_allowed": False,
            "xadd_allowed": False,
            "xreadgroup_allowed": False,
            "event_envelope_required_fields": ["event_id", "session_id", "agent_id"],
        },
        "read_model_cards": [
            _card("agent_heartbeat_readback", "query_contract_ready"),
            _card("redis_message_receipts", "approval_required"),
        ],
        "worker_gate_plan": [
            _gate("db_read_model_no_write_smoke", "approval_required"),
            _gate("worker_kill_switch", "blocked"),
        ],
        "rollback_plan": [
            {"rollback_id": "disable", "step": "停用。", "owner_agent": "openclaw"},
        ],
        "no_write_smoke_plan": [
            {
                "smoke_id": "loader",
                "status": "defined",
                "writes_allowed": False,
                "assertion": "測試。",
            },
        ],
        "display_redaction_contract": {
            "redaction_required": True,
            "work_window_conversation_display_allowed": False,
            "agent_raw_output_display_allowed": False,
            "secret_value_display_allowed": False,
            "forbidden_frontend_content": ["工作視窗內容"],
        },
        "approval_boundaries": {
            "db_migration_allowed": False,
            "live_db_query_allowed": False,
            "redis_xadd_allowed": False,
            "redis_consumer_group_allowed": False,
            "runtime_worker_allowed": False,
            "telegram_direct_send_allowed": False,
            "learning_writeback_allowed": False,
            "secret_plaintext_allowed": False,
            "conversation_transcript_display_allowed": False,
            "private_reasoning_display_allowed": False,
            "agent_raw_output_display_allowed": False,
        },
        "rollups": {
            "source_ref_count": 1,
            "read_model_card_count": 2,
            "gate_count": 2,
            "approval_required_gate_ids": [
                "db_read_model_no_write_smoke",
                "worker_kill_switch",
            ],
            "query_contract_ready_card_ids": ["agent_heartbeat_readback"],
            "rollback_step_count": 1,
            "no_write_smoke_count": 1,
            "forbidden_frontend_content_count": 1,
            "live_truth_count_total": 0,
        },
    }


def _card(card_id: str, status: str) -> dict:
    return {
        "card_id": card_id,
        "display_name": card_id,
        "owner_agent": "openclaw",
        "source_of_truth": "agent_sessions",
        "readiness_status": status,
        "operator_signal": "測試。",
        "next_gate": "測試。",
    }


def _gate(gate_id: str, status: str) -> dict:
    return {
        "gate_id": gate_id,
        "display_name": gate_id,
        "owner_agent": "openclaw",
        "status": status,
        "required_evidence": "測試。",
        "blocked_action": "test",
    }
