from flask import Flask

from services.pchome_mapping_backlog_service import (
    build_pchome_direct_mapping_candidate_decision_lane_closeout_package,
)


def _payload():
    return {
        "success": True,
        "system_name": "MOMO Pro",
        "generated_at": "2026-06-28T01:16:02",
        "cache_state": "fresh",
        "stats": {
            "candidate_count": 4,
            "mapped_count": 1,
            "mapping_rate": 25.0,
            "needs_mapping_count": 3,
            "review_candidate_count": 1,
            "overall_latest_sales_date": "2026-06-24",
            "overall_sales_7d": 2020234.0,
            "action_counts": {
                "先補商品對應": 2,
                "確認候選": 1,
                "放大價格優勢": 1,
            },
            "action_code_counts": {
                "map_external_product": 2,
                "review_external_candidate": 1,
                "amplify_price_advantage": 1,
            },
        },
        "opportunities": [
            {
                "pchome_product_id": "PCH-1",
                "product_name": "Mapped product",
                "sales_7d": 0,
                "external_price": {
                    "momo_sku": "M-1",
                    "price_basis": "unit_price",
                    "gap_pct": 12.5,
                },
                "recommended_action": {
                    "code": "amplify_price_advantage",
                    "label": "放大價格優勢",
                },
                "priority_score": 75.0,
            },
            {
                "pchome_product_id": "PCH-2",
                "product_name": "Direct mapping product 40ml x2",
                "sales_7d": 9800,
                "pchome_price": 1200,
                "external_price": None,
                "recommended_action": {"code": "map_external_product", "label": "先補商品對應"},
                "priority_score": 88.0,
                "reason_lines": ["需要補商品對應"],
            },
            {
                "pchome_product_id": "PCH-3",
                "product_name": "Review candidate product",
                "sales_7d": 1200,
                "external_price": None,
                "review_candidate": {
                    "id": 725,
                    "momo_sku": "5868343",
                    "momo_name": "MOMO candidate",
                    "quality_score": 94.8,
                },
                "recommended_action": {"code": "review_external_candidate", "label": "確認候選"},
                "priority_score": 64.0,
            },
        ],
    }


def test_candidate_decision_lane_closeout_outputs_receipt_replay_drift_and_readiness(tmp_path):
    def fake_search(targets, limit_per_product, max_products, max_terms_per_product, min_score):
        return True, "found", [
            {
                "product_id": "MOMO-1",
                "name": "Direct mapping product 40ml x2",
                "price": 999,
                "target_pchome_product_id": "PCH-2",
                "target_pchome_name": "Direct mapping product 40ml x2",
                "target_match_score": 0.92,
                "auto_compare_type": "total_price",
                "target_hard_veto": False,
                "target_price_basis": "total_price",
                "target_gap_pct": 16.8,
                "target_search_term": "direct mapping product 40ml x2",
            },
            {
                "product_id": "MOMO-2",
                "name": "Variant candidate",
                "price": 899,
                "target_pchome_product_id": "PCH-2",
                "target_pchome_name": "Direct mapping product 40ml x2",
                "target_match_score": 0.51,
                "auto_compare_type": "manual_review",
                "target_hard_veto": False,
            },
        ]

    package = build_pchome_direct_mapping_candidate_decision_lane_closeout_package(
        _payload(),
        batch_size=1,
        execute_search=True,
        limit_per_product=3,
        search_func=fake_search,
        artifact_root=tmp_path,
    )

    assert package["policy"] == "read_only_pchome_growth_direct_mapping_candidate_decision_lane_closeout"
    assert package["result"] == "DIRECT_MAPPING_CANDIDATE_DECISION_LANE_CLOSEOUT_READY"
    assert package["summary"]["candidate_decision_count"] == 2
    assert package["summary"]["auto_compare_decision_count"] == 1
    assert package["summary"]["machine_review_decision_count"] == 1
    assert package["summary"]["receipt_payload_hash_ready_count"] == 1
    assert package["summary"]["replay_verified_count"] == 1
    assert package["summary"]["drift_count"] == 0
    assert package["summary"]["primary_human_gate_count"] == 0
    assert package["lane_receipt"]["receipt_status"] == "candidate_decision_lane_receipt_ready"
    assert package["receipt_replay"]["passed"] is True
    assert package["drift_verifier"]["status"] == "verified"
    assert package["product_readiness"]["status"] == "ready_for_next_automation"
    assert package["product_readiness"]["automation_policy"]["primary_flow"] == "ai_controlled"
    assert package["product_readiness"]["primary_human_gate_count"] == 0
    assert package["safety"]["writes_database"] is False
    assert package["safety"]["writes_artifact_count"] == 0
    assert package["all_checks_passed"] is True


