"""
IwoooS security control coverage rollup.

This service consolidates committed security inventory snapshots into one
read-only control-plane view. It never queries live hosts, Wazuh, Kali,
Kubernetes, Docker, Nginx, Telegram, or secret stores.
"""

from __future__ import annotations

import json
from pathlib import Path
from typing import Any

from src.services.snapshot_paths import default_evaluations_dir, default_security_dir

_DEFAULT_SECURITY_DIR = default_security_dir(Path(__file__))
_DEFAULT_EVALUATIONS_DIR = default_evaluations_dir(Path(__file__))
_SCHEMA_VERSION = "iwooos_security_control_coverage_v1"

_SECURITY_SNAPSHOTS = {
    "asset_ledger": "security-asset-control-ledger.snapshot.json",
    "host_service": "host-service-config-inventory.snapshot.json",
    "monitoring": "monitoring-alerting-observability-inventory.snapshot.json",
    "ssh_network": "ssh-network-access-inventory.snapshot.json",
    "wazuh_hosts": "wazuh-managed-host-coverage-gate.snapshot.json",
    "agent_bounty": "agent-bounty-iwooos-onboarding-handoff.snapshot.json",
}


def load_latest_iwooos_security_control_coverage(
    security_dir: Path | None = None,
    evaluations_dir: Path | None = None,
) -> dict[str, Any]:
    """Load committed security-control inventory snapshots as one rollup."""
    sec_dir = security_dir or _DEFAULT_SECURITY_DIR
    eval_dir = evaluations_dir or _DEFAULT_EVALUATIONS_DIR

    snapshots = {
        key: _load_json(sec_dir / filename)
        for key, filename in _SECURITY_SNAPSHOTS.items()
    }
    runtime_inventory = _load_latest(eval_dir, "runtime_surface_inventory_*.json")
    ai_inventory = _load_latest(eval_dir, "ai_agent_automation_inventory_snapshot_*.json")
    snapshots["runtime_surface"] = runtime_inventory
    snapshots["ai_agent_automation"] = ai_inventory

    _require_snapshot_schemas(snapshots)
    _require_zero_runtime_boundaries(snapshots)

    domains = _build_domains(snapshots)
    summary = _build_summary(snapshots, domains)

    return {
        "schema_version": _SCHEMA_VERSION,
        "status": "committed_scope_rollup_ready_with_controlled_apply_exception",
        "mode": "committed_snapshot_rollup_only_no_live_runtime_query",
        "summary": summary,
        "domains": domains,
        "p0_next_actions": _build_p0_next_actions(),
        "no_false_green_rules": [
            "納管覆蓋總表只代表 committed snapshot 可讀，不代表所有主機已被 Wazuh manager registry 驗收。",
            "route 200、transport observed、UI 可見、一般工作批准都不能當成 runtime 授權。",
            "IwoooS ledger 的 owner response received / accepted、live evidence accepted、active scan、active response、Telegram send、host write 仍維持 0 / false；這不阻擋 AwoooP allowlisted controlled apply。",
            "Nginx、Firewall、Workflow、Secret、K8s、Docker、systemd、AI Agent provider 變更都必須先進 execution packet、check-mode、rollback、verifier 與 KM / PlayBook trust，不得繞過受控路由。",
        ],
        "source_refs": [
            "docs/security/security-asset-control-ledger.snapshot.json",
            "docs/security/host-service-config-inventory.snapshot.json",
            "docs/security/monitoring-alerting-observability-inventory.snapshot.json",
            "docs/security/ssh-network-access-inventory.snapshot.json",
            "docs/security/wazuh-managed-host-coverage-gate.snapshot.json",
            "docs/security/agent-bounty-iwooos-onboarding-handoff.snapshot.json",
            f"docs/evaluations/{runtime_inventory['_snapshot_name']}",
            f"docs/evaluations/{ai_inventory['_snapshot_name']}",
        ],
    }


def _load_json(path: Path) -> dict[str, Any]:
    with path.open(encoding="utf-8") as handle:
        payload = json.load(handle)
    if not isinstance(payload, dict):
        raise ValueError(f"{path}: expected JSON object")
    payload["_snapshot_name"] = path.name
    return payload


