"""automation.workflow.trigger resolver — Phase 1C Make and n8n candidates, same binding rules."""
from __future__ import annotations

from uuid import uuid4

from src.domain.connectors.automation_workflow import (
    AutomationWorkflowConnectionSnapshot,
    DispatchAuthorization,
    invoke_automation_workflow_trigger,
    map_automation_input_to_provider_payload,
    normalize_logical_workflow,
    public_result_is_capability_shaped,
    resolve_automation_workflow_trigger,
    to_public_automation_workflow_result,
)

_CAPS = {"integrations.execute"}
_PAYLOAD = {
    "workflow": "lead-intake",
    "input": {"name": "Jane", "email": "jane@example.com"},
}


def _conn(key="make_com", **overrides) -> AutomationWorkflowConnectionSnapshot:
    data = dict(
        connection_id=uuid4(),
        connector_key=key,
        status="active",
        has_secrets=False,
        permission_mode="allow",
        config={"webhook_url": "https://hook.example/abc", "workflow": "lead-intake"},
        requires_secrets=False,
        client_side_only=False,
    )
    data.update(overrides)
    return AutomationWorkflowConnectionSnapshot(**data)


def test_public_resolve_uses_make_alias() -> None:
    result = resolve_automation_workflow_trigger(
        payload=_PAYLOAD,
        connections=[_conn()],
        enabled_capabilities=_CAPS,
    )
    assert result.ok is True
    assert result.plan is not None
    assert result.plan.action == "make_com.trigger_scenario"
    assert result.plan.resolved_input == {
        "payload": {"name": "Jane", "email": "jane@example.com"}
    }


def test_n8n_alias_is_a_live_runtime_candidate() -> None:
    result = resolve_automation_workflow_trigger(
        payload=_PAYLOAD,
        connections=[_conn("n8n")],
        enabled_capabilities=_CAPS,
    )
    assert result.ok is True
    assert result.plan is not None
    assert result.plan.action == "n8n.trigger_workflow"
    assert result.plan.connector_key == "n8n"
    assert result.plan.resolved_input == {
        "payload": {"name": "Jane", "email": "jane@example.com"}
    }


def test_logical_workflow_rejects_provider_ids_and_urls() -> None:
    assert normalize_logical_workflow("lead-intake") == "lead-intake"
    assert normalize_logical_workflow("3918237") is None
    assert normalize_logical_workflow("https://hook.us1.make.com/abc") is None
    mapped = map_automation_input_to_provider_payload(_PAYLOAD["input"])
    assert mapped == {"payload": {"name": "Jane", "email": "jane@example.com"}}


def test_unique_make_without_alias_is_unbound() -> None:
    result = resolve_automation_workflow_trigger(
        payload=_PAYLOAD,
        connections=[_conn(config={"webhook_url": "https://hook.example/abc"})],
        enabled_capabilities=_CAPS,
    )
    assert result.ok is False
    assert result.reason_code == "workflow_unbound"


def test_unique_n8n_without_alias_is_unbound() -> None:
    result = resolve_automation_workflow_trigger(
        payload=_PAYLOAD,
        connections=[_conn("n8n", config={"webhook_url": "https://n8n.example/b"})],
        enabled_capabilities=_CAPS,
    )
    assert result.ok is False
    assert result.reason_code == "workflow_unbound"


def test_workflow_map_binds_n8n_without_alias() -> None:
    row = _conn("n8n", config={"webhook_url": "https://n8n.example/b"})
    result = resolve_automation_workflow_trigger(
        payload=_PAYLOAD,
        connections=[row],
        enabled_capabilities=_CAPS,
        workflow_map={"lead-intake": row.connection_id},
    )
    assert result.ok is True
    assert result.plan is not None
    assert result.plan.action == "n8n.trigger_workflow"
    assert result.plan.connection_id == row.connection_id


def test_make_plus_n8n_without_alias_is_ambiguous() -> None:
    result = resolve_automation_workflow_trigger(
        payload=_PAYLOAD,
        connections=[
            _conn(config={"webhook_url": "https://hook.example/a"}),
            _conn("n8n", config={"webhook_url": "https://n8n.example/b"}),
        ],
        enabled_capabilities=_CAPS,
    )
    assert result.ok is False
    assert result.reason_code == "binding_ambiguous"


def test_shared_alias_on_make_and_n8n_is_ambiguous() -> None:
    result = resolve_automation_workflow_trigger(
        payload=_PAYLOAD,
        connections=[_conn(), _conn("n8n")],
        enabled_capabilities=_CAPS,
    )
    assert result.ok is False
    assert result.reason_code == "binding_ambiguous"


def test_provider_hint_filters_family_and_does_not_invent_a_binding() -> None:
    result = resolve_automation_workflow_trigger(
        payload=_PAYLOAD,
        connections=[
            _conn(config={"webhook_url": "https://hook.example/a"}),
            _conn("n8n", config={"webhook_url": "https://n8n.example/b"}),
        ],
        enabled_capabilities=_CAPS,
        provider_hint="n8n",
    )
    assert result.ok is False
    assert result.reason_code == "workflow_unbound"


def test_provider_hint_selects_n8n_among_aliased_families() -> None:
    result = resolve_automation_workflow_trigger(
        payload=_PAYLOAD,
        connections=[_conn(), _conn("n8n")],
        enabled_capabilities=_CAPS,
        provider_hint="n8n",
    )
    assert result.ok is True
    assert result.plan is not None
    assert result.plan.action == "n8n.trigger_workflow"


def test_provider_ids_in_payload_are_forbidden() -> None:
    result = resolve_automation_workflow_trigger(
        payload={"workflow_id": "123", "workflow": "lead-intake", "input": {}},
        connections=[_conn("n8n")],
        enabled_capabilities=_CAPS,
    )
    assert result.ok is False
    assert result.reason_code == "provider_fields_forbidden"


def test_zapier_is_not_a_candidate() -> None:
    result = resolve_automation_workflow_trigger(
        payload=_PAYLOAD,
        connections=[_conn("zapier", config={"workflow": "lead-intake"})],
        enabled_capabilities=_CAPS,
    )
    assert result.ok is False
    assert result.reason_code == "capability_not_bound"


def test_public_result_hides_webhook_and_action() -> None:
    resolution = resolve_automation_workflow_trigger(
        payload=_PAYLOAD,
        connections=[_conn("n8n")],
        enabled_capabilities=_CAPS,
    )
    public = to_public_automation_workflow_result(
        resolution, enqueue={"ok": True, "job_id": "job_n8n_1"}
    )
    assert public == {
        "capability": "automation.workflow.trigger",
        "status": "queued",
        "execution_ref": "job_n8n_1",
    }
    assert public_result_is_capability_shaped(public)
    assert "workflow_id" not in public
    assert "webhook_url" not in public
    assert "action" not in public


def test_dispatch_rechecks_authorization_for_n8n() -> None:
    allowed = invoke_automation_workflow_trigger(
        payload=_PAYLOAD,
        connections=[_conn("n8n")],
        enabled_capabilities=_CAPS,
        authorize=DispatchAuthorization(allowed=True, reason_code=None, message=None),
    )
    assert allowed.ok is True
    assert allowed.plan is not None
    assert allowed.plan.action == "n8n.trigger_workflow"
