import sys
import types


def test_price_decision_envelope_has_hilt_guardrails():
    import services.nemoton_dispatcher_service as module

    envelope = module._build_price_decision_envelope(
        decision_type="price_alert",
        sku="10413050",
        name="測試精華液",
        gap_pct=16.7,
        sales_delta=-31.2,
        confidence=0.91,
        analysis="建議進入人工價格覆核",
        momo_price=1200,
        comp_price=999,
        revenue_loss_7d=65000,
        recommended_price=999,
        match_type="exact",
        price_basis="total_price",
        alert_tier="price_alert_exact",
        match_score=0.93,
        competitor_product_id="PCHOME-1",
        competitor_product_name="PChome 測試精華液",
    )

    assert envelope["decision_type"] == "price_alert"
    assert envelope["severity"] == "P1"
    assert envelope["confidence"] == 0.91
    assert envelope["subject"]["sku"] == "10413050"
    assert envelope["subject"]["competitor_product_id"] == "PCHOME-1"
    assert envelope["guardrails"]["can_auto_execute"] is False
    assert envelope["guardrails"]["data_quality"] == "complete"
    assert envelope["guardrails"]["match_type"] == "exact"
    assert envelope["guardrails"]["price_basis"] == "total_price"
    assert envelope["guardrails"]["alert_tier"] == "price_alert_exact"
    assert envelope["recommended_action"]["requires_hitl"] is True
    assert envelope["expected_impact"]["revenue_loss_7d"] == 65000
    assert envelope["expected_impact"]["gap_amount"] == 201
    assert any(e["metric"] == "match_score" and e["value"] == 0.93 for e in envelope["evidence"])


def test_send_telegram_attaches_decision_envelope_to_event_router(monkeypatch):
    import services.nemoton_dispatcher_service as module

    captured = []
    fake_event_router = types.ModuleType("services.event_router")
    fake_event_router.dispatch_sync = lambda event: captured.append(event)
    monkeypatch.setitem(sys.modules, "services.event_router", fake_event_router)

    envelope = {
        "decision_id": "nemotron:price_alert:SKU-1:abcdef12",
        "decision_type": "price_alert",
        "severity": "P2",
        "guardrails": {"can_auto_execute": False},
    }
    module.NemotronDispatcher()._send_telegram("hello price alert", decision_envelope=envelope)

    assert len(captured) == 1
    event = captured[0]
    assert event["event_type"] == "nemoton_dispatch_alert"
    assert event["id"] == "nemotron:price_alert:SKU-1:abcdef12"
    assert event["decision_envelope"] == envelope
    assert event["payload"]["decision_envelope"] == envelope
    assert event["payload"]["raw_message"] == "hello price alert"


def test_exec_trigger_price_alert_persists_decision_envelope(monkeypatch):
    import services.nemoton_dispatcher_service as module

    dispatcher = module.NemotronDispatcher()
    sent = []
    stored = []
    monkeypatch.setattr(
        dispatcher,
        "_send_telegram",
        lambda message, decision_envelope=None: sent.append((message, decision_envelope)),
    )
    monkeypatch.setattr(
        dispatcher,
        "_sink_insight_to_km",
        lambda *args, **kwargs: stored.append((args, kwargs)),
    )

    dispatcher._exec_trigger_price_alert(
        sku="SKU-1",
        name="測試商品",
        gap_pct=12.5,
        sales_delta=-10.0,
        action="請人工確認是否跟價",
        confidence=0.88,
        momo_price=1000,
        comp_price=875,
        revenue_loss_7d=32000,
        recommended_price=875,
        match_type="exact",
        price_basis="total_price",
        alert_tier="price_alert_exact",
        match_score=0.9,
        competitor_product_id="PC-1",
    )

    assert sent
    _, envelope = sent[0]
    assert envelope["decision_type"] == "price_alert"
    assert envelope["guardrails"]["can_auto_execute"] is False
    assert envelope["subject"]["competitor_product_id"] == "PC-1"
    assert stored
    assert stored[0][1]["metadata"]["decision_envelope"] == envelope
