"""市場情報機會與威脅告警候選 preview。

只定義未來 alert candidate、Telegram 與 AI 摘要的 gate、去重與節流；
不建立 queue、不寫 DB、不派送訊息、不呼叫 LLM。
"""


ALERT_CHANNELS = (
    {
        "key": "operator_review",
        "label": "人工審核清單",
        "minimum_level": "watch",
        "requires_operator_approval": False,
        "dispatch_target": "market_intel_review_queue",
    },
    {
        "key": "daily_digest",
        "label": "每日市場情報摘要",
        "minimum_level": "medium",
        "requires_operator_approval": True,
        "dispatch_target": "openclaw_daily_digest",
    },
    {
        "key": "telegram_candidate",
        "label": "Telegram 候選告警",
        "minimum_level": "high",
        "requires_operator_approval": True,
        "dispatch_target": "telegram_market_intel_channel",
    },
    {
        "key": "ai_briefing_candidate",
        "label": "AI 摘要候選",
        "minimum_level": "medium",
        "requires_operator_approval": True,
        "dispatch_target": "hermes_openclaw_briefing",
    },
)

ALERT_GATES = (
    {
        "key": "evidence_bundle_ready",
        "label": "必須有完整 evidence bundle",
        "required_for": ["watch", "medium", "high", "critical"],
    },
    {
        "key": "score_threshold_met",
        "label": "分數需達 channel 最低門檻",
        "required_for": ["medium", "high", "critical"],
    },
    {
        "key": "dedupe_key_clear",
        "label": "同日同商品同活動不得重複派送",
        "required_for": ["medium", "high", "critical"],
    },
    {
        "key": "freshness_window_valid",
        "label": "價格與活動快照需在 freshness window 內",
        "required_for": ["medium", "high", "critical"],
    },
    {
        "key": "operator_approval",
        "label": "人工批准後才可進 Telegram 或 AI 摘要候選",
        "required_for": ["high", "critical"],
    },
)

THROTTLE_POLICY = {
    "dedupe_window_hours": 24,
    "max_telegram_candidates_per_day": 12,
    "max_critical_candidates_per_hour": 3,
    "max_ai_briefing_items_per_digest": 20,
}

REVIEW_STATES = (
    {
        "key": "draft",
        "label": "候選草案",
        "dispatch_allowed": False,
        "description": "由 scoring / evidence 形成候選，但尚未進人工審核。",
    },
    {
        "key": "needs_review",
        "label": "待人工審核",
        "dispatch_allowed": False,
        "description": "資料完整但尚未批准，不得推送或產生 AI 摘要。",
    },
    {
        "key": "approved_for_digest",
        "label": "批准進每日摘要",
        "dispatch_allowed": False,
        "description": "只可進每日摘要候選，仍不得直接推 Telegram。",
    },
    {
        "key": "approved_for_telegram",
        "label": "批准進 Telegram 候選",
        "dispatch_allowed": True,
        "description": "仍需經 dispatch gate 與 throttle，再進下一階段。",
    },
    {
        "key": "rejected",
        "label": "駁回",
        "dispatch_allowed": False,
        "description": "保留審核理由，不再升級。",
    },
    {
        "key": "deferred",
        "label": "延後觀察",
        "dispatch_allowed": False,
        "description": "等待新價格快照或活動狀態更新。",
    },
)

REVIEW_ACTIONS = (
    {
        "key": "approve_digest",
        "from": ["needs_review"],
        "to": "approved_for_digest",
        "requires_reason": True,
    },
    {
        "key": "approve_telegram",
        "from": ["needs_review", "approved_for_digest"],
        "to": "approved_for_telegram",
        "requires_reason": True,
    },
    {
        "key": "reject",
        "from": ["draft", "needs_review", "approved_for_digest"],
        "to": "rejected",
        "requires_reason": True,
    },
    {
        "key": "defer",
        "from": ["needs_review", "approved_for_digest"],
        "to": "deferred",
        "requires_reason": True,
    },
)

REVIEW_QUEUE_CONTRACT = {
    "table_name": "market_alert_review_queue",
    "primary_key": "id",
    "required_fields": [
        "alert_candidate_id",
        "review_state",
        "priority_lane",
        "threshold_level",
        "total_score",
        "evidence_bundle_id",
        "dedupe_key",
        "source_batch_id",
        "created_at",
        "updated_at",
    ],
    "audit_fields": [
        "reviewer_identity",
        "review_action",
        "review_reason",
        "reviewed_at",
        "previous_state",
        "next_state",
    ],
    "forbidden_fields": [
        "customer_personal_data",
        "login_required_price",
        "cart_or_order_data",
        "payment_or_shipping_data",
    ],
}

REVIEW_QUEUE_INDEXES = (
    {
        "key": "idx_market_alert_review_queue_state_priority",
        "columns": ["review_state", "priority_lane", "created_at"],
        "purpose": "審核台依狀態與優先級快速排序。",
    },
    {
        "key": "ux_market_alert_review_queue_dedupe",
        "columns": ["dedupe_key"],
        "purpose": "避免同商品同活動同日重複進入審核佇列。",
    },
    {
        "key": "idx_market_alert_review_queue_bundle",
        "columns": ["evidence_bundle_id", "source_batch_id"],
        "purpose": "回查 evidence bundle 與來源批次。",
    },
)

