"""messaging.send resolver — public invoke is invocable; Slack implements the catalog verb."""
from __future__ import annotations

from uuid import uuid4

from src.domain.connectors.catalog import get_action
from src.domain.connectors.invoke_capabilities import MESSAGING_SEND_RESOLVER_DESIGN
from src.domain.connectors.messaging_resolve import (
    DispatchAuthorization,
    MessagingConnectionSnapshot,
    dispatch_messaging_send_plan,
    invoke_messaging_send,
    public_result_is_capability_shaped,
    resolve_messaging_send,
    to_public_messaging_send_result,
)
from src.domain.manifest.service import _connectors_manifest_envelope

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


def _slack(**overrides) -> MessagingConnectionSnapshot:
    data = dict(
        connection_id=uuid4(),
        connector_key="slack",
        status="active",
        has_secrets=True,
        permission_mode="allow",
        config={"destinations": {"ops": "C0123456789"}},
        requires_secrets=True,
        client_side_only=False,
        action_slug="slack.post_message",
    )
    data.update(overrides)
    return MessagingConnectionSnapshot(**data)


def test_public_resolve_is_invocable_with_catalog_implements() -> None:
    result = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[_slack()],
        enabled_capabilities=_CAPS,
        enforce_invocable=True,
    )
    assert result.ok is True
    envelope = _connectors_manifest_envelope(items={})
    assert envelope["capabilities"]["messaging.send"]["invocable"] is True
    assert envelope["capabilities"]["messaging.send"]["implemented_by"] == ["slack.post_message"]
    assert get_action("slack.post_message")[1].implements == ("messaging.send",)


def test_plan_maps_logical_destination_not_slack_semantics() -> None:
    row = _slack()
    result = resolve_messaging_send(
        payload={"destination": "ops", "text": "hello", "thread_ref": "ts1", "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.send"
    assert result.plan.action == "slack.post_message"
    assert result.plan.provider == "slack"
    assert result.plan.resolved_input == {"channel": "C0123456789", "text": "hello", "thread_ts": "ts1"}
    assert "blocks" not in result.plan.resolved_input
    payload = result.plan.integration_execute_payload()
    assert payload["request_type"] == "integration.execute"
    assert payload["action"] == "slack.post_message"


def test_raw_slack_id_is_destination_invalid() -> None:
    result = resolve_messaging_send(
        payload={"destination": "C0123456789", "text": "hello"},
        connections=[_slack()],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert result.reason_code == "destination_invalid"


def test_zero_eligible_is_capability_not_bound_not_email() -> None:
    result = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[_slack(status="inactive"), _slack(has_secrets=False)],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert result.reason_code == "capability_not_bound"
    assert "email.send" in (result.message or "")
    assert {item["reason"] for item in result.diagnostics["rejected"]} == {
        "connection_inactive",
        "credentials_missing",
    }


def test_two_inactive_without_binding_is_not_connection_inactive() -> None:
    result = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[_slack(status="inactive"), _slack(has_secrets=False)],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert result.reason_code == "capability_not_bound"


def test_explicit_binding_inactive() -> None:
    row = _slack(status="inactive")
    result = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[row, _slack(has_secrets=False)],
        enabled_capabilities=_CAPS,
        binding_connection_id=row.connection_id,
        enforce_invocable=False,
    )
    assert result.reason_code == "connection_inactive"


def test_explicit_binding_credentials_missing() -> None:
    row = _slack(has_secrets=False)
    result = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[row],
        enabled_capabilities=_CAPS,
        binding_connection_id=row.connection_id,
        enforce_invocable=False,
    )
    assert result.reason_code == "credentials_missing"


def test_multiple_eligible_is_ambiguous() -> None:
    result = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[_slack(), _slack()],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert result.reason_code == "binding_ambiguous"


def test_provider_hint_disambiguates_without_persisting() -> None:
    slack = _slack()
    # A second slack connection still ambiguous even with hint=slack
    result = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[slack, _slack()],
        enabled_capabilities=_CAPS,
        provider_hint="slack",
        enforce_invocable=False,
    )
    assert result.reason_code == "binding_ambiguous"
    one = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[slack],
        enabled_capabilities=_CAPS,
        provider_hint="slack",
        enforce_invocable=False,
    )
    assert one.ok is True
    assert one.plan.connection_id == slack.connection_id


def test_unmapped_destination_after_unique_connection() -> None:
    row = _slack(config={})
    result = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[row],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert result.reason_code == "destination_unbound"


def test_twilio_is_not_a_messaging_candidate() -> None:
    twilio = MessagingConnectionSnapshot(
        connection_id=uuid4(),
        connector_key="twilio",
        status="active",
        has_secrets=True,
        permission_mode="allow",
        config={},
        requires_secrets=True,
    )
    result = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[twilio],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert result.reason_code == "capability_not_bound"


