"""notification.sms resolver around the live Twilio path — not public/invocable yet."""
from __future__ import annotations

from uuid import uuid4

from src.domain.connectors.notification_sms import (
    NotificationSmsConnectionSnapshot,
    map_notification_sms_to_twilio_input,
    normalize_e164,
    public_result_is_capability_shaped,
    resolve_notification_sms,
    resolve_sender_from_connection_config,
    to_public_notification_sms_result,
)

_CAPS = {"integrations.execute"}
_PAYLOAD = {"destination": "+14155550123", "text": "hello"}


def _twilio(**overrides) -> NotificationSmsConnectionSnapshot:
    data = dict(
        connection_id=uuid4(),
        connector_key="twilio",
        status="active",
        has_secrets=True,
        permission_mode="allow",
        config={"from_phone": "+15551234567"},
        requires_secrets=True,
        client_side_only=False,
        action_slug="twilio.send_sms",
    )
    data.update(overrides)
    return NotificationSmsConnectionSnapshot(**data)


def test_catalog_invocable_gate_allows_public_resolve() -> None:
    result = resolve_notification_sms(
        payload=_PAYLOAD,
        connections=[_twilio()],
        enabled_capabilities=_CAPS,
        enforce_invocable=True,
    )
    assert result.ok is True
    assert result.plan is not None


def test_e164_normalization_and_rejects() -> None:
    assert normalize_e164("+14155550123") == "+14155550123"
    assert normalize_e164("+1 (415) 555-0123") == "+14155550123"
    assert normalize_e164("14155550123") is None
    assert normalize_e164("whatsapp:+14155550123") is None
    assert normalize_e164("MGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") is None
    assert normalize_e164("ops") is None


def test_generic_fields_map_to_existing_twilio_input_without_sender() -> None:
    mapped = map_notification_sms_to_twilio_input(destination="+14155550123", text="hello")
    assert mapped == {"to": "+14155550123", "body": "hello"}
    assert "from" not in mapped
    assert "media_url" not in mapped
    assert "messaging_service_sid" not in mapped


def test_sender_comes_from_connection_config() -> None:
    assert resolve_sender_from_connection_config(
        {"messaging_service_sid": "MG123", "from_phone": "+15551234567"}
    ) == {"source": "messaging_service_sid", "messaging_service_sid": "MG123"}
    assert resolve_sender_from_connection_config({"from_phone": "+15551234567"}) == {
        "source": "from_phone",
        "from_phone": "+15551234567",
    }
    assert resolve_sender_from_connection_config({}) is None


def test_plan_reuses_twilio_send_sms_without_from() -> None:
    row = _twilio()
    result = resolve_notification_sms(
        payload={"destination": "+1 415 555 0123", "text": "hello", "metadata": {"order_id": "9"}},
        connections=[row],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert result.ok is True
    assert result.plan is not None
    assert result.plan.capability == "messaging.sms.send"
    assert result.plan.action == "twilio.send_sms"
    assert result.plan.provider == "twilio"
    assert result.plan.resolved_input == {"to": "+14155550123", "body": "hello"}
    assert result.plan.sender_source == "from_phone"
    payload = result.plan.integration_execute_payload()
    assert payload["request_type"] == "integration.execute"
    assert payload["action"] == "twilio.send_sms"
    assert "from" not in payload["input"]


def test_messaging_service_sid_wins_as_sender_source() -> None:
    result = resolve_notification_sms(
        payload=_PAYLOAD,
        connections=[
            _twilio(config={"messaging_service_sid": "MGabc", "from_phone": "+15550001111"})
        ],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert result.ok is True
    assert result.plan is not None
    assert result.plan.sender_source == "messaging_service_sid"
    assert result.plan.resolved_input == {"to": "+14155550123", "body": "hello"}


def test_missing_sender_config_is_sender_unbound() -> None:
    result = resolve_notification_sms(
        payload=_PAYLOAD,
        connections=[_twilio(config={})],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert result.reason_code == "sender_unbound"


def test_zero_eligible_is_capability_not_bound() -> None:
    result = resolve_notification_sms(
        payload=_PAYLOAD,
        connections=[],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert result.reason_code == "capability_not_bound"


def test_two_twilio_accounts_are_ambiguous_without_binding() -> None:
    result = resolve_notification_sms(
        payload=_PAYLOAD,
        connections=[_twilio(), _twilio()],
        enabled_capabilities=_CAPS,
        provider_hint="twilio",
        enforce_invocable=False,
    )
    assert result.reason_code == "binding_ambiguous"


def test_explicit_binding_selects_one_twilio_account() -> None:
    a = _twilio()
    b = _twilio()
    result = resolve_notification_sms(
        payload=_PAYLOAD,
        connections=[a, b],
        enabled_capabilities=_CAPS,
        binding_connection_id=b.connection_id,
        enforce_invocable=False,
    )
    assert result.ok is True
    assert result.plan is not None
    assert result.plan.connection_id == b.connection_id


def test_slack_is_not_a_notification_sms_candidate() -> None:
    slack = NotificationSmsConnectionSnapshot(
        connection_id=uuid4(),
        connector_key="slack",
        status="active",
        has_secrets=True,
        permission_mode="allow",
        config={"from_phone": "+15551234567"},
    )
    result = resolve_notification_sms(
        payload=_PAYLOAD,
        connections=[slack],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert result.reason_code == "capability_not_bound"


def test_twilio_from_on_capability_input_is_forbidden() -> None:
    result = resolve_notification_sms(
        payload={"destination": "+14155550123", "text": "hello", "from": "+15550001111"},
        connections=[_twilio()],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert result.reason_code == "provider_fields_forbidden"


def test_media_url_stays_on_escape_hatch() -> None:
    result = resolve_notification_sms(
        payload={"destination": "+14155550123", "text": "hello", "media_url": ["https://x/a.png"]},
        connections=[_twilio()],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert result.reason_code == "provider_fields_forbidden"


def test_public_result_hides_twilio_ids() -> None:
    resolution = resolve_notification_sms(
        payload=_PAYLOAD,
        connections=[_twilio()],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    public = to_public_notification_sms_result(resolution, enqueue={"ok": True, "job_id": "job_1"})
    body = public.as_dict()
    assert public_result_is_capability_shaped(body)
    assert body == {"capability": "messaging.sms.send", "status": "queued", "message_id": "job_1"}
    assert "twilio_sid" not in body
    assert "from_number" not in body
    rejected = to_public_notification_sms_result(resolution).as_dict()
    assert rejected["status"] == "rejected"
    assert rejected["reason_code"] == "provider_unavailable"
