#!/usr/bin/env python3
"""Build the AWOOOI AI technology radar readback artifact."""

from __future__ import annotations

import argparse
import json
from collections import defaultdict
from datetime import datetime, timezone
from pathlib import Path
from typing import Any


def build_radar(
    *,
    technology_watch: dict[str, Any],
    agent_market_radar: dict[str, Any],
    evidence_commit: str,
    generated_at: str | None = None,
) -> dict[str, Any]:
    """Build a read-only AI technology radar readback from committed evidence."""
    _require_schema(technology_watch, "ai_technology_watch_report_v1", "technology_watch")
    _require_schema(agent_market_radar, "ai_agent_market_radar_readback_v1", "agent_market_radar")

    watch_summary = technology_watch.get("summary") or {}
    agent_summary = agent_market_radar.get("summary") or {}
    source_count = int(watch_summary.get("source_count", 0))
    failure_count = int(watch_summary.get("source_failure_count", 0))
    success_rate = _success_rate(source_count, failure_count)

    return {
        "schema_version": "ai_technology_radar_readback_v1",
        "generated_at": generated_at or datetime.now(timezone.utc).isoformat(),
        "source_scope": {
            "technology_watch_report": "docs/evaluations/ai_technology_watch_report_2026-06-25.json",
            "technology_source_registry": "docs/ai/ai-technology-watch-sources.v1.json",
            "agent_market_radar_readback": "docs/operations/ai-agent-market-radar-readback.snapshot.json",
            "gitea_main_evidence_basis_commit": evidence_commit,
            "scope_note": "本讀回只整合已提交的只讀來源監控、AI Agent 市場雷達與治理 gate；不包含 raw chat history、secret、session 或本機工作視窗內容。",
        },
        "summary": {
            "overall_completion_percent": float(agent_summary.get("overall_completion_percent", 42.2)),
            "ai_technology_radar_completion_percent": success_rate,
            "technology_count": int(watch_summary.get("technology_count", 0)),
            "technology_area_count": int(watch_summary.get("technology_area_count", 0)),
            "source_count": source_count,
            "changed_technologies": int(watch_summary.get("changed_technologies", 0)),
            "review_queue_count": int(watch_summary.get("review_queue_count", 0)),
            "source_failures": failure_count,
            "high_priority_count": int(watch_summary.get("high_priority_count", 0)),
            "rolling_update_status": "near_real_time_watch_ready_integration_gated",
        },
        "policy": {
            "read_only": True,
            "raw_chat_history_synced": False,
            "sdk_installation_approved": False,
            "paid_api_calls_approved": False,
            "production_routing_approved": False,
            "telegram_send_approved": False,
            "model_provider_switch_approved": False,
            "host_write_approved": False,
            "openclaw_replacement_approved": False,
        },
        "technology_area_counts": dict(technology_watch.get("technology_area_counts") or {}),
        "technology_domains": _technology_domains(technology_watch),
        "high_priority_review_queue": _high_priority_review_queue(technology_watch),
        "professional_agent_roles": _professional_agent_roles(),
        "rolling_update_controls": _rolling_update_controls(technology_watch),
        "primary_source_alignment": _primary_source_alignment(),
        "integration_candidates": _integration_candidates(technology_watch),
        "priority_workplan": _priority_workplan(),
        "blocked_gates": [
            "sdk_installation_approved=false",
            "paid_api_calls_approved=false",
            "production_routing_approved=false",
            "telegram_send_approved=false",
            "model_provider_switch_approved=false",
            "host_write_approved=false",
            "openclaw_replacement_approved=false",
            "replay_shadow_canary_gate_required=true",
            "cost_and_data_boundary_review_required=true",
        ],
        "report_contract": {
            "api_endpoint": "/api/v1/agents/ai-technology-radar-readback",
            "frontend_target": "/zh-TW/governance?tab=agent-market",
            "schedule_workflow": ".gitea/workflows/ai-technology-watch.yaml",
            "schedule_enabled": True,
            "schedule_cron_utc": "0 */6 * * *",
            "near_real_time": "每 6 小時讀取 primary sources，偵測主流 AI 技術版本、文件與 release 變更。",
            "daily": "每日彙整變更、來源失敗、審核佇列與可自動處理項目。",
            "weekly": "每週做技術 scorecard，決定 sandbox / replay / adapter design 優先級。",
            "monthly": "每月進行策略 review，決定納入 roadmap、維持 watch-only 或移出監控。",
            "human_review_required_for": [
                "新 SDK / package / MCP server 安裝",
                "付費 API 或 token 上限變更",
                "模型 provider / 生產路由切換",
                "Telegram Bot 即時發送或審批按鈕策略變更",
                "主機、K8s、workflow、Nginx、secret 或資料層寫入",
                "OpenClaw 生產決策核心替換、拆分或降級",
            ],
            "agent_auto_allowed_for": [
                "官方來源只讀監控",
                "版本與文件 hash 比對",
                "審核佇列分類",
                "繁中 no-send 報告草稿",
                "離線 replay fixture 準備",
                "低風險文件與讀回 snapshot 更新提案",
            ],
        },
    }


