from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]


def test_competitor_intel_cache_reuses_memory_and_shared_file(tmp_path, monkeypatch):
    from services import competitor_intel_repository as repo

    monkeypatch.setattr(repo, "_CACHE_FILE", Path(tmp_path) / "competitor_intel_cache.pkl")
    repo._MEM_CACHE.clear()

    calls = {"count": 0}

    def producer():
        calls["count"] += 1
        return {"valid_matches": 7, "match_rate": 0.1}

    first = repo._cached_payload("coverage:test", producer, ttl_seconds=60)
    second = repo._cached_payload("coverage:test", producer, ttl_seconds=60)
    repo._MEM_CACHE.clear()
    third = repo._cached_payload("coverage:test", producer, ttl_seconds=60)

    assert first == second == third == {"valid_matches": 7, "match_rate": 0.1}
    assert calls["count"] == 1


def test_clear_competitor_intel_cache_removes_shared_file(tmp_path, monkeypatch):
    from services import competitor_intel_repository as repo

    cache_file = Path(tmp_path) / "competitor_intel_cache.pkl"
    monkeypatch.setattr(repo, "_CACHE_FILE", cache_file)
    repo._MEM_CACHE["x"] = {"time": 1, "value": {"ok": True}}
    cache_file.write_bytes(b"stale")

    repo.clear_competitor_intel_cache()

    assert repo._MEM_CACHE == {}
    assert not cache_file.exists()


def test_competitor_ppt_results_keep_pending_diagnostics_in_export():
    source = (ROOT / "services" / "competitor_intel_repository.py").read_text(encoding="utf-8")

    assert "LEFT JOIN valid_competitor" in source
    assert "\"found\": found" in source
    assert "\"match_status\"" in source
    assert "\"candidate_count\"" in source
    assert "\"unit_comparison\"" in source
    assert "build_unit_price_comparison" in source
    assert "(vc.pchome_price IS NULL)" in source
    assert "(lm.momo_price - vc.pchome_price) AS price_diff" in source
    assert "((lm.momo_price - vc.pchome_price) / vc.pchome_price * 100) AS price_diff_pct" in source


def test_competitor_ppt_results_use_history_for_dated_reports():
    source = (ROOT / "services" / "competitor_intel_repository.py").read_text(encoding="utf-8")
    route_source = (ROOT / "routes" / "openclaw_bot_routes.py").read_text(encoding="utf-8")
    comparison_source = source.split("def fetch_competitor_comparison_results", 1)[1].split(
        "def build_competitor_intel_payload", 1
    )[0]

    assert "requested_historical_prices" in source
    assert "use_history_prices" in source
    assert "FROM competitor_price_history cph" in source
    assert "cph.crawled_at >= DATE(:start_date)" in source
    assert "cph.crawled_at < DATE(:end_date) + INTERVAL '1 day'" in source
    assert "pr.timestamp < DATE(:end_date) + INTERVAL '1 day'" in source
    assert "FROM products p\n            JOIN LATERAL" in comparison_source
    assert "WHERE pr.product_id = p.id" in comparison_source
    assert "ORDER BY pr.timestamp DESC, pr.id DESC" in comparison_source
    assert "ROW_NUMBER() OVER (PARTITION BY p.id" not in comparison_source
    assert "WHERE lm.rn = 1" not in comparison_source
    assert "'competitor_price_history' AS competitor_source" in source
    assert "\"competitor_source\"" in source
    assert "\"pc_crawled_at\"" in source
    assert "指定期間 competitor_price_history" in route_source


