"""候選審核 queue review_state writer run package preview。

本模組只把人工 CLI 更新 review_state 前需要保存的 payload、命令、
證據與回退資訊整理成可審核預覽；不讀 approval token、不寫本機檔案、
不開 DB connection、不執行 CLI、不更新 review_state、不 commit、不掛 scheduler。
"""

import hashlib
import json

from services.market_intel.candidate_queue_review_decision_transaction import (
    ALLOWED_DECISIONS,
    TARGET_TABLE,
)


def _as_dict(value):
    return value if isinstance(value, dict) else {}


def _as_list(value):
    if value is None:
        return []
    if isinstance(value, (list, tuple, set)):
        return list(value)
    return [value]


def _stable_hash(value):
    encoded = json.dumps(
        value,
        ensure_ascii=False,
        sort_keys=True,
        separators=(",", ":"),
    ).encode("utf-8")
    return hashlib.sha256(encoded).hexdigest()


def _statement_payloads(transaction_preview):
    payloads = []
    for statement in _as_list(_as_dict(transaction_preview).get("statements")):
        statement = _as_dict(statement)
        payload = _as_dict(statement.get("parameter_preview"))
        dedupe_key = payload.get("dedupe_key") or _as_dict(statement.get("lookup")).get(
            "dedupe_key"
        )
        current_state = (
            payload.get("expected_current_review_state")
            or statement.get("expected_current_review_state")
        )
        next_state = payload.get("next_review_state") or statement.get(
            "next_review_state"
        )
        manifest = {
            "index": statement.get("index"),
            "idempotency_key": statement.get("idempotency_key"),
            "dedupe_key": dedupe_key,
            "expected_current_review_state": current_state,
            "next_review_state": next_state,
            "operation": statement.get("operation"),
            "statement_type": statement.get("statement_type"),
            "payload_hash": _stable_hash(payload),
        }
        if dedupe_key and current_state and next_state:
            payloads.append(manifest)
    return payloads


def _package_gates(
    *,
    transaction_preview,
    writer_preflight,
    writer_status,
    postwrite_smoke,
    operator_drill,
    payloads,
):
    transaction_preview = _as_dict(transaction_preview)
    writer_preflight = _as_dict(writer_preflight)
    writer_status = _as_dict(writer_status)
    postwrite_smoke = _as_dict(postwrite_smoke)
    operator_drill = _as_dict(operator_drill)
    return [
        {
            "key": "transaction_preview_created",
            "label": "已產生 review_state transaction preview",
            "passed": bool(transaction_preview.get("transaction_preview_created")),
        },
        {
            "key": "transaction_has_update_statements",
            "label": "run package 至少需包含一筆 update_review_state statement",
            "passed": bool(payloads),
        },
        {
            "key": "transaction_updates_are_small_batch",
            "label": "首次 review_state run package 必須是小批次，最多 5 筆",
            "passed": 0 < len(payloads) <= 5,
        },
        {
            "key": "transaction_transition_allowed",
            "label": "只能從 needs_review 更新為 confirmed / rejected / deferred",
            "passed": bool(
                payloads
                and all(
                    item.get("expected_current_review_state") == "needs_review"
                    and item.get("next_review_state") in ALLOWED_DECISIONS
                    for item in payloads
                )
            ),
        },
        {
            "key": "writer_preflight_available",
            "label": "writer preflight 已可用，正式操作前需另跑只讀檢查",
            "passed": bool(writer_preflight),
        },
        {
            "key": "writer_cli_gate_available",
            "label": "review_state writer CLI gate 已可用，真更新只允許 CLI 執行",
            "passed": bool(writer_status),
        },
        {
            "key": "operator_drill_available",
            "label": "operator drill 已產生正式操作順序",
            "passed": bool(operator_drill),
        },
        {
            "key": "postwrite_smoke_available",
            "label": "post-write smoke 已可用，更新後可只讀驗證 review_state",
            "passed": bool(postwrite_smoke),
        },
        {
            "key": "writer_status_still_blocks_api_write",
            "label": "writer gate 仍需阻擋 API/UI 寫入",
            "passed": bool(
                writer_status.get("mode")
                == "candidate_queue_review_decision_writer_cli_blocked"
                and not writer_status.get("ready_for_real_write")
            ),
        },
        {
            "key": "run_artifacts_saved_by_operator",
            "label": "正式更新前操作員必須保存 transaction JSON 與 preflight 輸出",
            "passed": False,
        },
        {
            "key": "backup_artifact_path_recorded",
            "label": "正式更新前必須記錄最新備份檔路徑",
            "passed": False,
        },
        {
            "key": "one_time_token_supplied_in_shell_only",
            "label": "一次性 approval token 只能在 CLI shell 提供",
            "passed": False,
        },
        {
            "key": "postwrite_evidence_saved",
            "label": "正式更新後必須保存 writer output 與 post-write smoke 結果",
            "passed": False,
        },
    ]