def render_markdown(payload: dict[str, Any]) -> str:
    """Render a Traditional Chinese operator report."""
    summary = payload["summary"]
    lines = [
        "# AI 技術雷達與滾動更新讀回",
        "",
        f"- 產生時間：`{payload['generated_at']}`",
        f"- 整體治理完成度：`{summary['overall_completion_percent']}%`",
        f"- AI 技術雷達來源成功率：`{summary['ai_technology_radar_completion_percent']}%`",
        f"- 監控技術項目：`{summary['technology_count']}`",
        f"- 技術領域：`{summary['technology_area_count']}`",
        f"- 官方 / primary sources：`{summary['source_count']}`",
        f"- 來源失敗：`{summary['source_failures']}`",
        f"- 需要審核變更：`{summary['changed_technologies']}`",
        f"- 高優先級項目：`{summary['high_priority_count']}`",
        f"- 滾動更新狀態：`{summary['rolling_update_status']}`",
        "",
        "## 技術領域覆蓋",
        "",
        "| 技術領域 | 技術數 | 高優先級 | 需要審核 | 代表技術 |",
        "|---|---:|---:|---:|---|",
    ]
    for domain in payload["technology_domains"]:
        lines.append(
            f"| `{domain['technology_area']}` | `{domain['technology_count']}` | "
            f"`{domain['high_priority_count']}` | `{domain['changed_count']}` | "
            f"{', '.join(domain['representative_technologies'])} |"
        )

    lines.extend([
        "",
        "## 高優先級審核佇列",
        "",
        "| 技術 | 領域 | 優先級 | Gate | 下一步 |",
        "|---|---|---|---|---|",
    ])
    for item in payload["high_priority_review_queue"]:
        lines.append(
            f"| {item['display_name']} | `{item['technology_area']}` | "
            f"`{item['evaluation_priority']}` | `{item['gate_status']}` | {item['next_gate']} |"
        )

    lines.extend([
        "",
        "## Agent 專業分工",
        "",
        "| Agent | 專業角色 | 自動化範圍 | 需要審核的邊界 |",
        "|---|---|---|---|",
    ])
    for role in payload["professional_agent_roles"]:
        lines.append(
            f"| {role['agent']} | {role['professional_role']} | "
            f"{role['auto_scope']} | {role['review_boundary']} |"
        )

    lines.extend([
        "",
        "## 滾動更新控制",
        "",
        "| 節奏 | Agent 可自動做什麼 | 輸出 | Gate |",
        "|---|---|---|---|",
    ])
    for control in payload["rolling_update_controls"]:
        lines.append(
            f"| {control['cadence']} | {control['agent_auto_action']} | "
            f"{control['output']} | `{control['gate']}` |"
        )

    lines.extend([
        "",
        "## 主流實務來源證據",
        "",
        "| 實務 | 官方來源 | AWOOOI Gate | Agent 分工 |",
        "|---|---|---|---|",
    ])
    for item in payload["primary_source_alignment"]:
        lines.append(
            f"| {item['practice']} | {item['source']} | `{item['awoooi_gate']}` | "
            f"{item['agent_assignment']} |"
        )

    lines.extend([
        "",
        "## 優先工作清單",
        "",
        "| 順序 | 工作 | 優先級 | 自動化模式 | 完成定義 |",
        "|---:|---|---|---|---|",
    ])
    for item in payload["priority_workplan"]:
        lines.append(
            f"| {item['order']} | {item['work_item']} | `{item['priority']}` | "
            f"`{item['automation_mode']}` | {item['done_definition']} |"
        )

    lines.extend([
        "",
        "## 仍被 Gate 擋下",
        "",
    ])
    for gate in payload["blocked_gates"]:
        lines.append(f"- `{gate}`")
    lines.append("")
    return "\n".join(lines)


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


