"""Sports Center API foundation flow — Phase 9.0."""
from __future__ import annotations

import pytest

from app.events.publisher import get_event_publisher
from app.events.types import SportsCenterEventType
from app.tests.conftest import TENANT_A, TENANT_B, tenant_headers


@pytest.mark.asyncio
async def test_health(client):
    resp = await client.get("/health")
    assert resp.status_code == 200
    body = resp.json()
    assert body["service"] == "sports-center-service"
    assert body["status"] == "ok"
    assert body["version"] == "0.9.2.0"


@pytest.mark.asyncio
async def test_foundation_flow_and_events(client):
    center = await client.post(
        "/api/v1/sports-centers",
        json={"code": "main", "name": "Main Sports Center", "status": "active"},
        headers=tenant_headers(TENANT_A),
    )
    assert center.status_code == 201, center.text
    center_id = center.json()["id"]
    assert center.json()["code"] == "MAIN"

    branch = await client.post(
        "/api/v1/branches",
        json={"sports_center_id": center_id, "code": "b1", "name": "Branch 1"},
        headers=tenant_headers(TENANT_A),
    )
    assert branch.status_code == 201, branch.text

    sport = await client.post(
        "/api/v1/sports",
        json={"sports_center_id": center_id, "code": "yoga", "name": "Yoga"},
        headers=tenant_headers(TENANT_A),
    )
    assert sport.status_code == 201, sport.text

    mtype = await client.post(
        "/api/v1/membership-types",
        json={"sports_center_id": center_id, "code": "monthly", "name": "Monthly"},
        headers=tenant_headers(TENANT_A),
    )
    assert mtype.status_code == 201, mtype.text
    mtype_id = mtype.json()["id"]

    membership = await client.post(
        "/api/v1/memberships",
        json={
            "sports_center_id": center_id,
            "membership_type_id": mtype_id,
            "display_name": "Ali Rezaei",
            "email": "ali@example.com",
            "mobile": "+989121111111",
            "status": "active",
        },
        headers=tenant_headers(TENANT_A),
    )
    assert membership.status_code == 201, membership.text
    membership_id = membership.json()["id"]

    coach = await client.post(
        "/api/v1/coaches",
        json={"sports_center_id": center_id, "code": "c1", "display_name": "Coach Sara"},
        headers=tenant_headers(TENANT_A),
    )
    assert coach.status_code == 201, coach.text

    facility = await client.post(
        "/api/v1/facilities",
        json={"sports_center_id": center_id, "code": "studio-1", "name": "Studio 1", "kind": "studio"},
        headers=tenant_headers(TENANT_A),
    )
    assert facility.status_code == 201, facility.text

    provider = await client.post(
        "/api/v1/device-providers",
        json={
            "code": "mock-qr",
            "name": "Mock QR",
            "capability": "qr",
            "adapter_key": "mock.qr",
        },
        headers=tenant_headers(TENANT_A),
    )
    assert provider.status_code == 201, provider.text
    provider_id = provider.json()["id"]

    device = await client.post(
        "/api/v1/devices",
        json={
            "sports_center_id": center_id,
            "code": "gate-1",
            "name": "Gate 1",
            "capability": "qr",
            "device_provider_id": provider_id,
        },
        headers=tenant_headers(TENANT_A),
    )
    assert device.status_code == 201, device.text
    device_id = device.json()["id"]

    connected = await client.post(
        f"/api/v1/devices/{device_id}/connect",
        headers=tenant_headers(TENANT_A),
    )
    assert connected.status_code == 200, connected.text
    assert connected.json()["status"] == "connected"

    lr = await client.post(
        "/api/v1/locker-rooms",
        json={"sports_center_id": center_id, "code": "lr1", "name": "Locker Room 1"},
        headers=tenant_headers(TENANT_A),
    )
    assert lr.status_code == 201, lr.text
    lr_id = lr.json()["id"]

    locker = await client.post(
        "/api/v1/lockers",
        json={"sports_center_id": center_id, "locker_room_id": lr_id, "code": "L01"},
        headers=tenant_headers(TENANT_A),
    )
    assert locker.status_code == 201, locker.text
    locker_id = locker.json()["id"]

    assigned = await client.post(
        f"/api/v1/lockers/{locker_id}/assign",
        json={"membership_id": membership_id},
        headers=tenant_headers(TENANT_A),
    )
    assert assigned.status_code == 200, assigned.text
    assert assigned.json()["status"] == "assigned"

    gateway = await client.post(
        "/api/v1/attendance-gateways",
        json={
            "sports_center_id": center_id,
            "code": "ag1",
            "name": "Main Gate",
            "primary_provider_id": provider_id,
        },
        headers=tenant_headers(TENANT_A),
    )
    assert gateway.status_code == 201, gateway.text
    gateway_id = gateway.json()["id"]

    provider2 = await client.post(
        "/api/v1/device-providers",
        json={
            "code": "mock-rfid",
            "name": "Mock RFID",
            "capability": "rfid",
            "adapter_key": "mock.rfid",
        },
        headers=tenant_headers(TENANT_A),
    )
    provider2_id = provider2.json()["id"]

    changed = await client.patch(
        f"/api/v1/attendance-gateways/{gateway_id}",
        json={"primary_provider_id": provider2_id},
        headers=tenant_headers(TENANT_A),
    )
    assert changed.status_code == 200, changed.text

    events = {e.event_type for e in get_event_publisher().published}
    assert SportsCenterEventType.MEMBER_CREATED.value in events
    assert SportsCenterEventType.MEMBERSHIP_CREATED.value in events
    assert SportsCenterEventType.COACH_CREATED.value in events
    assert SportsCenterEventType.FACILITY_CREATED.value in events
    assert SportsCenterEventType.DEVICE_CONNECTED.value in events
    assert SportsCenterEventType.LOCKER_ASSIGNED.value in events
    assert SportsCenterEventType.ATTENDANCE_PROVIDER_CHANGED.value in events


@pytest.mark.asyncio
async def test_tenant_isolation(client):
    center = await client.post(
        "/api/v1/sports-centers",
        json={"code": "iso", "name": "Iso Center"},
        headers=tenant_headers(TENANT_A),
    )
    center_id = center.json()["id"]

    missing = await client.get(
        f"/api/v1/sports-centers/{center_id}",
        headers=tenant_headers(TENANT_B),
    )
    assert missing.status_code == 404

    no_tenant = await client.get("/api/v1/sports-centers")
    assert no_tenant.status_code in (400, 422)
