"""Consumer connectors, widgets & notify dispatch API tests — Phase 11.9."""
import pytest

from app.tests.conftest import TENANT_A, TENANT_B, tenant_headers


async def _workspace(client, code="integrations"):
    response = await client.post(
        "/api/v1/workspaces",
        json={"code": code, "name": "Integrations", "status": "active"},
        headers=tenant_headers(TENANT_A),
    )
    assert response.status_code == 201, response.text
    return response.json()


async def _site(client, workspace_id, code="main-site"):
    response = await client.post(
        "/api/v1/sites",
        json={
            "workspace_id": workspace_id,
            "code": code,
            "name": "Main Site",
            "default_locale": "fa",
            "default_direction": "rtl",
        },
        headers=tenant_headers(TENANT_A),
    )
    assert response.status_code == 201, response.text
    return response.json()


@pytest.mark.asyncio
async def test_connector_widget_notify_happy_path(client):
    caps = (await client.get("/capabilities")).json()
    assert caps["phase"] == "11.10"
    assert caps["features"]["widgets"] is True
    assert caps["features"]["consumer_connectors"] is True

    ws = await _workspace(client)
    site = await _site(client, ws["id"])
    headers = tenant_headers(TENANT_A)

    registration = await client.post(
        "/api/v1/consumer-connector-registrations",
        json={
            "workspace_id": ws["id"],
            "site_id": site["id"],
            "kind": "hospitality",
            "code": "hosp-1",
            "name": "Hospitality Connector",
            "status": "active",
        },
        headers=headers,
    )
    assert registration.status_code == 201, registration.text
    reg_id = registration.json()["id"]

    dispatch = await client.post(
        "/api/v1/consumer-connector-dispatches",
        json={
            "registration_id": reg_id,
            "workspace_id": ws["id"],
            "site_id": site["id"],
            "direction": "outbound",
            "event_type": "menu.sync",
            "payload_ref": "menu:123",
        },
        headers=headers,
    )
    assert dispatch.status_code == 201, dispatch.text
    executed = await client.post(
        f"/api/v1/consumer-connector-dispatches/{dispatch.json()['id']}/execute",
        headers=headers,
    )
    assert executed.status_code == 200, executed.text
    assert executed.json()["status"] == "acknowledged"
    assert executed.json()["response_json"]["provider"] == "mock_hospitality"

    definition = await client.post(
        "/api/v1/widget-definitions",
        json={
            "workspace_id": ws["id"],
            "code": "menu-embed",
            "widget_kind": "menu_embed",
            "name": "Menu Embed",
            "status": "available",
            "connector_kind": "hospitality",
        },
        headers=headers,
    )
    assert definition.status_code == 201, definition.text

    instance = await client.post(
        "/api/v1/widget-instances",
        json={
            "workspace_id": ws["id"],
            "site_id": site["id"],
            "widget_definition_id": definition.json()["id"],
            "widget_kind": "menu_embed",
            "code": "menu-1",
            "name": "Menu Widget",
            "status": "active",
            "connector_registration_id": reg_id,
            "embed_ref": "embed:menu:main",
        },
        headers=headers,
    )
    assert instance.status_code == 201, instance.text
    embed = await client.get(
        "/api/v1/widget-instances/by-embed/embed:menu:main",
        headers=headers,
    )
    assert embed.status_code == 200, embed.text
    assert embed.json()["code"] == "menu-1"

    notify = await client.post(
        "/api/v1/notify-dispatches",
        json={
            "workspace_id": ws["id"],
            "site_id": site["id"],
            "widget_instance_id": instance.json()["id"],
            "channel": "sms",
            "template_key": "widget.notify",
            "to_ref": "user:1",
            "payload_json": {"message": "hello"},
        },
        headers=headers,
    )
    assert notify.status_code == 201, notify.text
    sent = await client.post(
        f"/api/v1/notify-dispatches/{notify.json()['id']}/send",
        headers=headers,
    )
    assert sent.status_code == 200, sent.text
    body = sent.json()
    assert body["status"] == "sent"
    assert body["communication_request_ref"].startswith("communication:request:")


@pytest.mark.asyncio
async def test_tenant_isolation(client):
    ws = await _workspace(client, "iso")
    site = await _site(client, ws["id"], "iso-site")
    headers = tenant_headers(TENANT_A)

    registration = await client.post(
        "/api/v1/consumer-connector-registrations",
        json={
            "workspace_id": ws["id"],
            "kind": "crm",
            "code": "crm-iso",
            "name": "CRM",
            "status": "active",
        },
        headers=headers,
    )
    assert registration.status_code == 201, registration.text
    reg_id = registration.json()["id"]

    other = await client.get(
        f"/api/v1/consumer-connector-registrations/{reg_id}",
        headers=tenant_headers(TENANT_B),
    )
    assert other.status_code == 404


@pytest.mark.asyncio
async def test_rejects_forbidden_ownership_keys(client):
    ws = await _workspace(client, "forbidden")
    headers = tenant_headers(TENANT_A)

    rejected_config = await client.post(
        "/api/v1/consumer-connector-registrations",
        json={
            "workspace_id": ws["id"],
            "kind": "communication",
            "code": "bad-config",
            "name": "Bad",
            "config_json": {"sms_provider": "local"},
        },
        headers=headers,
    )
    assert rejected_config.status_code == 422

    rejected_meta = await client.post(
        "/api/v1/widget-definitions",
        json={
            "code": "bad-meta",
            "widget_kind": "custom",
            "name": "Bad Meta",
            "metadata_json": {"booking_engine": "local"},
        },
        headers=headers,
    )
    assert rejected_meta.status_code == 422

    registration = await client.post(
        "/api/v1/consumer-connector-registrations",
        json={
            "workspace_id": ws["id"],
            "kind": "marketplace",
            "code": "inactive",
            "name": "Inactive",
            "status": "draft",
        },
        headers=headers,
    )
    assert registration.status_code == 201, registration.text
    dispatch = await client.post(
        "/api/v1/consumer-connector-dispatches",
        json={
            "registration_id": registration.json()["id"],
            "workspace_id": ws["id"],
            "direction": "outbound",
            "event_type": "catalog.sync",
        },
        headers=headers,
    )
    assert dispatch.status_code == 201, dispatch.text
    executed = await client.post(
        f"/api/v1/consumer-connector-dispatches/{dispatch.json()['id']}/execute",
        headers=headers,
    )
    assert executed.status_code == 200, executed.text
    assert executed.json()["status"] == "failed"