def _success_rate(source_count: int, failure_count: int) -> float:
    if source_count <= 0:
        return 0.0
    return round(((source_count - failure_count) / source_count) * 100, 1)


def _technology_domains(report: dict[str, Any]) -> list[dict[str, Any]]:
    grouped: dict[str, list[dict[str, Any]]] = defaultdict(list)
    for row in report.get("technologies") or []:
        grouped[str(row.get("technology_area") or "uncategorized")].append(row)

    domains = []
    for area, rows in sorted(grouped.items()):
        high_priority = [row for row in rows if row.get("evaluation_priority") in {"p0", "p1"}]
        changed = [row for row in rows if row.get("changed")]
        domains.append({
            "technology_area": area,
            "technology_count": len(rows),
            "high_priority_count": len(high_priority),
            "changed_count": len(changed),
            "representative_technologies": [
                str(row.get("display_name") or row.get("technology_id"))
                for row in rows[:4]
            ],
        })
    return domains


def _high_priority_review_queue(report: dict[str, Any]) -> list[dict[str, Any]]:
    rows = [
        row
        for row in report.get("technologies") or []
        if row.get("evaluation_priority") in {"p0", "p1"} and row.get("changed")
    ]
    return [
        {
            "technology_id": row.get("technology_id"),
            "display_name": row.get("display_name"),
            "technology_area": row.get("technology_area"),
            "evaluation_priority": row.get("evaluation_priority"),
            "gate_status": "scorecard_required_before_integration",
            "next_gate": "刷新 scorecard，若涉及 SDK/API/route/Telegram/host write 則送人工審核。",
            "requires_cost_approval": bool(row.get("requires_cost_approval")),
            "requires_dependency_approval": bool(row.get("requires_dependency_approval")),
            "requires_security_review": bool(row.get("requires_security_review")),
        }
        for row in rows[:12]
    ]


def _professional_agent_roles() -> list[dict[str, Any]]:
    return [
        {
            "agent": "OpenClaw",
            "professional_role": "生產決策仲裁者、風險分級與最後 policy guard",
            "auto_scope": "維持現有 production baseline、讀取 replay / shadow 評分、拒絕無證據替換",
            "review_boundary": "任何取代、降級、生產路由切換都必須通過 replay / shadow / canary 與人工批准。",
        },
        {
            "agent": "NemoTron",
            "professional_role": "離線回放評估者、模型能力比較、合約輸出 smoke gate",
            "auto_scope": "只讀 request pack、比對候選輸出、產生 replay scorecard 草稿",
            "review_boundary": "不得自行呼叫外部 NIM/API、不得讀 labels 作答、不得進生產路由。",
        },
        {
            "agent": "Hermes",
            "professional_role": "知識管理、RAG 整理、報告草稿與長期技能庫維護",
            "auto_scope": "整理 primary source 摘要、建立 no-send 日週月報、準備人審包",
            "review_boundary": "不得同步 raw chat history、不得保存 secret、不得直接發 Telegram live report。",
        },
        {
            "agent": "MarketRadar",
            "professional_role": "AI 技術市場雷達、版本監控、來源失敗偵測",
            "auto_scope": "每 6 小時只讀 primary sources、產生 freshness / review queue",
            "review_boundary": "不得自動新增 SDK、不得自動修改 provider route 或 workflow 行為。",
        },
        {
            "agent": "Critic / Reviewer",
            "professional_role": "獨立審核、反例檢查、整合風險評分",
            "auto_scope": "檢查政策旗標、來源可靠性、成本與資安風險",
            "review_boundary": "只能輸出 blocked / candidate / owner_review，不得直接執行寫入。",
        },
    ]