def _load_latest(directory: Path, pattern: str) -> dict[str, Any]:
    candidates = sorted(directory.glob(pattern))
    if not candidates:
        raise FileNotFoundError(f"no snapshots found: {directory / pattern}")
    return _load_json(candidates[-1])


def _require_snapshot_schemas(snapshots: dict[str, dict[str, Any]]) -> None:
    expected = {
        "asset_ledger": "security_asset_control_ledger_v1",
        "host_service": "host_service_config_inventory_v1",
        "monitoring": "monitoring_alerting_observability_inventory_v1",
        "ssh_network": "ssh_network_access_inventory_v1",
        "wazuh_hosts": "wazuh_managed_host_coverage_gate_v1",
        "agent_bounty": "agent_bounty_iwooos_onboarding_handoff_v1",
        "runtime_surface": "runtime_surface_inventory_v1",
        "ai_agent_automation": "ai_agent_automation_inventory_snapshot_v1",
    }
    for key, schema in expected.items():
        actual = snapshots[key].get("schema_version")
        if actual != schema:
            raise ValueError(f"{key}: expected schema_version={schema}, got {actual!r}")


def _require_zero_runtime_boundaries(snapshots: dict[str, dict[str, Any]]) -> None:
    for key in ("asset_ledger", "host_service", "monitoring", "ssh_network", "wazuh_hosts"):
        boundaries = snapshots[key].get("execution_boundaries") or {}
        allowed = sorted(
            name
            for name, value in boundaries.items()
            if name != "not_authorization" and value is not False
        )
        if allowed:
            raise ValueError(f"{key}: execution boundaries must stay false: {allowed}")

    runtime_approvals = snapshots["runtime_surface"].get("approval_boundaries") or {}
    allowed_runtime = sorted(name for name, value in runtime_approvals.items() if value is not False)
    if allowed_runtime:
        raise ValueError(f"runtime_surface: approval boundaries must stay false: {allowed_runtime}")

    runtime_operations = snapshots["runtime_surface"].get("operation_boundaries") or {}
    if runtime_operations.get("read_only_api_allowed") is not True:
        raise ValueError("runtime_surface: read_only_api_allowed must remain true")
    blocked_runtime_ops = {
        "live_k8s_query_allowed",
        "kubectl_allowed",
        "rollout_allowed",
        "restart_allowed",
        "scale_allowed",
        "delete_allowed",
        "secret_read_allowed",
        "secret_plaintext_allowed",
        "active_scan_allowed",
        "production_route_change_allowed",
    }
    allowed_ops = sorted(name for name in blocked_runtime_ops if runtime_operations.get(name) is not False)
    if allowed_ops:
        raise ValueError(f"runtime_surface: operation boundaries must stay false: {allowed_ops}")

    ai_program = snapshots["ai_agent_automation"].get("program_status") or {}
    if ai_program.get("read_only_mode") is not True:
        raise ValueError("ai_agent_automation: read_only_mode must remain true")
    ai_approvals = snapshots["ai_agent_automation"].get("approval_boundaries") or {}
    allowed_ai = sorted(name for name, value in ai_approvals.items() if value is not False)
    if allowed_ai:
        raise ValueError(f"ai_agent_automation: approval boundaries must stay false: {allowed_ai}")

    agent_bounty_summary = snapshots["agent_bounty"].get("summary") or {}
    blocked_agent_bounty = {
        "owner_response_received",
        "owner_response_accepted",
        "repo_refs_truth_accepted",
        "data_classification_accepted",
        "deployment_boundary_accepted",
        "external_agent_boundary_accepted",
        "runtime_execution_authorized",
        "runtime_gate_open",
        "production_deploy_authorized",
        "workflow_modification_authorized",
        "secret_value_collection_authorized",
        "external_agent_autonomy_authorized",
        "auto_claim_submit_authorized",
        "bounty_payout_authorized",
    }
    allowed_agent_bounty = sorted(
        name for name in blocked_agent_bounty if agent_bounty_summary.get(name) is not False
    )
    if allowed_agent_bounty:
        raise ValueError(f"agent_bounty: blocked summary flags must stay false: {allowed_agent_bounty}")