def test_competitor_coverage_counts_only_active_product_intersection():
    source = (ROOT / "services" / "competitor_intel_repository.py").read_text(encoding="utf-8")
    coverage_source = source.split("def _fetch_competitor_coverage_uncached", 1)[1].split(
        "def _fetch_manual_review_summary", 1
    )[0]

    assert "coverage:v14" in source
    assert "CATALOG_COMPARABLE_SCORE_FLOOR" in source
    assert "CATALOG_IDENTITY_REVIEW_SCORE_FLOOR" in source
    assert "rescore_accepted_count" in coverage_source
    assert "(SELECT COUNT(*) FROM valid_competitor) AS valid_matches" not in coverage_source
    assert "identity_competitor AS" in coverage_source
    assert "fresh_competitor AS" in coverage_source
    assert "unknown_freshness_competitor AS" in coverage_source
    assert "WHERE expires_at > CURRENT_TIMESTAMP" in coverage_source
    assert "WHERE expires_at IS NULL" in coverage_source
    assert "FROM latest_momo lm\n             JOIN identity_competitor ic ON ic.sku = lm.sku" in coverage_source
    assert "LEFT JOIN fresh_competitor fc ON fc.sku = lm.sku" in coverage_source
    assert "WHERE fc.sku IS NULL" in coverage_source
    assert "\"fresh_matches\": fresh" in coverage_source
    assert "\"stale_matches\": stale" in coverage_source
    assert "\"unknown_freshness_matches\": unknown_freshness" in coverage_source
    assert "\"not_decision_ready_count\": pending + stale + unknown_freshness" in coverage_source
    assert "\"decision_ready_matches\": fresh" in coverage_source
    assert "\"decision_ready_rate\": round(fresh / max(active, 1) * 100, 1)" in coverage_source
    assert "\"decision_support_count\": decision_support_count" in coverage_source
    assert "\"decision_support_rate\": round(decision_support_count / max(active, 1) * 100, 1)" in coverage_source
    assert "\"catalog_comparable_count\": catalog_comparable_count" in coverage_source
    assert "_catalog_comparable_sql(\"la\")" in coverage_source
    assert "_catalog_review_lane_sql(\"la\", \"catalog_variant_review\")" in coverage_source
    assert "_catalog_review_lane_sql(\"la\", \"catalog_unit_review\")" in coverage_source
    assert "_catalog_review_lane_sql(\"la\", \"catalog_identity_review\")" in coverage_source
    assert "\"catalog_review_plan\": {" in coverage_source
    assert "CATALOG_COMPARABLE_SIGNAL_REASONS" in source
    assert "CATALOG_VARIANT_REVIEW_REASONS" in source
    assert "CATALOG_UNIT_REVIEW_REASONS" in source
    assert "CATALOG_COMPARABLE_IDENTITY_REASONS" in source
    assert "\"catalog_identity_review_score_floor\": CATALOG_IDENTITY_REVIEW_SCORE_FLOOR" in coverage_source


def test_catalog_comparable_sql_includes_high_confidence_identity_review_lane():
    from services.competitor_intel_repository import (
        CATALOG_COMPARABLE_SCORE_FLOOR,
        CATALOG_IDENTITY_REVIEW_SCORE_FLOOR,
        _catalog_comparable_sql,
    )

    source = (ROOT / "services" / "competitor_intel_repository.py").read_text(encoding="utf-8")
    coverage_source = source.split("def _fetch_competitor_coverage_uncached", 1)[1].split(
        "def _fetch_manual_review_summary", 1
    )[0]
    sql = _catalog_comparable_sql("la")

    assert f">= {CATALOG_COMPARABLE_SCORE_FLOOR}" in sql
    assert f">= {CATALOG_IDENTITY_REVIEW_SCORE_FLOOR}" in sql
    assert "CATALOG_IDENTITY_REVIEW_SCORE_FLOOR" not in sql
    assert "OR COALESCE(la.best_match_score, 0)" in sql
    assert "CATALOG_COMPARABLE_SIGNAL_REASONS" not in sql
    assert "CATALOG_COMPARABLE_BLOCK_REASONS" in source
    assert "\"identity_coverage_matches\": valid" in coverage_source
    assert "\"manual_closed_count\": manual_closed_count" in coverage_source
    assert "\"last_decision_ready_crawled_at\": last_decision_ready_crawled_at" in coverage_source
    assert "FROM products p\n            JOIN LATERAL" in coverage_source
    assert "WHERE p.status = 'ACTIVE'" in coverage_source


