"""
Product code review gate snapshot.

Loads the latest committed, read-only all-product code-review gate and enriches
it with the existing AwoooP tenant asset inventory. The loader never enables
external scanners, writes workflows, auto-merges code, deploys, reads secrets,
pushes registry artifacts, sends Telegram messages, or opens runtime gates.
"""

from __future__ import annotations

import json
from copy import deepcopy
from pathlib import Path
from typing import Any

from src.services.platform_operator_service import build_tenant_asset_inventory
from src.services.snapshot_paths import default_evaluations_dir

_DEFAULT_EVALUATIONS_DIR = default_evaluations_dir(Path(__file__))
_SNAPSHOT_PATTERN = "product_code_review_gate_*.json"
_SCHEMA_VERSION = "product_code_review_gate_v1"

_BLOCKED_BOUNDARY_FLAGS = {
    "workflow_write_allowed",
    "external_scanner_activation_allowed",
    "paid_ai_review_allowed",
    "repo_app_install_allowed",
    "auto_merge_allowed",
    "production_deploy_authorized",
    "aider_auto_patch_allowed",
    "elephantalpha_write_allowed",
    "secret_read_allowed",
    "post_deploy_write_allowed",
    "runtime_execution_allowed",
    "telegram_send_allowed",
    "gateway_queue_write_allowed",
    "host_probe_allowed",
    "registry_push_allowed",
    "artifact_signing_allowed",
    "action_buttons_allowed",
}


def load_latest_product_code_review_gate(
    evaluations_dir: Path | None = None,
) -> dict[str, Any]:
    """Load the newest committed all-product code-review gate snapshot."""
    directory = evaluations_dir or _DEFAULT_EVALUATIONS_DIR
    candidates = sorted(directory.glob(_SNAPSHOT_PATTERN))
    if not candidates:
        raise FileNotFoundError(f"no product code review gate 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")

    inventory = build_tenant_asset_inventory([])
    enriched = deepcopy(payload)
    enriched["tenant_asset_inventory_summary"] = inventory.get("summary") or {}
    enriched["product_review_matrix"] = _build_product_review_matrix(inventory)

    _require_schema(enriched, _SCHEMA_VERSION, str(latest))
    _require_read_only_boundaries(enriched, str(latest))
    _require_rollup_consistency(enriched, str(latest))
    _require_gate_evidence(enriched, str(latest))
    _require_agent_boundaries(enriched, str(latest))
    return enriched


def _build_product_review_matrix(inventory: dict[str, Any]) -> list[dict[str, Any]]:
    products = inventory.get("products") or []
    matrix: list[dict[str, Any]] = []
    for product in products:
        status = product.get("coverage_status") or "read_only_candidate"
        source_repo_count = int(product.get("source_repo_count") or 0)
        public_route_count = int(product.get("public_route_count") or 0)
        gate_state = "owner_review_required" if status == "owner_response_required" else "read_only_visible"
        if source_repo_count == 0:
            gate_state = "source_mapping_required"
        matrix.append(
            {
                "product_id": product.get("product_id"),
                "product_name": product.get("product_name"),
                "category": product.get("category"),
                "surface_kind": product.get("surface_kind"),
                "owner_lane": product.get("owner_lane"),
                "coverage_status": status,
                "public_route_count": public_route_count,
                "source_repo_count": source_repo_count,
                "gate_state": gate_state,
                "pre_deploy_gate": "required",
                "post_deploy_gate": "required",
                "owner_response_received_count": int(
                    product.get("owner_response_received_count") or 0
                ),
                "owner_response_accepted_count": int(
                    product.get("owner_response_accepted_count") or 0
                ),
                "runtime_gate_count": int(product.get("runtime_gate_count") or 0),
                "action_button_count": int(product.get("action_button_count") or 0),
            }
        )
    return matrix


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


