"""Phase 10.5 — Dispatch Engine tests."""
from __future__ import annotations

import pytest

from app.events.publisher import get_event_publisher
from app.models.types import DispatchJobAction
from app.tests.conftest import TENANT_A, tenant_headers
from app.validators.dispatch import ensure_dispatch_job_transition


def test_dispatch_transition_matrix():
    from app.models.types import DispatchJobStatus

    ensure_dispatch_job_transition(
        action=DispatchJobAction.ASSIGN, current=DispatchJobStatus.PENDING
    )


@pytest.mark.asyncio
async def test_dispatch_job_lifecycle(client):
    org = await client.post(
        "/api/v1/organizations",
        headers=tenant_headers(TENANT_A),
        json={"code": "ORG_D105", "name": "Dispatch Org", "status": "active"},
    )
    assert org.status_code == 201
    org_id = org.json()["id"]

    job = await client.post(
        "/api/v1/dispatch/jobs",
        headers=tenant_headers(TENANT_A),
        json={
            "organization_id": org_id,
            "code": "JOB1",
            "external_order_ref": "ORD-100",
        },
    )
    assert job.status_code == 201, job.text
    jid = job.json()["id"]
    version = job.json()["version"]

    assigned = await client.post(
        f"/api/v1/dispatch/jobs/{jid}/status",
        headers=tenant_headers(TENANT_A),
        json={"action": "assign", "version": version},
    )
    assert assigned.status_code == 200
    assert assigned.json()["status"] == "assigned"

    driver = await client.post(
        "/api/v1/drivers",
        headers=tenant_headers(TENANT_A),
        json={
            "organization_id": org_id,
            "code": "DRV_D105",
            "display_name": "Dispatch Driver",
            "status": "active",
        },
    )
    assert driver.status_code == 201

    assignment = await client.post(
        "/api/v1/dispatch/assignments",
        headers=tenant_headers(TENANT_A),
        json={"dispatch_job_id": jid, "driver_id": driver.json()["id"]},
    )
    assert assignment.status_code == 201

    events = {e.event_type for e in get_event_publisher().published}
    assert "delivery.dispatch_job.created" in events
    assert "delivery.dispatch_job.status_changed" in events
    assert "delivery.job_assignment.created" in events
