"""
AI Agent 12-Agent War Room 快照。

讀取最新已提交的 War Room 只讀回報，把 12 位邏輯 Agent 的分工、
工作量、報告合約、市場觀測合約與 Telegram 邊界產品化；本模組不開
runtime writer、不送 Telegram、不呼叫 Bot API、不安裝 SDK、不呼叫付費
API、不讀 secret、不寫 production，也不執行破壞性操作。
"""

from __future__ import annotations

import json
from pathlib import Path
from typing import Any

from src.services.snapshot_paths import default_evaluations_dir

_DEFAULT_EVALUATIONS_DIR = default_evaluations_dir(Path(__file__))
_SNAPSHOT_PATTERN = "ai_agent_12_agent_war_room_*.json"
_SCHEMA_VERSION = "ai_agent_12_agent_war_room_v1"
_RUNTIME_AUTHORITY = "12_agent_war_room_read_only_no_live_write"
_EXPECTED_AGENT_IDS = {
    "agent_01_openclaw_arbiter",
    "agent_02_hermes_rag",
    "agent_03_nemotron_replay",
    "agent_04_sre_sentinel",
    "agent_05_security_sentinel",
    "agent_06_devops_commander",
    "agent_07_data_dr_guardian",
    "agent_08_supply_chain_scout",
    "agent_09_product_ui_curator",
    "agent_10_qa_verifier",
    "agent_11_market_scout",
    "agent_12_telegram_ops_liaison",
}
_ZERO_FIELDS = {
    "live_write_count",
    "telegram_send_count",
    "bot_api_call_count",
    "production_write_count",
    "paid_api_call_count",
    "sdk_install_count",
    "secret_read_count",
    "destructive_operation_count",
}
_FORBIDDEN_PUBLIC_TERMS = {
    "work_window_transcript",
    "chain-of-thought",
    "source_thread_id",
    "browser_context",
    "telegram_token",
    "authorization header",
}


def load_latest_ai_agent_12_agent_war_room(
    evaluations_dir: Path | None = None,
) -> dict[str, Any]:
    """讀取最新已提交的 12-Agent War Room 只讀快照。"""
    directory = evaluations_dir or _DEFAULT_EVALUATIONS_DIR
    candidates = sorted(directory.glob(_SNAPSHOT_PATTERN))
    if not candidates:
        raise FileNotFoundError(f"no AI Agent 12-Agent War Room snapshots found in {directory}")

    latest = candidates[-1]
    with latest.open(encoding="utf-8") as handle:
        payload = json.load(handle)

    if not isinstance(payload, dict):
        raise ValueError(f"{latest}: expected JSON object")

    label = str(latest)
    _require_schema(payload, label)
    _require_agent_roles(payload, label)
    _require_rollups(payload, label)
    _require_contracts(payload, label)
    _require_no_forbidden_public_terms(payload, label)
    return payload


def _require_schema(payload: dict[str, Any], label: str) -> None:
    if payload.get("schema_version") != _SCHEMA_VERSION:
        raise ValueError(f"{label}: expected schema_version={_SCHEMA_VERSION}")

    status = payload.get("program_status") or {}
    expected = {
        "current_priority": "P1",
        "current_task_id": "P2-142",
        "next_task_id": "P2-143",
        "read_only_mode": True,
        "runtime_authority": _RUNTIME_AUTHORITY,
        "overall_completion_percent": 72,
    }
    mismatches = _mismatches(status, expected)
    if mismatches:
        raise ValueError(f"{label}: program_status mismatch: {mismatches}")
    if not status.get("status_note"):
        raise ValueError(f"{label}: program_status.status_note is required")


def _require_agent_roles(payload: dict[str, Any], label: str) -> None:
    roles = payload.get("agent_roles") or []
    if len(roles) != 12:
        raise ValueError(f"{label}: expected exactly 12 agent roles")

    role_ids = {str(role.get("agent_id")) for role in roles}
    if role_ids != _EXPECTED_AGENT_IDS:
        missing = sorted(_EXPECTED_AGENT_IDS - role_ids)
        extra = sorted(role_ids - _EXPECTED_AGENT_IDS)
        raise ValueError(f"{label}: agent ids mismatch missing={missing} extra={extra}")

    for role in roles:
        role_id = role.get("agent_id")
        if role.get("review_status") != "read_only_review_completed":
            raise ValueError(f"{label}: {role_id} must remain read_only_review_completed")
        for field in ("live_write_count", "telegram_send_count", "bot_api_call_count"):
            if role.get(field) != 0:
                raise ValueError(f"{label}: {role_id}.{field} must remain zero")
        for field in ("display_name", "war_room_role", "next_action"):
            if not role.get(field):
                raise ValueError(f"{label}: {role_id}.{field} is required")
        if not isinstance(role.get("work_units"), int) or role["work_units"] <= 0:
            raise ValueError(f"{label}: {role_id}.work_units must be positive")