def _build_domains(snapshots: dict[str, dict[str, Any]]) -> list[dict[str, Any]]:
    asset_summary = snapshots["asset_ledger"].get("summary") or {}
    host_summary = snapshots["host_service"].get("summary") or {}
    monitoring_summary = snapshots["monitoring"].get("summary") or {}
    ssh_summary = snapshots["ssh_network"].get("summary") or {}
    wazuh_summary = snapshots["wazuh_hosts"].get("summary") or {}
    runtime_rollups = snapshots["runtime_surface"].get("rollups") or {}
    runtime_program = snapshots["runtime_surface"].get("program_status") or {}
    agent_bounty_summary = snapshots["agent_bounty"].get("summary") or {}
    ai_program = snapshots["ai_agent_automation"].get("program_status") or {}
    ai_assets = snapshots["ai_agent_automation"].get("assets") or []

    return [
        {
            "domain_id": "high_value_asset_control",
            "label": "高價值資產與配置總帳",
            "priority": "P0",
            "coverage_percent": _as_int(asset_summary.get("security_asset_control_ledger_completion_percent")),
            "scope_count": _as_int(asset_summary.get("asset_group_count")),
            "write_capable_count": _as_int(asset_summary.get("c0_asset_group_count")),
            "accepted_count": _as_int(asset_summary.get("owner_response_accepted_count")),
            "blocked_count": _as_int(asset_summary.get("owner_packet_required_count")),
            "status": "owner_packet_required",
            "next_gate": "owner_packet_and_redacted_live_evidence",
            "source_refs": ["docs/security/security-asset-control-ledger.snapshot.json"],
        },
        {
            "domain_id": "host_service_runtime",
            "label": "主機服務 / Docker / systemd",
            "priority": "P0",
            "coverage_percent": _as_int(host_summary.get("coverage_percent_after_inventory")),
            "scope_count": _as_int(host_summary.get("surface_count")),
            "write_capable_count": _as_int(host_summary.get("write_capable_surface_count")),
            "accepted_count": _as_int(host_summary.get("owner_response_accepted_count")),
            "blocked_count": _as_int(host_summary.get("surfaces_requiring_owner_response_count")),
            "status": "waiting_live_hash_and_owner_response",
            "next_gate": "host_live_hash_restart_window_rollback_owner",
            "source_refs": ["docs/security/host-service-config-inventory.snapshot.json"],
        },
        {
            "domain_id": "monitoring_alerting_observability",
            "label": "監控 / 告警 / 可觀測性 / 通知",
            "priority": "P0",
            "coverage_percent": _as_int(monitoring_summary.get("coverage_percent_after_inventory")),
            "scope_count": _as_int(monitoring_summary.get("surface_count")),
            "write_capable_count": _as_int(monitoring_summary.get("write_capable_surface_count")),
            "accepted_count": _as_int(monitoring_summary.get("owner_response_accepted_count")),
            "blocked_count": _as_int(monitoring_summary.get("surfaces_requiring_owner_response_count")),
            "status": "waiting_receiver_route_and_receipt_evidence",
            "next_gate": "alert_readability_receiver_receipt_reload_owner",
            "source_refs": ["docs/security/monitoring-alerting-observability-inventory.snapshot.json"],
        },
        {
            "domain_id": "ssh_firewall_network_access",
            "label": "SSH / Firewall / WireGuard / NodePort / NetworkPolicy",
            "priority": "P0",
            "coverage_percent": _as_int(ssh_summary.get("coverage_percent_after_inventory")),
            "scope_count": _as_int(ssh_summary.get("surface_count")),
            "write_capable_count": _as_int(ssh_summary.get("write_capable_surface_count")),
            "accepted_count": _as_int(ssh_summary.get("owner_response_accepted_count")),
            "blocked_count": _as_int(ssh_summary.get("surfaces_requiring_owner_response_count")),
            "status": "waiting_actor_before_after_and_recurrence_guard",
            "next_gate": "post_incident_network_change_readback",
            "source_refs": ["docs/security/ssh-network-access-inventory.snapshot.json"],
        },
        {
            "domain_id": "awoooi_runtime_surfaces",
            "label": "AWOOOI runtime 工作負載 / Secret / Ingress / CronJob",
            "priority": "P0",
            "coverage_percent": _as_int(runtime_program.get("overall_completion_percent")),
            "scope_count": _as_int(runtime_rollups.get("total_surfaces")),
            "write_capable_count": len(runtime_rollups.get("secret_surface_ids") or []),
            "accepted_count": 0,
            "blocked_count": len(runtime_rollups.get("action_required_surface_ids") or []),
            "status": "manifest_mapped_read_only_runtime_gate_closed",
            "next_gate": "live_runtime_binding_owner_acceptance",
            "source_refs": [f"docs/evaluations/{snapshots['runtime_surface']['_snapshot_name']}"],
        },
        {
            "domain_id": "wazuh_managed_host_coverage",
            "label": "Wazuh 主機納管與 manager registry",
            "priority": "P0",
            "coverage_percent": 70 if _as_int(wazuh_summary.get("manager_registry_accepted_count")) else 0,
            "scope_count": _as_int(wazuh_summary.get("expected_host_scope_count")),
            "write_capable_count": _as_int(wazuh_summary.get("agent_reenroll_authorized_count")),
            "accepted_count": _as_int(wazuh_summary.get("manager_registry_accepted_count")),
            "blocked_count": max(
                _as_int(wazuh_summary.get("expected_host_scope_count"))
                - _as_int(wazuh_summary.get("manager_registry_accepted_count")),
                0,
            ),
            "status": (
                "manager_registry_readback_accepted_runtime_gate_closed"
                if _as_int(wazuh_summary.get("manager_registry_accepted_count"))
                else "waiting_manager_registry_readback"
            ),
            "next_gate": "runtime_gate_owner_review_and_postcheck",
            "source_refs": ["docs/security/wazuh-managed-host-coverage-gate.snapshot.json"],
        },
        {
            "domain_id": "agent_bounty_protocol",
            "label": "agent-bounty-protocol 產品邊界 / MCP / A2A",
            "priority": "P0",
            "coverage_percent": _as_int(agent_bounty_summary.get("onboarding_handoff_completion_percent")),
            "scope_count": len(snapshots["agent_bounty"].get("product_surfaces") or []),
            "write_capable_count": 0,
            "accepted_count": 0,
            "blocked_count": len(snapshots["agent_bounty"].get("product_surfaces") or []),
            "status": "draft_waiting_owner_review_runtime_gate_closed",
            "next_gate": "repo_refs_data_classification_deployment_boundary_owner_acceptance",
            "source_refs": ["docs/security/agent-bounty-iwooos-onboarding-handoff.snapshot.json"],
        },
        {
            "domain_id": "ai_agent_automation",
            "label": "AI Agent / Provider / 自動化資產",
            "priority": "P0",
            "coverage_percent": _as_int(ai_program.get("overall_completion_percent")),
            "scope_count": len(ai_assets),
            "write_capable_count": 0,
            "accepted_count": 0,
            "blocked_count": len(
                [
                    asset
                    for asset in ai_assets
                    if isinstance(asset, dict) and asset.get("status") != "done"
                ]
            ),
            "status": "read_only_inventory_runtime_write_gate_closed",
            "next_gate": "owner_approved_runtime_write_gate_and_replay_shadow_canary",
            "source_refs": [f"docs/evaluations/{snapshots['ai_agent_automation']['_snapshot_name']}"],
        },
    ]