def test_candidate_decision_lane_closeout_route_defaults_to_cached_no_db_no_search(monkeypatch):
    from routes import ai_routes as routes

    monkeypatch.setattr(routes, "_get_cached_pchome_growth_payload", lambda: _payload())

    def fail_engine(database_path):
        raise AssertionError("cached candidate decision lane closeout should not open a DB engine")

    monkeypatch.setattr(routes, "_create_icaim_dashboard_engine", fail_engine)

    app = Flask(__name__)
    with app.test_request_context(
        "/api/ai/pchome-growth/mapping-backlog/direct-mapping-candidate-decision-lane-closeout-package?batch_size=1"
    ):
        response = (
            routes
            .api_pchome_growth_direct_mapping_candidate_decision_lane_closeout_package
            .__wrapped__()
        )

    payload = response.get_json()
    assert payload["success"] is True
    assert payload["policy"] == "read_only_pchome_growth_direct_mapping_candidate_decision_lane_closeout"
    assert payload["source_endpoint"] == (
        "/api/ai/pchome-growth/mapping-backlog/direct-mapping-candidate-decision-package"
    )
    assert payload["result"] == "WAITING_FOR_DIRECT_MAPPING_CANDIDATE_DECISION_LANE_CANDIDATES"
    assert payload["summary"]["candidate_decision_count"] == 0
    assert payload["summary"]["replay_verified_count"] == 1
    assert payload["summary"]["drift_count"] == 0
    assert payload["product_readiness"]["status"] == "waiting_for_read_only_search"
    assert payload["product_readiness"]["primary_human_gate_count"] == 0
    assert payload["safety"]["executes_search"] is False
    assert payload["safety"]["writes_database"] is False


def test_ai_automation_surface_summary_route_defaults_to_cached_no_db(monkeypatch):
    from routes import ai_routes as routes

    monkeypatch.setattr(routes, "_get_cached_pchome_growth_payload", lambda: _payload())

    def fail_engine(database_path):
        raise AssertionError("cached AI automation surface summary should not open a DB engine")

    monkeypatch.setattr(routes, "_create_icaim_dashboard_engine", fail_engine)

    app = Flask(__name__)
    with app.test_request_context(
        "/api/ai/pchome-growth/ai-automation-surface-summary"
        "?batch_size=1&include_receipt_replay=false&include_drift_verifier=false"
    ):
        response = routes.api_pchome_growth_ai_automation_surface_summary.__wrapped__()

    payload = response.get_json()
    signals = {signal["key"]: signal for signal in payload["golden_signals"]}
    assert payload["success"] is True
    assert payload["policy"] == "read_only_pchome_growth_ai_automation_surface_summary"
    assert payload["source_endpoint"] == "/api/ai/pchome-growth/ai-automation-readiness"
    assert payload["summary"]["safe_lane_count"] >= 4
    assert payload["summary"]["primary_human_gate_count"] == 0
    assert payload["summary"]["writes_database_count"] == 0
    assert set(signals) == {
        "automated-landing",
        "verified",
        "change-state",
        "next-machine-action",
    }
    assert signals["next-machine-action"]["next_machine_action"]
    assert payload["safety"]["writes_database"] is False
    assert payload["safety"]["llm_calls_in_preview"] is False
