from services import webcrumbs_host_data_service as svc


def test_webcrumbs_host_data_maps_price_alert_exact_rows(monkeypatch):
    engine = object()

    monkeypatch.setattr(
        svc,
        "fetch_top_competitor_risks",
        lambda passed_engine, limit: [
            {
                "sku": "SKU-REVIEW",
                "name": "需人工覆核的非直接告警候選",
                "momo_price": 999,
                "pchome_price": 500,
                "gap_pct": 99.8,
                "match_score": 0.95,
                "alert_tier": "identity_review",
                "match_type": "exact",
                "price_basis": "total_price",
            },
            {
                "sku": "SKU-1",
                "name": "Derma Angel 護妍天使 集中抗痘精華",
                "momo_price": 420,
                "pchome_price": 250,
                "gap_pct": 68.0,
                "match_score": 0.91,
                "alert_tier": "price_alert_exact",
                "match_type": "exact",
                "price_basis": "total_price",
                "pchome_id": "DABC123",
                "pchome_name": "Derma Angel 集中抗痘精華",
                "crawled_at": "05/31 20:50",
            }
        ],
    )
    monkeypatch.setattr(
        svc,
        "fetch_competitor_coverage",
        lambda passed_engine: {
            "valid_matches": 88,
            "match_rate": 12.3,
            "fresh_matches": 70,
            "fresh_match_rate": 79.5,
            "decision_ready_matches": 70,
            "decision_ready_rate": 9.8,
            "decision_support_count": 105,
            "decision_support_rate": 14.7,
            "decision_support_non_exact_count": 35,
            "catalog_comparable_count": 12,
            "catalog_comparable_rate": 1.7,
            "catalog_variant_review_count": 7,
            "catalog_unit_review_count": 3,
            "catalog_identity_review_count": 2,
            "catalog_review_plan": {
                "variant_review": 7,
                "unit_review": 3,
                "identity_review": 2,
                "total": 12,
            },
            "unit_comparable_count": 23,
            "stale_matches": 18,
            "pending": 612,
        },
    )
    monkeypatch.setattr(
        svc,
        "fetch_competitor_review_queue",
        lambda passed_engine, limit: [
            {
                "sku": "SKU-REVIEW",
                "name": "人工覆核精華液",
                "decision_envelope": {
                    "decision_id": "review_queue:SKU-REVIEW",
                    "severity": "P2",
                    "subject": {
                        "sku": "SKU-REVIEW",
                        "name": "人工覆核精華液",
                        "momo_price": 399,
                        "competitor_price": 329,
                        "competitor_product_id": "PCH-REVIEW",
                    },
                    "recommended_action": {
                        "action": "review_accept_identity",
                        "requires_hitl": True,
                    },
                    "expected_impact": {"candidate_gap_pct": 21.3},
                    "guardrails": {
                        "data_quality": "complete",
                        "can_auto_execute": False,
                    },
                    "evidence": [
                        {
                            "metric": "match_score",
                            "value": 0.91,
                            "basis": "exact/total_price/identity_review",
                        }
                    ],
                },
            }
        ],
    )

    payload = svc.build_webcrumbs_marketplace_host_data(engine=engine, limit=5)

    assert payload["marketSnapshot"][0]["name"].startswith("SKU-1")
    assert payload["marketSnapshot"][0]["price"] == 250
    assert payload["marketSnapshot"][0]["change_pct"] == 68.0
    assert payload["aiCandidate"]["ticker"] == "SKU-1"
    assert payload["aiCandidate"]["confidence_score"] == 0.91
    assert "MOMO NT$420 vs PChome NT$250" in payload["aiCandidate"]["thesis"]
    assert payload["aiCandidate"]["release_status"] == "review_required"
    assert payload["metadata"]["writes_database"] is False
    assert payload["metadata"]["calls_llm"] is False
    assert payload["metadata"]["fetches_external"] is False
    assert payload["metadata"]["matched_count"] == 88
    assert payload["metadata"]["coverage_rate"] == 12.3
    assert payload["metadata"]["identity_coverage_rate"] == 12.3
    assert payload["metadata"]["decision_ready_count"] == 70
    assert payload["metadata"]["decision_ready_rate"] == 9.8
    assert payload["metadata"]["decision_support_count"] == 105
    assert payload["metadata"]["decision_support_rate"] == 14.7
    assert payload["metadata"]["decision_support_non_exact_count"] == 35
    assert payload["metadata"]["catalog_comparable_count"] == 12
    assert payload["metadata"]["catalog_comparable_rate"] == 1.7
    assert payload["metadata"]["catalog_variant_review_count"] == 7
    assert payload["metadata"]["catalog_unit_review_count"] == 3
    assert payload["metadata"]["catalog_identity_review_count"] == 2
    assert payload["metadata"]["catalog_review_plan"]["variant_review"] == 7
    assert payload["metadata"]["catalog_review_plan"]["unit_review"] == 3
    assert payload["metadata"]["catalog_review_plan"]["identity_review"] == 2
    assert payload["metadata"]["unit_comparable_count"] == 23
    assert payload["metadata"]["fresh_match_count"] == 70
    assert payload["metadata"]["fresh_match_rate"] == 79.5
    assert payload["metadata"]["stale_match_count"] == 18
    assert payload["metadata"]["pending_match_count"] == 612
    assert payload["metadata"]["review_queue_count"] == 1
    assert payload["metadata"]["hitl_count"] == 1
    assert payload["metadata"]["auto_execute_blocked_count"] == 1
    assert payload["metadata"]["decision_envelope_source"] == "competitor_intel_repository"
    assert payload["reviewDecisionBrief"]["items"][0]["sku"] == "SKU-REVIEW"
    assert payload["reviewDecisionBrief"]["items"][0]["can_auto_execute"] is False
    assert "review_accept_identity" in payload["reviewDecisionBrief"]["items"][0]["action"]
    assert all(row["freshness_status"] == "price_alert_exact" for row in payload["marketSnapshot"])