def test_competitor_decision_consumers_require_explicit_freshness():
    source = (ROOT / "services" / "competitor_intel_repository.py").read_text(encoding="utf-8")

    assert "(cp.expires_at IS NULL OR cp.expires_at > CURRENT_TIMESTAMP)" not in source
    assert source.count("AND cp.expires_at > CURRENT_TIMESTAMP") >= 4


def test_competitor_ppt_and_ai_use_momo_minus_pchome_gap_direction():
    ppt_source = (ROOT / "services" / "ppt_generator.py").read_text(encoding="utf-8")
    route_source = (ROOT / "routes" / "openclaw_bot_routes.py").read_text(encoding="utf-8")

    assert 'pc_wins    = [r for r in found if r.get("price_diff", 0) > 10]' in ppt_source
    assert 'mo_wins    = [r for r in found if r.get("price_diff", 0) < -10]' in ppt_source
    assert "平均價差 {avg_pct:+.1f}%（momo - PChome）" in ppt_source
    assert "price_diff = MOMO售價 − PChome售價" in route_source
    assert "正值=PChome價格優勢" in route_source


def test_competitor_review_queue_is_canonical_unit_price_handoff():
    source = (ROOT / "services" / "competitor_intel_repository.py").read_text(encoding="utf-8")
    daily_template = (ROOT / "templates" / "daily_sales.html").read_text(encoding="utf-8")
    growth_template = (ROOT / "templates" / "growth_analysis.html").read_text(encoding="utf-8")

    assert "def fetch_competitor_review_queue" in source
    assert "review_queue = fetch_competitor_review_queue" in source
    assert "\"review_queue\": review_queue" in source
    assert "\"unit_comparable_count\"" in source
    assert "\"rescore_accepted_count\"" in source
    assert "manual_review_summary" in source
    assert "manual_accept_count" in source
    assert "manual_reject_count" in source
    assert "manual_unit_price_count" in source
    assert "manual_rejected" in source
    assert "manual_unit_price_required" in source
    assert "manual_needs_research" in source
    assert "manual_closed" in source
    assert "competitor_match_reviews" in source
    assert "\"status_label\"" in source
    assert "\"action_label\"" in source
    assert "build_unit_price_comparison" in source
    assert "需單位價覆核" in daily_template
    assert "人工採用" in daily_template
    assert "人工否決" in daily_template
    assert "人工單位價" in daily_template
    assert "competitor_intel.review_queue" in daily_template
    assert "coverage.fresh_matches" in growth_template
    assert "coverage.fresh_match_rate" in growth_template
    assert "coverage.decision_ready_rate" in growth_template
    assert "coverage.decision_support_rate" in growth_template
    assert "coverage.catalog_comparable_count" in growth_template
    assert "型錄/任選可比" in growth_template
    assert "coverage.stale_matches" in growth_template
    assert "coverage.unknown_freshness_matches" in growth_template
    assert "未形成有效身份配對" in growth_template
    assert "coverage.unit_comparable_count" in growth_template
    assert "coverage.rescore_accepted_count" in growth_template
    assert "重算待人工覆核" in growth_template
    assert "coverage.manual_accept_count" in growth_template
    assert "coverage.manual_reject_count" in growth_template
    assert "coverage.manual_unit_price_count" in growth_template
    assert "comp_coverage.rescore_accepted_count" in daily_template
    assert "重算待人工覆核" in daily_template
    assert "comp_coverage.decision_support_rate" in daily_template
    assert "comp_coverage.catalog_comparable_count" in daily_template
    assert "精準可告警覆蓋" in daily_template
    assert "comp_coverage.stale_matches" in daily_template
    assert "comp_coverage.unknown_freshness_matches" in daily_template
    assert "comp_coverage.decision_ready_rate" in daily_template