REVIEW_PRIORITY_LANES = (
    {
        "key": "critical",
        "label": "立即審核",
        "max_age_hours": 2,
        "minimum_threshold": "critical",
    },
    {
        "key": "high",
        "label": "今日優先",
        "max_age_hours": 8,
        "minimum_threshold": "high",
    },
    {
        "key": "medium",
        "label": "每日摘要候選",
        "max_age_hours": 24,
        "minimum_threshold": "medium",
    },
    {
        "key": "watch",
        "label": "觀察池",
        "max_age_hours": 72,
        "minimum_threshold": "watch",
    },
)


def build_opportunity_alert_plan_preview(
    *,
    runtime_status,
    opportunity_plan,
    scoring_plan,
    evidence_plan,
    scheduler_plan,
):
    """建立告警候選與派送 gate 計畫；不建立或派送任何告警。"""
    opportunity_preview_safe = (
        opportunity_plan.get("mode") == "opportunity_plan_preview"
        and not opportunity_plan.get("opportunity_queue_created")
        and not opportunity_plan.get("threat_alert_dispatched")
        and not opportunity_plan.get("database_write_executed")
    )
    scoring_preview_safe = (
        scoring_plan.get("mode") == "opportunity_scoring_plan_preview"
        and not scoring_plan.get("score_calculation_executed")
        and not scoring_plan.get("scoring_job_created")
        and not scoring_plan.get("database_write_executed")
    )
    evidence_preview_safe = (
        evidence_plan.get("mode") == "opportunity_evidence_plan_preview"
        and not evidence_plan.get("evidence_bundle_created")
        and not evidence_plan.get("evidence_query_executed")
        and not evidence_plan.get("database_write_executed")
    )
    scheduler_preview_safe = (
        scheduler_plan.get("mode") == "scheduler_attach_plan_preview"
        and not scheduler_plan.get("scheduler_registration_executed")
        and not scheduler_plan.get("crawler_job_started")
    )
    gate_checks = {
        "opportunity_plan_preview_safe": opportunity_preview_safe,
        "scoring_plan_preview_safe": scoring_preview_safe,
        "evidence_plan_preview_safe": evidence_preview_safe,
        "scheduler_plan_preview_safe": scheduler_preview_safe,
        "evidence_bundle_ready": bool(
            evidence_plan.get("ready_for_evidence_bundle")
        ),
        "scoring_job_ready": bool(scoring_plan.get("ready_for_scoring_job")),
        "opportunity_queue_ready": bool(
            opportunity_plan.get("ready_for_opportunity_queue")
        ),
        "database_write_still_blocked": not bool(
            runtime_status.database_write_allowed
        ),
        "operator_approval": False,
    }
    blocked_reasons = [
        key for key, passed in gate_checks.items()
        if not passed
    ]

    return {
        "mode": "opportunity_alert_plan_preview",
        "ready_for_alert_candidates": False,
        "alert_candidate_created": False,
        "alert_queue_created": False,
        "review_queue_created": False,
        "review_queue_contract_defined": True,
        "review_queue_contract_written": False,
        "review_queue_table_created": False,
        "review_action_executed": False,
        "approval_record_written": False,
        "telegram_dispatched": False,
        "ai_summary_generated": False,
        "llm_call_executed": False,
        "notification_sent": False,
        "database_session_created": False,
        "database_write_executed": False,
        "database_commit_executed": False,
        "external_network_executed": False,
        "scheduler_attached": False,
        "writes_executed": False,
        "would_write_database": False,
        "channel_count": len(ALERT_CHANNELS),
        "channels": list(ALERT_CHANNELS),
        "alert_gates": list(ALERT_GATES),
        "review_state_count": len(REVIEW_STATES),
        "review_states": list(REVIEW_STATES),
        "review_actions": list(REVIEW_ACTIONS),
        "review_queue_contract": REVIEW_QUEUE_CONTRACT,
        "review_queue_indexes": list(REVIEW_QUEUE_INDEXES),
        "review_priority_lanes": list(REVIEW_PRIORITY_LANES),
        "throttle_policy": THROTTLE_POLICY,
        "gate_checks": gate_checks,
        "blocked_reasons": blocked_reasons,
        "approval_policy": {
            "manual_approval_required_for_dispatch": True,
            "approval_reason_required": True,
            "reviewer_identity_required": True,
            "approved_candidate_still_requires_dispatch_gate": True,
            "queue_item_requires_evidence_bundle": True,
            "queue_item_requires_dedupe_key": True,
        },
        "payload_contract": {
            "required_fields": [
                "alert_candidate_id",
                "rule_key",
                "threshold_level",
                "total_score",
                "bundle_id",
                "source_batch_id",
                "dedupe_key",
                "created_at",
            ],
            "forbidden_fields": [
                "customer_personal_data",
                "login_required_price",
                "cart_or_order_data",
            ],
        },
        "operator_sequence": [
            "先由 evidence bundle 產生 alert candidate 草案",
            "依 throttle_policy 去重與節流，不直接推播",
            "medium 以上進每日摘要候選，high 以上才可進 Telegram 候選",
            "人工批准後才允許 AI 摘要或 Telegram 候選進入下一階段",
            "所有派送內容必須附 bundle id、source batch id 與 dedupe key",
        ],
        "safe_boundaries": [
            "do_not_create_alert_queue_from_preview",
            "do_not_create_review_queue_table_from_preview",
            "do_not_write_review_queue_contract_from_preview",
            "do_not_dispatch_telegram_from_alert_preview",
            "do_not_call_llm_from_alert_preview",
            "do_not_notify_without_evidence_bundle",
            "do_not_send_duplicate_alerts",
            "do_not_include_personal_or_login_required_data",
        ],
    }