def _rolling_update_controls(report: dict[str, Any]) -> list[dict[str, Any]]:
    cadence = report.get("cadence") or {}
    return [
        {
            "cadence": "每 6 小時",
            "agent_auto_action": "讀取官方文件、PyPI、npm、GitHub release、primary source hash。",
            "output": "AI 技術 watch report、來源失敗清單、review queue。",
            "gate": "read_only_only",
            "cadence_source": cadence.get("near_real_time_watch", ""),
        },
        {
            "cadence": "每日",
            "agent_auto_action": "依 business applicability、成本、依賴、資安、AWOOOI fit 分類。",
            "output": "日報摘要與中低風險自動處理建議。",
            "gate": "no_send_report_until_delivery_gate",
            "cadence_source": cadence.get("daily_triage", ""),
        },
        {
            "cadence": "每週",
            "agent_auto_action": "刷新 scorecard，決定 sandbox / replay / adapter design 優先級。",
            "output": "週報、優先序、候選整合審查包。",
            "gate": "scorecard_required_before_replay",
            "cadence_source": cadence.get("weekly_scorecard", ""),
        },
        {
            "cadence": "每月",
            "agent_auto_action": "彙整趨勢，提出 roadmap / watch-only / retire 建議。",
            "output": "月報與策略審核包。",
            "gate": "human_review_for_strategy_or_production_change",
            "cadence_source": cadence.get("monthly_strategy_review", ""),
        },
    ]


def _primary_source_alignment() -> list[dict[str, str]]:
    return [
        {
            "practice": "OpenAI Agents SDK：專家協作、tool execution、approvals、state 由產品掌控",
            "source": "https://developers.openai.com/api/docs/guides/agents",
            "awoooi_gate": "sandbox_orchestration_no_write",
            "agent_assignment": "OpenClaw 負責 policy guard；MarketRadar 追版本；Hermes 產審核包。",
        },
        {
            "practice": "NVIDIA Nemotron 3 Ultra / NeMo：長任務 Agent、profiling、evaluation、MCP / A2A 互通",
            "source": "https://developer.nvidia.com/blog/nvidia-nemotron-3-ultra-powers-faster-more-efficient-reasoning-for-long-running-agents/",
            "awoooi_gate": "nemotron_replay_evaluator_only",
            "agent_assignment": "NemoTron 只做離線 replay / evaluator / smoke gate，不接 production routing。",
        },
        {
            "practice": "LangGraph：durable execution、human-in-the-loop、stateful workflow runtime",
            "source": "https://docs.langchain.com/oss/python/langgraph/overview",
            "awoooi_gate": "incident_workflow_kernel_replay_first",
            "agent_assignment": "OpenClaw 仲裁狀態轉移；Hermes 記錄 replay 證據與交接原因。",
        },
        {
            "practice": "MCP：標準化 agent-to-tool / resource / prompt 連接，且需明確 user consent",
            "source": "https://modelcontextprotocol.io/specification/2025-06-18",
            "awoooi_gate": "read_only_tool_registry_before_write_adapter",
            "agent_assignment": "MarketRadar 監控 SDK / spec；Critic 檢查資料權限與 tool safety。",
        },
        {
            "practice": "A2A：跨框架 Agent 溝通、委派與互通；MCP 處理工具、A2A 處理 Agent 對 Agent",
            "source": "https://a2a-protocol.org/latest/",
            "awoooi_gate": "agent_to_agent_interop_watch_only",
            "agent_assignment": "OpenClaw 設定協作邊界；Hermes 彙整 handoff 記錄；NemoTron 比對輸出。",
        },
        {
            "practice": "OpenTelemetry GenAI：Agent / LLM / MCP trace 語意慣例，支援可觀測與稽核",
            "source": "https://opentelemetry.io/docs/specs/semconv/registry/attributes/gen-ai/",
            "awoooi_gate": "trace_semconv_mapping_before_runtime_export",
            "agent_assignment": "Critic 定義稽核欄位；MarketRadar 追語意規範版本；Hermes 產日週月報。",
        },
    ]