def test_competitor_review_filters_split_low_score_operational_buckets():
    from services.competitor_intel_repository import REVIEW_STATUS_FILTER_GROUPS

    assert REVIEW_STATUS_FILTER_GROUPS["catalog_comparable"] == (
        "true_low_confidence",
        "catalog_variant_review",
        "catalog_unit_review",
        "catalog_identity_review",
    )
    assert REVIEW_STATUS_FILTER_GROUPS["catalog_variant_review"] == (
        "true_low_confidence",
        "catalog_variant_review",
    )
    assert REVIEW_STATUS_FILTER_GROUPS["catalog_unit_review"] == (
        "true_low_confidence",
        "catalog_unit_review",
    )
    assert REVIEW_STATUS_FILTER_GROUPS["catalog_identity_review"] == (
        "true_low_confidence",
        "catalog_identity_review",
    )
    assert REVIEW_STATUS_FILTER_GROUPS["recoverable_low_score"] == ("recoverable_low_score",)
    assert REVIEW_STATUS_FILTER_GROUPS["true_low_confidence"] == ("true_low_confidence",)
    assert REVIEW_STATUS_FILTER_GROUPS["legacy_low_score"] == ("low_score", "refresh_low_score")
    assert set(REVIEW_STATUS_FILTER_GROUPS["low_score"]) == {
        "low_score",
        "refresh_low_score",
        "recoverable_low_score",
        "true_low_confidence",
    }


def test_catalog_comparable_review_item_keeps_exact_match_guardrail():
    from services.competitor_intel_repository import _format_competitor_review_item

    item = _format_competitor_review_item({
        "sku": "CAT-001",
        "name": "DASHING DIVA Gloss Gel 美甲片 月影柔霧",
        "momo_price": 699,
        "attempt_status": "true_low_confidence",
        "catalog_comparable": True,
        "candidate_count": 3,
        "best_competitor_product_id": "DABC-CATALOG",
        "best_competitor_product_name": "DASHING DIVA Gloss Gel 美甲片 月影柔霧 任選",
        "best_competitor_price": 599,
        "best_match_score": 0.912,
        "match_diagnostic_json": {
            "match_type": "comparable",
            "price_basis": "manual_review",
            "alert_tier": "identity_review",
            "reasons": [
                "strong_product_line_match",
                "variant_selection_review",
            ],
        },
    })

    assert item["review_bucket"] == "catalog_variant_review"
    assert item["status_label"] == "選項 / 色號待核"
    assert item["catalog_review_guidance"]["primary_review_action"] == "needs_research"
    assert "選項、色號" in item["action_label"]
    envelope = item["decision_envelope"]
    assert envelope["recommended_action"]["action"] == "needs_research"
    assert envelope["guardrails"]["can_auto_execute"] is False
    assert envelope["guardrails"]["catalog_comparable"] is True
    assert envelope["guardrails"]["catalog_review_lane"] == "catalog_variant_review"
    assert envelope["expected_impact"]["catalog_review_guidance"]["lane"] == "catalog_variant_review"
    assert any(
        evidence["metric"] == "catalog_comparable"
        and evidence["value"] == "catalog_variant_review"
        for evidence in envelope["evidence"]
    )
    assert any(evidence["metric"] == "catalog_comparable" for evidence in envelope["evidence"])


