"""市場情報機會與威脅分數模型 preview。

只定義未來 scoring job 的欄位、權重、門檻與 evidence 要求；不查 DB、
不建立 queue、不派送 Telegram、不產生 AI 摘要。
"""


SCORING_DIMENSIONS = (
    {
        "key": "price_gap_pct",
        "label": "競品活動價差百分比",
        "weight": 35,
        "evidence": [
            "confirmed_market_product_match",
            "market_product_price_history.price",
            "momo_reference_price",
        ],
        "calculation": "max(0, momo_reference_price - market_price) / momo_reference_price",
    },
    {
        "key": "discount_depth",
        "label": "活動折扣深度",
        "weight": 20,
        "evidence": [
            "market_campaign_products.original_price",
            "market_campaign_products.price",
            "market_campaign_products.discount_rate",
        ],
        "calculation": "normalized_discount_rate",
    },
    {
        "key": "match_confidence",
        "label": "商品比對可信度",
        "weight": 20,
        "evidence": [
            "market_product_matches.match_score",
            "market_product_matches.match_status",
            "market_product_matches.match_reason_json",
        ],
        "calculation": "confirmed=1.0, needs_review=score, rejected=0",
    },
    {
        "key": "campaign_urgency",
        "label": "活動時間急迫性",
        "weight": 15,
        "evidence": [
            "market_campaigns.end_at",
            "market_campaigns.status",
            "market_campaign_snapshots.crawled_at",
        ],
        "calculation": "higher_when_active_and_ending_within_72h",
    },
    {
        "key": "data_freshness",
        "label": "資料新鮮度",
        "weight": 10,
        "evidence": [
            "market_product_price_history.crawled_at",
            "market_crawler_runs.finished_at",
        ],
        "calculation": "higher_when_snapshot_age_under_24h",
    },
)

SEVERITY_THRESHOLDS = (
    {
        "level": "critical",
        "minimum_score": 85,
        "action": "只建立人工審核項；必須有 confirmed match 與最新價格 evidence。",
    },
    {
        "level": "high",
        "minimum_score": 70,
        "action": "排入威脅審核清單；不得自動調價或直接推播。",
    },
    {
        "level": "medium",
        "minimum_score": 50,
        "action": "排入日報候選；需人工確認後才可進 AI 摘要。",
    },
    {
        "level": "watch",
        "minimum_score": 30,
        "action": "只保留觀察訊號，不進即時告警。",
    },
)

REQUIRED_EVIDENCE_TABLES = (
    "market_campaigns",
    "market_campaign_products",
    "market_product_price_history",
    "market_product_matches",
    "market_crawler_runs",
)


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_scoring_plan_preview(
    *,
    runtime_status,
    opportunity_plan,
    match_review_plan,
    scheduler_plan,
    schema_smoke,
    mcp_fetch_gate,
):
    """建立機會與威脅分數模型 preview；不執行任何計算或寫入。"""
    available_tables = _schema_tables(schema_smoke)
    required_tables_present = set(REQUIRED_EVIDENCE_TABLES) <= available_tables
    dimensions = list(SCORING_DIMENSIONS)
    total_weight = sum(item["weight"] for item in dimensions)
    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")
    )
    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")
    )
    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,
        "opportunity_rules_available": bool(opportunity_plan.get("rule_count")),
        "opportunity_queue_ready": bool(
            opportunity_plan.get("ready_for_opportunity_queue")
        ),
        "match_review_preview_safe": match_review_preview_safe,
        "confirmed_match_source_ready": bool(
            match_review_plan.get("ready_for_review_queue")
        ),
        "schema_smoke_passed": bool(
            (schema_smoke.get("schema_smoke") or schema_smoke).get("passed")
        ),
        "required_evidence_tables_declared": required_tables_present,
        "mcp_fetch_gate_closed_for_preview": not bool(
            mcp_fetch_gate.get("network_request_allowed")
        ),
        "scheduler_plan_preview_safe": scheduler_preview_safe,
        "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_scoring_plan_preview",
        "ready_for_scoring_job": False,
        "scoring_job_created": False,
        "score_calculation_executed": False,
        "sample_scores_generated": False,
        "opportunity_queue_created": False,
        "review_queue_created": False,
        "threat_alert_dispatched": 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,
        "dimension_count": len(dimensions),
        "total_weight": total_weight,
        "dimensions": dimensions,
        "thresholds": list(SEVERITY_THRESHOLDS),
        "required_evidence_tables": list(REQUIRED_EVIDENCE_TABLES),
        "gate_checks": gate_checks,
        "blocked_reasons": blocked_reasons,
        "formula": "sum(normalized_dimension_score * weight) / 100",
        "promotion_policy": {
            "critical": "只可進人工審核；人工確認後才可生成 Telegram 候選。",
            "high": "只可進審核清單；不得直接觸發價格調整。",
            "medium": "只可進日報候選；AI 摘要必須附 evidence id。",
            "watch": "只做趨勢觀察，不進告警。",
        },
        "operator_sequence": [
            "確認 market_* migration 與 seed rows 已完成",
            "確認商品比對 queue 已有 confirmed / needs_review evidence",
            "用最新 price history 與 campaign snapshot 計算 dimension scores",
            "依 thresholds 建立人工審核候選，不直接推播或調價",
            "人工批准後才允許 AI 摘要或 Telegram 候選進入下一階段",
        ],
        "safe_boundaries": [
            "do_not_score_without_confirmed_or_reviewed_match",
            "do_not_generate_sample_scores_from_placeholder_data",
            "do_not_write_scoring_results_from_preview",
            "do_not_dispatch_alerts_from_scoring_preview",
            "do_not_generate_ai_summary_from_scoring_preview",
            "do_not_auto_adjust_price",
        ],
    }