def build_candidate_queue_review_decision_writer_run_package(
    *,
    transaction_preview,
    writer_preflight,
    writer_status,
    postwrite_smoke,
    operator_drill,
):
    """建立 review_state writer run package preview；不執行任何副作用。"""
    payloads = _statement_payloads(transaction_preview)
    payload_manifest_hash = _stable_hash(payloads)
    gates = _package_gates(
        transaction_preview=transaction_preview,
        writer_preflight=writer_preflight,
        writer_status=writer_status,
        postwrite_smoke=postwrite_smoke,
        operator_drill=operator_drill,
        payloads=payloads,
    )
    blocked_reasons = [gate["key"] for gate in gates if not gate["passed"]]
    package_ready = bool(payloads and not blocked_reasons)

    return {
        "mode": "candidate_queue_review_decision_writer_run_package_preview",
        "target_table": TARGET_TABLE,
        "target_operation": "update_review_state",
        "package_ready": package_ready,
        "package_artifact_created": False,
        "ready_for_api_review_state_update": False,
        "ready_for_api_database_write": False,
        "ready_for_scheduler_attach": False,
        "api_writes_file": False,
        "api_executes_cli": False,
        "api_reads_approval_token": False,
        "api_writes_database": False,
        "api_updates_review_state": False,
        "approval_record_written": False,
        "decision_record_written": False,
        "review_state_update_executed": False,
        "database_connection_opened": False,
        "database_session_created": False,
        "explicit_transaction_opened": False,
        "transaction_opened": False,
        "transaction_committed": False,
        "database_write_executed": False,
        "database_commit_executed": False,
        "database_rollback_executed": False,
        "external_network_executed": False,
        "scheduler_attached": False,
        "writes_executed": False,
        "would_write_database": False,
        "blocked_reasons": blocked_reasons,
        "package_gates": gates,
        "payload_manifest": {
            "payload_count": len(payloads),
            "manifest_hash": payload_manifest_hash,
            "dedupe_keys": [
                item["dedupe_key"] for item in payloads if item.get("dedupe_key")
            ],
            "allowed_next_states": list(ALLOWED_DECISIONS),
            "payloads": payloads,
            "redaction_policy": [
                "do_not_include_approval_token",
                "do_not_include_raw_html",
                "do_not_include_login_or_member_data",
            ],
        },
        "required_artifacts": [
            {
                "key": "review_state_transaction_json",
                "label": "操作員保存的 review_state transaction JSON",
                "path_shape": "artifacts/market_intel/review-state-transaction-YYYYMMDD-HHMMSS.json",
                "created_by_api": False,
            },
            {
                "key": "project_backup_zip",
                "label": "正式更新前備份檔",
                "path_shape": "scripts/tools/backups/momo_pro_system_backup_*.zip",
                "created_by_api": False,
            },
            {
                "key": "read_only_preflight_json",
                "label": "CLI read-only preflight 輸出",
                "path_shape": "artifacts/market_intel/review-state-preflight-*.json",
                "created_by_api": False,
            },
            {
                "key": "review_state_writer_output_json",
                "label": "CLI review_state writer 正式執行輸出",
                "path_shape": "artifacts/market_intel/review-state-writer-output-*.json",
                "created_by_api": False,
            },
            {
                "key": "review_state_postwrite_smoke_json",
                "label": "review_state post-write smoke 只讀驗證輸出",
                "path_shape": "artifacts/market_intel/review-state-postwrite-smoke-*.json",
                "created_by_api": False,
            },
        ],
        "command_bundle": [
            {
                "step": 1,
                "key": "save_review_state_transaction",
                "command_shape": (
                    "mkdir -p artifacts/market_intel && write transaction JSON to "
                    "artifacts/market_intel/review-state-transaction-YYYYMMDD-HHMMSS.json"
                ),
                "executes_database": False,
            },
            {
                "step": 2,
                "key": "backup",
                "command_shape": "python3 scripts/tools/backup_system.py",
                "executes_database": False,
            },
            {
                "step": 3,
                "key": "preflight",
                "command_shape": (
                    "python3 scripts/market_intel_review_decision_writer.py "
                    "--transaction-json artifacts/market_intel/review-state-transaction.json "
                    "--read-only-preflight > artifacts/market_intel/review-state-preflight.json"
                ),
                "executes_database": False,
            },
            {
                "step": 4,
                "key": "review_state_writer",
                "command_shape": (
                    "MARKET_INTEL_QUEUE_WRITE_APPROVAL=... "
                    "python3 scripts/market_intel_review_decision_writer.py --execute "
                    "--apply-real-write --transaction-json "
                    "artifacts/market_intel/review-state-transaction.json "
                    "> artifacts/market_intel/review-state-writer-output.json"
                ),
                "executes_database": True,
            },
            {
                "step": 5,
                "key": "postwrite_smoke",
                "command_shape": (
                    "POST /api/market_intel/manual_sample_review/"
                    "candidate_queue_review_decision_writer_postwrite_smoke?execute=true "
                    "> artifacts/market_intel/review-state-postwrite-smoke.json"
                ),
                "executes_database": False,
            },
        ],
        "operator_signoff": [
            "確認每個 dedupe_key 仍是 needs_review",
            "確認下一狀態只包含 confirmed / rejected / deferred",
            "確認備份檔路徑與時間",
            "確認 approval token 只在 shell 環境提供",
            "確認 post-write smoke 的 review_state 與 transaction preview 相符",
        ],
        "rollback_plan": [
            {
                "key": "no_preview_side_effect",
                "label": "此 run package preview 沒有副作用，不需要 DB rollback",
            },
            {
                "key": "review_state_reversal_requires_manual_audit",
                "label": "正式 CLI 更新後若需回退，必須依 dedupe_key 與審核證據人工稽核",
            },
            {
                "key": "keep_market_flags_disabled",
                "label": "異常時維持 MARKET_INTEL_* flags 關閉，不掛 scheduler",
            },
        ],
        "safe_boundaries": [
            "do_not_create_review_state_run_artifacts_from_api",
            "do_not_execute_review_state_writer_from_run_package_api",
            "do_not_read_approval_token_from_run_package_api",
            "do_not_open_database_connection_from_review_state_run_package",
            "do_not_update_review_state_from_review_state_run_package",
            "do_not_commit_review_state_run_package",
            "do_not_attach_scheduler_from_review_state_run_package",
            "no_remove_orphans",
            "no_momo_db_lifecycle_change",
        ],
    }