def test_competitor_review_reasons_prefer_json_payload_labels():
    from services.competitor_intel_repository import _format_competitor_review_item

    item = _format_competitor_review_item({
        "sku": "SKU-1",
        "name": "M.A.C Macximal 柔霧唇膏",
        "momo_price": 990,
        "attempt_status": "identity_veto",
        "candidate_count": 1,
        "best_competitor_product_id": "DABC123",
        "best_competitor_product_name": "MAC Macximal 緞光唇膏",
        "best_competitor_price": 880,
        "best_match_score": 0.32,
        "match_diagnostic_json": {
            "match_type": "no_match",
            "price_basis": "none",
            "alert_tier": "suppress",
            "identity_evidence": {
                "version": "identity_evidence_v1",
                "brand": {"momo": ["mac"], "competitor": ["mac"], "shared": ["mac"]},
                "product_type": {"momo": "唇膏", "competitor": "唇膏", "matched": True},
                "identity_anchor": "macximal 柔霧唇膏",
                "shared_model_tokens": [],
                "specs": {
                    "momo": {"volumes_ml": [], "weights_g": [], "dosages_mg": [], "counts": [], "total_piece_count": None},
                    "competitor": {"volumes_ml": [], "weights_g": [], "dosages_mg": [], "counts": [], "total_piece_count": None},
                    "mismatches": [],
                },
                "variant_guardrails": {
                    "hard_veto": True,
                    "conflict_reasons": ["makeup_finish_conflict"],
                    "catalog_count_omission": False,
                },
            },
            "offer_evidence": {
                "version": "offer_evidence_v1",
                "price_basis": "none",
                "alert_tier": "suppress",
                "momo_price": 990,
                "competitor_price": 880,
                "gap_pct": 12.5,
                "price_is_identity_evidence": False,
            },
            "reasons": [
                "makeup_finish_conflict",
                "nail_tool_function_conflict",
                "schick_razor_line_conflict",
            ],
        },
        "error_message": "",
    })

    assert item["match_type_label"] == "非同款"
    assert item["price_basis_label"] == "不可比"
    assert item["alert_tier_label"] == "不告警"
    assert item["diagnostic_reason_text"] == "妝效質地不同、工具功能不同、除毛刀品線不同"
    assert item["identity_evidence_summary"].startswith("品牌 mac")
    assert item["offer_evidence"]["price_is_identity_evidence"] is False
    assert item["difference_highlights"][0]["dimension"] == "妝效/質地不同"
    assert [reason["code"] for reason in item["diagnostic_reasons"]] == [
        "makeup_finish_conflict",
        "nail_tool_function_conflict",
        "schick_razor_line_conflict",
    ]
    envelope = item["decision_envelope"]
    assert envelope["decision_type"] == "pchome_match_review"
    assert envelope["subject"]["sku"] == "SKU-1"
    assert envelope["subject"]["competitor_product_id"] == "DABC123"
    assert envelope["guardrails"]["can_auto_execute"] is False
    assert envelope["guardrails"]["data_quality"] == "partial"
    assert envelope["guardrails"]["match_type"] == "no_match"
    assert envelope["guardrails"]["identity_evidence_version"] == "identity_evidence_v1"
    assert envelope["guardrails"]["price_is_identity_evidence"] is False
    assert envelope["identity_evidence"]["brand"]["shared"] == ["mac"]
    assert envelope["offer_evidence"]["gap_pct"] == 12.5
    assert envelope["difference_highlights"][0]["dimension"] == "妝效/質地不同"
    assert envelope["recommended_action"]["requires_hitl"] is True
    assert envelope["recommended_action"]["action"] == "verify_or_reject_identity"
    assert any(evidence["metric"] == "reasons" for evidence in envelope["evidence"])
    assert any(evidence["metric"] == "identity_evidence" for evidence in envelope["evidence"])
    assert any(evidence["metric"] == "offer_evidence" for evidence in envelope["evidence"])
    assert any(evidence["metric"] == "difference_highlights" for evidence in envelope["evidence"])