def _require_read_only_boundaries(payload: dict[str, Any], label: str) -> None:
    program_status = payload.get("program_status") or {}
    if program_status.get("read_only_mode") is not True:
        raise ValueError(f"{label}: program_status.read_only_mode must be true")

    boundaries = payload.get("gate_boundaries") or {}
    if boundaries.get("read_only_api_allowed") is not True:
        raise ValueError(f"{label}: read_only_api_allowed must be true")

    allowed = sorted(flag for flag in _BLOCKED_BOUNDARY_FLAGS if boundaries.get(flag) is not False)
    if allowed:
        raise ValueError(f"{label}: gate boundaries must remain false: {allowed}")


def _require_rollup_consistency(payload: dict[str, Any], label: str) -> None:
    rollups = payload.get("rollups") or {}
    tenant_summary = payload.get("tenant_asset_inventory_summary") or {}
    product_matrix = payload.get("product_review_matrix") or []
    pre_deploy = payload.get("pre_deploy_gates") or []
    post_deploy = payload.get("post_deploy_gates") or []
    reviewers = payload.get("ai_reviewer_lanes") or []
    tools = payload.get("mainstream_tool_lanes") or []
    boundaries = payload.get("gate_boundaries") or {}

    product_count = int(tenant_summary.get("product_surface_count") or 0)
    route_count = int(tenant_summary.get("public_route_count") or 0)
    source_count = int(tenant_summary.get("source_candidate_repo_count") or 0)

    if rollups.get("product_scope_count") != product_count:
        raise ValueError(f"{label}: rollups.product_scope_count must match tenant inventory")
    if rollups.get("product_scope_count") != len(product_matrix):
        raise ValueError(f"{label}: product_review_matrix length must match product scope count")
    if route_count < int(rollups.get("public_route_count_minimum") or 0):
        raise ValueError(f"{label}: tenant route count is lower than product gate minimum")
    if rollups.get("source_candidate_repo_count") != source_count:
        raise ValueError(f"{label}: source candidate count must match tenant inventory")
    if rollups.get("pre_deploy_gate_count") != len(pre_deploy):
        raise ValueError(f"{label}: pre_deploy_gate_count must match gates")
    if rollups.get("post_deploy_gate_count") != len(post_deploy):
        raise ValueError(f"{label}: post_deploy_gate_count must match gates")
    if rollups.get("ai_reviewer_count") != len(reviewers):
        raise ValueError(f"{label}: ai_reviewer_count must match reviewer lanes")
    if rollups.get("mainstream_tool_count") != len(tools):
        raise ValueError(f"{label}: mainstream_tool_count must match tool lanes")

    false_count = sum(1 for flag in _BLOCKED_BOUNDARY_FLAGS if boundaries.get(flag) is False)
    if rollups.get("blocked_operation_count") != false_count:
        raise ValueError(f"{label}: blocked_operation_count must match false boundaries")
    if rollups.get("active_write_gate_count") != 0:
        raise ValueError(f"{label}: active_write_gate_count must remain 0")
    if rollups.get("action_button_count") != 0:
        raise ValueError(f"{label}: action_button_count must remain 0")


def _require_gate_evidence(payload: dict[str, Any], label: str) -> None:
    for key in ("pre_deploy_gates", "post_deploy_gates"):
        for gate in payload.get(key) or []:
            gate_id = gate.get("gate_id") or "<missing>"
            if not gate.get("evidence_refs"):
                raise ValueError(f"{label}: gate {gate_id} must include evidence_refs")
            if not gate.get("next_action"):
                raise ValueError(f"{label}: gate {gate_id} must include next_action")


def _require_agent_boundaries(payload: dict[str, Any], label: str) -> None:
    reviewers = payload.get("ai_reviewer_lanes") or []
    for reviewer in reviewers:
        agent_id = reviewer.get("agent_id") or "<missing>"
        if reviewer.get("write_allowed") is not False:
            raise ValueError(f"{label}: reviewer {agent_id} write_allowed must remain false")

    matrix = payload.get("product_review_matrix") or []
    active_runtime = [item for item in matrix if item.get("runtime_gate_count") != 0]
    action_buttons = [item for item in matrix if item.get("action_button_count") != 0]
    if active_runtime:
        raise ValueError(f"{label}: product runtime gates must remain 0")
    if action_buttons:
        raise ValueError(f"{label}: product action buttons must remain 0")