def _build_summary(snapshots: dict[str, dict[str, Any]], domains: list[dict[str, Any]]) -> dict[str, Any]:
    visible_scope_count = sum(_as_int(domain.get("scope_count")) for domain in domains)
    write_capable_count = sum(_as_int(domain.get("write_capable_count")) for domain in domains)
    blocked_count = sum(_as_int(domain.get("blocked_count")) for domain in domains)
    accepted_count = sum(_as_int(domain.get("accepted_count")) for domain in domains)
    coverage_values = [_as_int(domain.get("coverage_percent")) for domain in domains]

    return {
        "source_snapshot_count": 8,
        "control_domain_count": len(domains),
        "visible_scope_unit_count": visible_scope_count,
        "write_capable_scope_count": write_capable_count,
        "blocked_scope_count": blocked_count,
        "accepted_scope_count": accepted_count,
        "control_plane_visibility_percent": round(sum(coverage_values) / len(coverage_values)),
        "actual_runtime_acceptance_percent": 0,
        "runtime_gate_count": 0,
        "owner_response_received_count": 0,
        "owner_response_accepted_count": 0,
        "live_evidence_accepted_count": 0,
        "wazuh_manager_registry_accepted_count": _summary_int(
            snapshots["wazuh_hosts"],
            "manager_registry_accepted_count",
        ),
        "active_scan_authorized_count": 0,
        "active_response_authorized_count": 0,
        "telegram_send_authorized_count": 0,
        "host_write_authorized_count": 0,
        "secret_value_collected_count": 0,
        "agent_bounty_runtime_gate_open_count": 0,
        "ai_agent_runtime_write_gate_open_count": 0,
        "asset_group_count": _summary_int(snapshots["asset_ledger"], "asset_group_count"),
        "host_service_surface_count": _summary_int(snapshots["host_service"], "surface_count"),
        "monitoring_surface_count": _summary_int(snapshots["monitoring"], "surface_count"),
        "ssh_network_surface_count": _summary_int(snapshots["ssh_network"], "surface_count"),
        "runtime_surface_count": _as_int((snapshots["runtime_surface"].get("rollups") or {}).get("total_surfaces")),
        "wazuh_expected_host_scope_count": _summary_int(snapshots["wazuh_hosts"], "expected_host_scope_count"),
        "agent_bounty_product_surface_count": len(snapshots["agent_bounty"].get("product_surfaces") or []),
        "ai_agent_asset_count": len(snapshots["ai_agent_automation"].get("assets") or []),
        "all_scope_runtime_controlled": False,
        "allowlisted_controlled_apply_bypasses_iwooos_ledger": True,
        "controlled_apply_policy": "low_medium_high_allowed_after_allowlist_check_mode_rollback_verifier_km",
        "critical_break_glass_required": True,
    }