def test_rescore_accepted_review_item_has_actionable_decision_envelope():
    from services.competitor_intel_repository import _format_competitor_review_item

    item = _format_competitor_review_item({
        "sku": "10922465",
        "name": "【Herbacin 德國小甘菊】小甘菊1號護手霜20ml",
        "momo_price": 99,
        "attempt_status": "rescore_accepted_current",
        "candidate_count": 1,
        "best_competitor_product_id": "DDAO4C-A79050612",
        "best_competitor_product_name": "小甘菊經典護手霜20ml",
        "best_competitor_price": 89,
        "best_match_score": 0.872,
        "match_diagnostic_json": {
            "match_type": "exact",
            "price_basis": "total_price",
            "alert_tier": "identity_review",
            "reasons": ["focused_exact_identity_herbacin_classic_hand_cream_20ml_brandless"],
        },
    })

    envelope = item["decision_envelope"]
    assert envelope["severity"] in {"P1", "P2"}
    assert envelope["subject"]["momo_price"] == 99
    assert envelope["subject"]["competitor_price"] == 89
    assert envelope["recommended_action"]["action"] == "review_accept_identity"
    assert envelope["guardrails"]["data_quality"] == "complete"
    assert envelope["expected_impact"]["gap_amount"] == 10
    assert envelope["expected_impact"]["candidate_gap_pct"] == 11.2
    assert any(evidence["metric"] == "candidate_gap_pct" for evidence in envelope["evidence"])


def test_manual_unit_price_review_item_keeps_business_insight():
    from services.competitor_intel_repository import (
        _format_competitor_review_item,
        summarize_review_decision_envelopes,
    )

    item = _format_competitor_review_item({
        "sku": "11223344",
        "name": "理膚寶水 B5 全面修復霜 40ml x2 超值組",
        "momo_price": 1199,
        "attempt_status": "manual_unit_price_required",
        "candidate_count": 1,
        "best_competitor_product_id": "DABC01-B5",
        "best_competitor_product_name": "理膚寶水 全面修復霜 B5 40ml",
        "best_competitor_price": 679,
        "best_match_score": 0.742,
        "match_diagnostic_json": {
            "match_type": "same_product_different_pack",
            "price_basis": "unit_price",
            "alert_tier": "unit_price_review",
            "reasons": ["unit_comparable"],
        },
    })

    assert item["unit_comparison"]["comparable"] is True
    assert item["unit_price_insight"]["direction"] == "momo_cheaper"
    assert "MOMO 單位價低" in item["unit_price_insight"]["summary"]
    envelope = item["decision_envelope"]
    assert envelope["recommended_action"]["action"] == "unit_price_required"
    assert envelope["expected_impact"]["unit_price_insight"]["unit_gap_pct"] == -11.71
    assert any(evidence["metric"] == "unit_price_gap_pct" for evidence in envelope["evidence"])

    brief = summarize_review_decision_envelopes([item], limit=5)
    assert "單位價差 -11.7%" in brief["text"]
    assert brief["items"][0]["unit_price_gap_pct"] == -11.71


def test_protected_existing_match_envelope_explains_candidate_conflict():
    from services.competitor_intel_repository import _format_competitor_review_item

    item = _format_competitor_review_item({
        "sku": "14338675",
        "name": "【Relove】胺基酸私密潔淨精華凝露120ml",
        "momo_price": 399,
        "attempt_status": "protected_existing_match",
        "candidate_count": 2,
        "best_competitor_product_id": "QEAE1O-A900A6DRS",
        "best_competitor_product_name": "RELOVE胺基酸私密清潔凝露120ml",
        "best_competitor_price": 329,
        "best_match_score": 0.817,
        "match_diagnostic_json": {
            "match_type": "exact",
            "price_basis": "total_price",
            "alert_tier": "identity_review",
            "reasons": ["strong_exact_spec_match", "spec_name_alignment"],
        },
        "error_message": (
            "existing_match_conflict;existing_id=QEAE1O-A900A6DNN;"
            "incoming_id=QEAE1O-A900A6DRS;existing_score=0.766;incoming_score=0.817"
        ),
    })

    envelope = item["decision_envelope"]
    conflict = envelope["expected_impact"]["existing_match_conflict"]
    assert item["existing_match_conflict"]["score_delta"] == 0.051
    assert envelope["recommended_action"]["action"] == "compare_existing_identity"
    assert envelope["severity"] == "P2"
    assert envelope["guardrails"]["existing_match_protected"] is True
    assert conflict["existing_product_id"] == "QEAE1O-A900A6DNN"
    assert conflict["incoming_product_id"] == "QEAE1O-A900A6DRS"
    assert any(evidence["metric"] == "existing_match_conflict" for evidence in envelope["evidence"])