def test_stripped_metadata_does_not_enter_resolved_input() -> None:
    row = _slack()
    result = resolve_messaging_send(
        payload={"destination": "ops", "text": "hi", "metadata": {"blocks": [], "order_id": "1"}},
        connections=[row],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert result.ok is True
    assert "blocks" not in result.plan.resolved_input
    assert result.diagnostics["stripped_metadata_keys"] == ["blocks"]


def test_resolver_design_order_and_unique_errors() -> None:
    design = MESSAGING_SEND_RESOLVER_DESIGN
    assert design["status"] == "codegen_default"
    assert design["catalog_invocable"] is True
    assert design["implements_attached"] is True
    assert design["codegen_default"] is True
    assert design["slack_demoted_to_provider_actions"] is True
    assert design["public_result"] == "capability_shaped"
    assert design["evaluation_order"][0] == "capability_exists"
    assert design["evaluation_order"][1] == "capability_invocable"
    assert design["evaluation_order"][-1] == "return_execution_plan"
    assert "only when an explicit binding" in design["unique_connection_errors"]["connection_inactive"]
    assert design["dispatch"] == "integration.execute"
    assert design["resolver_eligibility_is_not_execution_authorization"] is True
    assert design["flip_order"][0].startswith("invocable_true")
    assert design["flip_order"][-1].startswith("demote_slack")


def test_one_valid_slack_plan_and_dispatch_succeeds() -> None:
    row = _slack()
    result = invoke_messaging_send(
        payload=_PAYLOAD,
        connections=[row],
        enabled_capabilities=_CAPS,
        authorize=DispatchAuthorization(allowed=True),
        enforce_invocable=False,
    )
    assert result.ok is True
    assert result.diagnostics["authorization"] == "allowed"
    assert result.diagnostics["payload"]["action"] == "slack.post_message"


def test_explicit_binding_selects_one_of_two_eligible() -> None:
    a, b = _slack(), _slack()
    result = resolve_messaging_send(
        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.connection_id == b.connection_id


def test_destination_map_overlay_binds_logical_name() -> None:
    row = _slack(config={})
    result = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[row],
        enabled_capabilities=_CAPS,
        destination_map={"ops": "C9999999999"},
        enforce_invocable=False,
    )
    assert result.ok is True
    assert result.plan.resolved_input["channel"] == "C9999999999"


def test_provider_hint_mismatch_is_capability_not_bound() -> None:
    result = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[_slack()],
        enabled_capabilities=_CAPS,
        provider_hint="teams",
        enforce_invocable=False,
    )
    assert result.reason_code == "capability_not_bound"


def test_ask_without_approval_is_not_eligible() -> None:
    result = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[_slack(permission_mode="ask")],
        enabled_capabilities=_CAPS,
        approval_present=False,
        enforce_invocable=False,
    )
    assert result.reason_code == "capability_not_bound"
    assert result.diagnostics["rejected"][0]["reason"] == "approval_required"


def test_ask_with_approval_is_eligible() -> None:
    result = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[_slack(permission_mode="ask")],
        enabled_capabilities=_CAPS,
        approval_present=True,
        enforce_invocable=False,
    )
    assert result.ok is True


def test_dispatch_rejects_when_authorization_fails_after_plan() -> None:
    row = _slack()
    planned = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[row],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert planned.ok is True
    dispatched = dispatch_messaging_send_plan(
        planned.plan,
        DispatchAuthorization(allowed=False, reason_code="connection_inactive", message="gone"),
        diagnostics=planned.diagnostics,
    )
    assert dispatched.ok is False
    assert dispatched.reason_code == "connection_inactive"
    assert dispatched.diagnostics["authorization"] == "rejected"
    assert dispatched.diagnostics["payload"]["action"] == "slack.post_message"


def test_block_kit_is_not_on_the_capability_path() -> None:
    row = _slack()
    result = resolve_messaging_send(
        payload={"destination": "ops", "text": "hi", "metadata": {"blocks": [{"type": "section"}]}},
        connections=[row],
        enabled_capabilities=_CAPS,
        enforce_invocable=False,
    )
    assert result.ok is True
    assert "blocks" not in result.plan.resolved_input
    assert get_action("slack.post_message")[1].slug == "slack.post_message"
    assert "blocks" in (get_action("slack.post_message")[1].input_schema.get("properties") or {})


def test_public_result_is_capability_shaped_not_plan_shaped() -> None:
    row = _slack()
    planned = resolve_messaging_send(
        payload={"destination": "ops", "text": "hello", "thread_ref": "opaque-1"},
        connections=[row],
        enabled_capabilities=_CAPS,
    )
    assert planned.ok is True
    public = to_public_messaging_send_result(
        planned,
        thread_ref="opaque-1",
        enqueue={"ok": True, "job_id": "job_abc"},
    )
    body = public.as_dict()
    assert public_result_is_capability_shaped(body)
    assert body == {
        "capability": "messaging.send",
        "status": "queued",
        "message_id": "job_abc",
        "thread_ref": "opaque-1",
    }
    assert "channel" not in body
    assert "thread_ts" not in body
    assert "action" not in body
    assert planned.plan.resolved_input["channel"] == "C0123456789"


def test_public_result_hides_plan_when_enqueue_fails() -> None:
    planned = resolve_messaging_send(
        payload=_PAYLOAD,
        connections=[_slack()],
        enabled_capabilities=_CAPS,
    )
    public = to_public_messaging_send_result(
        planned,
        enqueue={"ok": False, "reason_code": "connection_inactive", "message": "gone"},
    )
    body = public.as_dict()
    assert public_result_is_capability_shaped(body)
    assert body["status"] == "rejected"
    assert body["reason_code"] == "connection_inactive"
    assert "channel" not in body
    assert "payload" not in body