def test_webcrumbs_host_data_uses_empty_state_without_risks(monkeypatch):
    monkeypatch.setattr(svc, "fetch_top_competitor_risks", lambda engine, limit: [])
    monkeypatch.setattr(svc, "fetch_competitor_review_queue", lambda engine, limit: [])
    monkeypatch.setattr(
        svc,
        "fetch_competitor_coverage",
        lambda engine: {
            "valid_matches": 3,
            "fresh_matches": 1,
            "decision_support_count": 4,
            "catalog_comparable_count": 2,
            "catalog_variant_review_count": 1,
            "catalog_unit_review_count": 1,
            "catalog_identity_review_count": 0,
            "catalog_review_plan": {
                "variant_review": 1,
                "unit_review": 1,
                "identity_review": 0,
                "total": 2,
            },
            "unit_comparable_count": 1,
            "stale_matches": 2,
            "pending": 9,
        },
    )

    payload = svc.build_webcrumbs_marketplace_host_data(engine=object(), limit=5)

    assert payload["marketSnapshot"][0]["freshness_status"] == "no_current_exact_risk"
    assert payload["aiCandidate"]["release_status"] == "blocked"
    assert payload["metadata"]["matched_count"] == 3
    assert payload["metadata"]["decision_ready_count"] == 1
    assert payload["metadata"]["decision_support_count"] == 4
    assert payload["metadata"]["catalog_comparable_count"] == 2
    assert payload["metadata"]["catalog_variant_review_count"] == 1
    assert payload["metadata"]["catalog_unit_review_count"] == 1
    assert payload["metadata"]["catalog_identity_review_count"] == 0
    assert payload["metadata"]["catalog_review_plan"]["total"] == 2
    assert payload["metadata"]["unit_comparable_count"] == 1
    assert payload["metadata"]["fresh_match_count"] == 1
    assert payload["metadata"]["stale_match_count"] == 2
    assert payload["metadata"]["pending_match_count"] == 9
    assert payload["metadata"]["review_queue_count"] == 0
    assert payload["reviewDecisionBrief"]["text"] == "（目前沒有待覆核決策信封）"
    assert "非同款、單位價或變體候選" in payload["aiCandidate"]["thesis"]


def test_webcrumbs_seed_data_fallback_does_not_expose_demo_values(monkeypatch):
    from services import external_tool_payload_service as payload_service

    def boom(limit):
        raise RuntimeError("db unavailable")

    monkeypatch.setattr(payload_service, "build_webcrumbs_marketplace_host_data", boom)

    payload = payload_service.build_webcrumbs_seed_data(limit=5)

    assert payload["marketSnapshot"][0]["freshness_status"] == "diagnostic_unavailable"
    assert payload["aiCandidate"]["release_status"] == "blocked"
    assert "fallback demo" in payload["aiCandidate"]["thesis"]
    assert "TAIEX" not in str(payload)


def test_webcrumbs_auth_required_seed_data_is_non_sensitive():
    from services.external_tool_payload_service import build_webcrumbs_auth_required_seed_data

    payload = build_webcrumbs_auth_required_seed_data()

    assert payload["marketSnapshot"][0]["freshness_status"] == "auth_required"
    assert payload["aiCandidate"]["release_status"] == "blocked"
    assert payload["metadata"]["source"] == "auth_required"
    assert "MOMO NT$" not in str(payload)
    assert "PChome NT$" not in str(payload)