def test_review_decision_brief_is_shared_by_openclaw_and_ppt():
    from services.competitor_intel_repository import (
        _format_competitor_review_item,
        summarize_review_decision_envelopes,
    )

    item = _format_competitor_review_item({
        "sku": "10922465",
        "name": "【Herbacin 德國小甘菊】小甘菊1號護手霜20ml",
        "momo_price": 99,
        "attempt_status": "rescore_accepted_current",
        "candidate_count": 1,
        "best_competitor_product_id": "DDAO4C-A79050612",
        "best_competitor_product_name": "小甘菊經典護手霜20ml",
        "best_competitor_price": 89,
        "best_match_score": 0.872,
        "match_diagnostic_json": {
            "match_type": "exact",
            "price_basis": "total_price",
            "alert_tier": "identity_review",
        },
    })

    brief = summarize_review_decision_envelopes([item], limit=5)

    assert brief["hitl_count"] == 1
    assert brief["auto_execute_blocked_count"] == 1
    assert brief["severity_counts"]
    assert brief["data_quality_counts"] == {"complete": 1}
    assert "人工確認身份後採用同款" in brief["text"]
    assert "HITL" in brief["text"]
    assert "DDAO4C-A79050612" in brief["text"]

    repo_source = (ROOT / "services" / "competitor_intel_repository.py").read_text(encoding="utf-8")
    openclaw_source = (ROOT / "services" / "openclaw_strategist_service.py").read_text(encoding="utf-8")
    ppt_source = (ROOT / "services" / "ppt_generator.py").read_text(encoding="utf-8")
    bot_source = (ROOT / "routes" / "openclaw_bot_routes.py").read_text(encoding="utf-8")

    assert "\"review_decision_brief\": summarize_review_decision_envelopes" in repo_source
    assert "summarize_review_decision_envelopes" in openclaw_source
    assert "review_decision_text" in openclaw_source
    assert "PChome 覆核決策信封（HITL，不可自動寫正式價差）" in openclaw_source
    assert "SUM(CASE WHEN attempt_status IN ('unit_comparable'" not in openclaw_source
    assert "review_decision_brief" in bot_source
    assert "覆核決策信封（HITL，不可自動寫正式價差）" in bot_source
    assert "覆核決策信封（HITL）" in ppt_source


def test_competitor_ppt_prompt_uses_neutral_ewooc_viewpoint():
    source = (ROOT / "routes" / "openclaw_bot_routes.py").read_text(encoding="utf-8")

    assert "EwoooC 商品營運視角" in source
    assert "待補資料不可當成成功配對" in source
    assert "高信心比對" in source
    assert "待補身份/價格" in source
    assert "需單位價比較" in source
    assert "單位價覆核樣本" in source
    assert "我方 = PChome" not in source
    assert "請以 PChome 視角" not in source


def test_top_competitor_risks_reads_latest_momo_price_after_valid_competitor_filter():
    source = (ROOT / "services" / "competitor_intel_repository.py").read_text(encoding="utf-8")
    risk_source = source.split("def _fetch_top_competitor_risks_uncached", 1)[1].split("def fetch_competitor_review_queue", 1)[0]

    assert "FROM valid_competitor vc" in risk_source
    assert "JOIN LATERAL" in risk_source
    assert "WHERE pr.product_id = p.id" in risk_source
    assert "ROW_NUMBER() OVER (PARTITION BY p.id" not in risk_source
