"""市場情報機會與威脅 evidence bundle preview。

只定義未來 scoring / alert / AI 摘要必須攜帶的可追溯證據包；
不查 DB、不產生 sample evidence、不建立 queue、不派送 Telegram。
"""


EVIDENCE_SECTIONS = (
    {
        "key": "campaign_context",
        "label": "活動脈絡",
        "source_tables": [
            "market_campaigns",
            "market_campaign_snapshots",
            "market_crawler_runs",
        ],
        "required_fields": [
            "campaign_id",
            "platform_code",
            "campaign_name",
            "campaign_url",
            "status",
            "start_at",
            "end_at",
            "snapshot_id",
            "batch_id",
        ],
        "purpose": "確認活動存在、時間狀態與爬取批次。",
    },
    {
        "key": "market_product_snapshot",
        "label": "競品商品快照",
        "source_tables": [
            "market_campaign_products",
            "market_product_price_history",
        ],
        "required_fields": [
            "market_product_id",
            "platform_product_id",
            "product_url",
            "name",
            "price",
            "original_price",
            "discount_rate",
            "coupon_text",
            "rank_position",
            "crawled_at",
        ],
        "purpose": "確認競品活動商品與當下價格、折扣、排序訊號。",
    },
    {
        "key": "match_review_state",
        "label": "商品比對審核狀態",
        "source_tables": [
            "market_product_matches",
        ],
        "required_fields": [
            "match_id",
            "momo_i_code",
            "match_score",
            "match_status",
            "match_reason_json",
            "reviewed_at",
            "reviewed_by",
        ],
        "purpose": "確認是否可把競品商品升級為同品或高信心候選。",
    },
    {
        "key": "momo_reference",
        "label": "MOMO 參考商品",
        "source_tables": [
            "products",
            "price_records",
            "daily_sales_snapshot",
        ],
        "required_fields": [
            "momo_i_code",
            "product_name",
            "brand",
            "reference_price",
            "latest_price_seen_at",
            "sales_signal_at",
        ],
        "purpose": "確認我方價格與銷售訊號，避免只靠競品資料判讀。",
    },
    {
        "key": "scoring_trace",
        "label": "分數計算軌跡",
        "source_tables": [
            "market_product_price_history",
            "market_product_matches",
        ],
        "required_fields": [
            "dimension_scores",
            "total_score",
            "threshold_level",
            "formula_version",
            "computed_from_batch_id",
        ],
        "purpose": "讓人工審核、AI 摘要與 Telegram 候選都能追溯分數來源。",
    },
)

ALERT_ESCALATION_GATES = (
    {
        "key": "confirmed_or_reviewed_match",
        "label": "必須有 confirmed 或 needs_review 高信心比對證據",
        "required_for": ["high", "critical"],
    },
    {
        "key": "fresh_price_snapshot",
        "label": "競品價格快照需在有效時間窗內",
        "required_for": ["medium", "high", "critical"],
    },
    {
        "key": "momo_reference_price",
        "label": "必須有可追溯的 MOMO 參考價",
        "required_for": ["high", "critical"],
    },
    {
        "key": "campaign_still_active",
        "label": "活動仍為 active 或 upcoming，ended 不得進即時告警",
        "required_for": ["medium", "high", "critical"],
    },
    {
        "key": "operator_approval",
        "label": "人工批准後才可進 Telegram 或 AI 摘要候選",
        "required_for": ["critical"],
    },
)


def _schema_tables(schema_smoke):
    expected_tables = schema_smoke.get("expected_tables") or []
    if expected_tables:
        return set(expected_tables)
    smoke = schema_smoke.get("schema_smoke") or schema_smoke
    return {
        item.get("table")
        for item in smoke.get("tables", [])
        if item.get("table")
    }


def build_opportunity_evidence_plan_preview(
    *,
    runtime_status,
    opportunity_plan,
    scoring_plan,
    match_review_plan,
    legacy_source_bridge,
    schema_smoke,
):
    """建立 evidence bundle 計畫；不查資料、不產生範例 evidence。"""
    available_tables = _schema_tables(schema_smoke)
    required_market_tables = {
        table
        for section in EVIDENCE_SECTIONS
        for table in section["source_tables"]
        if table.startswith("market_")
    }
    required_market_tables_declared = required_market_tables <= available_tables
    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")
    )
    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")
    )
    match_review_preview_safe = (
        match_review_plan.get("mode") == "match_review_plan_preview"
        and not match_review_plan.get("auto_confirm_executed")
        and not match_review_plan.get("database_write_executed")
    )
    legacy_bridge_safe = (
        legacy_source_bridge.get("mode") == "legacy_source_bridge_planned"
        and not legacy_source_bridge.get("read_only_query_executed")
        and not legacy_source_bridge.get("database_write_executed")
    )
    gate_checks = {
        "opportunity_plan_preview_safe": opportunity_preview_safe,
        "scoring_plan_preview_safe": scoring_preview_safe,
        "match_review_preview_safe": match_review_preview_safe,
        "legacy_bridge_planned_safe": legacy_bridge_safe,
        "schema_smoke_passed": bool(
            (schema_smoke.get("schema_smoke") or schema_smoke).get("passed")
        ),
        "required_market_tables_declared": required_market_tables_declared,
        "confirmed_match_evidence_available": bool(
            match_review_plan.get("ready_for_review_queue")
        ),
        "scoring_trace_available": bool(scoring_plan.get("ready_for_scoring_job")),
        "database_write_still_blocked": not bool(
            runtime_status.database_write_allowed
        ),
        "manual_operator_approval": False,
    }
    blocked_reasons = [
        key for key, passed in gate_checks.items()
        if not passed
    ]

    return {
        "mode": "opportunity_evidence_plan_preview",
        "ready_for_evidence_bundle": False,
        "evidence_bundle_created": False,
        "evidence_query_executed": False,
        "sample_evidence_generated": False,
        "alert_candidate_created": False,
        "telegram_dispatched": False,
        "ai_summary_generated": 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,
        "section_count": len(EVIDENCE_SECTIONS),
        "sections": list(EVIDENCE_SECTIONS),
        "escalation_gates": list(ALERT_ESCALATION_GATES),
        "required_market_tables": sorted(required_market_tables),
        "gate_checks": gate_checks,
        "blocked_reasons": blocked_reasons,
        "bundle_contract": {
            "identity": "platform_code + campaign_id + market_product_id + match_id",
            "freshness_window_hours": 24,
            "dedupe_key": "rule_key + momo_i_code + platform_product_id + campaign_id + crawled_at_date",
            "must_include": [
                "rule_key",
                "threshold_level",
                "total_score",
                "evidence_sections",
                "source_batch_id",
            ],
        },
        "operator_sequence": [
            "先確認 scoring plan 只基於正式 market_* evidence",
            "建立 evidence bundle 時逐一附上來源 table 與 primary key",
            "缺任一高風險 evidence 時只能降級為 watch",
            "人工審核通過後才可建立 alert candidate",
            "AI 摘要與 Telegram 候選必須引用 bundle id 與 source_batch_id",
        ],
        "safe_boundaries": [
            "do_not_query_database_from_evidence_preview",
            "do_not_generate_placeholder_evidence",
            "do_not_create_alert_candidate_from_preview",
            "do_not_dispatch_telegram_from_evidence_preview",
            "do_not_generate_ai_summary_from_evidence_preview",
            "do_not_escalate_without_bundle_contract",
        ],
    }