def _integration_candidates(report: dict[str, Any]) -> list[dict[str, Any]]:
    return [
        {
            "technology_id": row.get("technology_id"),
            "display_name": row.get("display_name"),
            "technology_area": row.get("technology_area"),
            "integration_surface": row.get("integration_surface"),
            "awoooi_role": row.get("awoooi_role"),
            "changed": bool(row.get("changed")),
            "decision": row.get("decision"),
            "recommended_actions": row.get("recommended_actions") or [],
        }
        for row in report.get("technologies") or []
    ]


def _priority_workplan() -> list[dict[str, Any]]:
    return [
        {
            "order": 1,
            "priority": "P0",
            "work_item": "AI 技術雷達 primary source 監控產品化",
            "automation_mode": "agent_auto_read_only",
            "done_definition": "API、snapshot、Markdown、schema、測試與 production readback 都能顯示技術領域、來源與 Gate。",
        },
        {
            "order": 2,
            "priority": "P0",
            "work_item": "近即時版本 / release / docs 變更偵測",
            "automation_mode": "agent_auto_schedule_read_only",
            "done_definition": "每 6 小時可跑 watch；失敗來源會進日報，不會自動整合。",
        },
        {
            "order": 3,
            "priority": "P0",
            "work_item": "OpenClaw / Hermes / NemoTron / MarketRadar 專業分工與成長紀錄",
            "automation_mode": "agent_auto_read_model_human_review_for_write",
            "done_definition": "每個 Agent 的角色、輸出、學習寫回與限制都能被前端讀回。",
        },
        {
            "order": 4,
            "priority": "P1",
            "work_item": "AI 技術 scorecard 與 sandbox / replay 優先級",
            "automation_mode": "agent_propose_owner_review",
            "done_definition": "高優先級變更先進 scorecard，再進 no-cost/no-write sandbox 或 replay 計畫。",
        },
        {
            "order": 5,
            "priority": "P1",
            "work_item": "Telegram Bot 報告與高風險審核橋接",
            "automation_mode": "blocked_until_telegram_send_gate",
            "done_definition": "低中風險只告警回報；高風險需 owner approval 後才可發送或執行。",
        },
        {
            "order": 6,
            "priority": "P2",
            "work_item": "新 AI 技術探索與 watchlist 擴充",
            "automation_mode": "agent_auto_discover_human_classify",
            "done_definition": "GitHub topic / package registry / 官方 blog 可提出候選，但加入正式 watchlist 前需審核。",
        },
    ]


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")
    return payload


def main() -> int:
    parser = argparse.ArgumentParser(description="Build AI technology radar readback.")
    parser.add_argument("--technology-watch", required=True)
    parser.add_argument("--agent-market-radar", required=True)
    parser.add_argument("--evidence-commit", required=True)
    parser.add_argument("--output", required=True)
    parser.add_argument("--markdown-output", required=True)
    parser.add_argument("--markdown-alias-output")
    args = parser.parse_args()

    payload = build_radar(
        technology_watch=load_json(Path(args.technology_watch)),
        agent_market_radar=load_json(Path(args.agent_market_radar)),
        evidence_commit=args.evidence_commit,
    )
    Path(args.output).write_text(
        json.dumps(payload, ensure_ascii=False, indent=2, sort_keys=True) + "\n",
        encoding="utf-8",
    )
    markdown = render_markdown(payload)
    Path(args.markdown_output).write_text(markdown, encoding="utf-8")
    if args.markdown_alias_output:
        Path(args.markdown_alias_output).write_text(markdown, encoding="utf-8")
    print(
        "AI_TECHNOLOGY_RADAR_READBACK_OK "
        f"overall={payload['summary']['overall_completion_percent']}% "
        f"technology={payload['summary']['technology_count']} "
        f"sources={payload['summary']['source_count']} "
        f"changed={payload['summary']['changed_technologies']} "
        f"failures={payload['summary']['source_failures']}"
    )
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