def _require_rollups(payload: dict[str, Any], label: str) -> None:
    roles = payload.get("agent_roles") or []
    rollups = payload.get("rollups") or {}
    expected = {
        "agent_role_count": len(roles),
        "read_only_review_completed_count": sum(
            1 for role in roles if role.get("review_status") == "read_only_review_completed"
        ),
        "subagent_batch_limit": 6,
        "subagent_batch_count": 2,
        "approval_required_total": sum(int(role.get("approval_required_count") or 0) for role in roles),
        "blocker_total": sum(int(role.get("blocker_count") or 0) for role in roles),
        "total_work_units": sum(int(role.get("work_units") or 0) for role in roles),
        "total_evidence_items": sum(int(role.get("evidence_items") or 0) for role in roles),
    }
    mismatches = _mismatches(rollups, expected)
    if mismatches:
        raise ValueError(f"{label}: rollups mismatch: {mismatches}")

    for field in _ZERO_FIELDS:
        if rollups.get(field) != 0:
            raise ValueError(f"{label}: rollups.{field} must remain zero")


def _require_contracts(payload: dict[str, Any], label: str) -> None:
    coordination = payload.get("coordination_model") or {}
    if coordination.get("logical_agent_count") != 12:
        raise ValueError(f"{label}: coordination_model.logical_agent_count must be 12")
    if coordination.get("subagent_batch_limit") != 6:
        raise ValueError(f"{label}: coordination_model.subagent_batch_limit must be 6")
    if coordination.get("arbiter") != "openclaw":
        raise ValueError(f"{label}: coordination_model.arbiter must remain openclaw")

    telegram = payload.get("telegram_contract") or {}
    for field in ("direct_send_allowed", "bot_api_call_allowed", "success_immediate_send_allowed"):
        if telegram.get(field) is not False:
            raise ValueError(f"{label}: telegram_contract.{field} must remain false")
    for field in ("dedup_required", "receipt_required"):
        if telegram.get(field) is not True:
            raise ValueError(f"{label}: telegram_contract.{field} must remain true")

    redaction = payload.get("display_redaction_contract") or {}
    expected_redaction = {
        "redaction_required": True,
        "conversation_transcript_display_allowed": False,
        "raw_prompt_display_allowed": False,
        "private_reasoning_display_allowed": False,
        "secret_value_display_allowed": False,
        "raw_runtime_payload_display_allowed": False,
    }
    mismatches = _mismatches(redaction, expected_redaction)
    if mismatches:
        raise ValueError(f"{label}: display_redaction_contract mismatch: {mismatches}")

    reporting = payload.get("reporting_contract") or {}
    for cadence in ("daily", "weekly", "monthly"):
        if (reporting.get(cadence) or {}).get("required") is not True:
            raise ValueError(f"{label}: reporting_contract.{cadence}.required must be true")

    market = payload.get("market_watch_contract") or {}
    candidates = market.get("p0_refresh_candidates") or []
    if len(candidates) < 5:
        raise ValueError(f"{label}: market_watch_contract.p0_refresh_candidates must include at least 5 entries")


def _require_no_forbidden_public_terms(payload: dict[str, Any], label: str) -> None:
    public_text = json.dumps(payload, ensure_ascii=False).lower()
    leaked = sorted(term for term in _FORBIDDEN_PUBLIC_TERMS if term.lower() in public_text)
    if leaked:
        raise ValueError(f"{label}: forbidden public terms leaked: {leaked}")


def _mismatches(payload: dict[str, Any], expected: dict[str, Any]) -> dict[str, dict[str, Any]]:
    return {
        key: {"expected": expected_value, "actual": payload.get(key)}
        for key, expected_value in expected.items()
        if payload.get(key) != expected_value
    }