def _build_p0_next_actions() -> list[dict[str, str]]:
    return [
        {
            "priority": "P0-01",
            "title": "Wazuh manager registry 全主機交叉驗收",
            "required_evidence": "manager registry、agent status、dashboard API / RBAC / TLS readback、缺席主機 owner decision。",
        },
        {
            "priority": "P0-02",
            "title": "Host / Docker / systemd live hash 與維護窗口",
            "required_evidence": "live config hash、restart window、rollback owner、post-check 指標、drift disposition。",
        },
        {
            "priority": "P0-03",
            "title": "Nginx / 公開入口 / Firewall 變更控管",
            "required_evidence": "脫敏 live conf export、rendered diff、nginx -t、route smoke、actor before / after。",
        },
        {
            "priority": "P0-04",
            "title": "監控告警卡片化與 receipt",
            "required_evidence": "可讀卡片格式、receiver route、Telegram / webhook receipt、silence / dedup / inhibit review。",
        },
        {
            "priority": "P0-05",
            "title": "AI Agent runtime write gate",
            "required_evidence": "allowlist、check-mode、rollback、verifier、KM / PlayBook trust；付費 provider / replacement 另需 replay / shadow / canary。",
        },
        {
            "priority": "P0-06",
            "title": "agent-bounty-protocol 安全納管",
            "required_evidence": "repo refs truth、data classification、MCP / A2A abuse boundary、deployment boundary、owner acceptance。",
        },
    ]


def _summary_int(snapshot: dict[str, Any], key: str) -> int:
    return _as_int((snapshot.get("summary") or {}).get(key))


def _as_int(value: Any) -> int:
    return value if isinstance(value, int) else 0
