"""Phase 12.4 POS Lite API / tenant / validation tests."""
from __future__ import annotations

import pytest

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


async def _seed_venue_item(client, tenant_id, *, venue_code: str = "v1", item_code: str = "item1"):
    h = tenant_headers(tenant_id)
    venue = await client.post(
        "/api/v1/venues",
        json={"code": venue_code, "name": "Cafe", "status": "active", "venue_format": "cafe"},
        headers=h,
    )
    assert venue.status_code == 201, venue.text
    venue_id = venue.json()["id"]

    menu = await client.post(
        "/api/v1/menus",
        json={"venue_id": venue_id, "code": f"{item_code}-menu", "name": "Menu"},
        headers=h,
    )
    assert menu.status_code == 201, menu.text
    menu_id = menu.json()["id"]

    item = await client.post(
        "/api/v1/menu-items",
        json={
            "venue_id": venue_id,
            "menu_id": menu_id,
            "code": item_code,
            "name": "Espresso",
            "base_price": 90000,
        },
        headers=h,
    )
    assert item.status_code == 201, item.text
    return {"headers": h, "venue_id": venue_id, "menu_id": menu_id, "item_id": item.json()["id"]}


@pytest.mark.asyncio
async def test_pos_lite_happy_path_register_shift_ticket_line_void(client):
    seed = await _seed_venue_item(client, TENANT_A, venue_code="pos-v1", item_code="pos-i1")
    h = seed["headers"]

    register = await client.post(
        "/api/v1/pos-registers",
        json={"venue_id": seed["venue_id"], "code": "reg-1", "name": "Register 1"},
        headers=h,
    )
    assert register.status_code == 201, register.text
    register_id = register.json()["id"]
    assert register.json()["status"] == "active"

    shift = await client.post(
        "/api/v1/pos-shifts",
        json={"venue_id": seed["venue_id"], "register_id": register_id, "opened_by": "cashier1"},
        headers=h,
    )
    assert shift.status_code == 201, shift.text
    shift_id = shift.json()["id"]
    assert shift.json()["status"] == "open"

    duplicate_shift = await client.post(
        "/api/v1/pos-shifts",
        json={"venue_id": seed["venue_id"], "register_id": register_id},
        headers=h,
    )
    assert duplicate_shift.status_code == 409

    ticket = await client.post(
        "/api/v1/pos-tickets",
        json={
            "venue_id": seed["venue_id"],
            "register_id": register_id,
            "shift_id": shift_id,
            "code": "t-1",
        },
        headers=h,
    )
    assert ticket.status_code == 201, ticket.text
    ticket_id = ticket.json()["id"]
    assert ticket.json()["status"] == "open"

    line = await client.post(
        "/api/v1/pos-ticket-lines",
        json={
            "venue_id": seed["venue_id"],
            "ticket_id": ticket_id,
            "menu_item_id": seed["item_id"],
            "quantity": 2,
        },
        headers=h,
    )
    assert line.status_code == 201, line.text
    assert line.json()["unit_price"] == 90000
    assert line.json()["quantity"] == 2

    voided = await client.post(f"/api/v1/pos-tickets/{ticket_id}/void", headers=h)
    assert voided.status_code == 200, voided.text
    assert voided.json()["status"] == "void"

    blocked = await client.post(f"/api/v1/pos-tickets/{ticket_id}/void", headers=h)
    assert blocked.status_code == 409

    closed = await client.post(f"/api/v1/pos-shifts/{shift_id}/close", headers=h)
    assert closed.status_code == 200, closed.text
    assert closed.json()["status"] == "closed"

    published = {e.event_type for e in get_event_publisher().published}
    assert HospitalityEventType.POS_REGISTER_CREATED.value in published
    assert HospitalityEventType.POS_SHIFT_OPENED.value in published
    assert HospitalityEventType.POS_SHIFT_CLOSED.value in published
    assert HospitalityEventType.POS_TICKET_CREATED.value in published
    assert HospitalityEventType.POS_TICKET_VOIDED.value in published
    assert HospitalityEventType.POS_TICKET_LINE_ADDED.value in published


@pytest.mark.asyncio
async def test_pos_lite_tenant_isolation(client):
    seed = await _seed_venue_item(client, TENANT_A, venue_code="pos-iso-v1", item_code="pos-iso-i1")
    register = await client.post(
        "/api/v1/pos-registers",
        json={"venue_id": seed["venue_id"], "code": "iso-reg", "name": "Iso Register"},
        headers=seed["headers"],
    )
    assert register.status_code == 201, register.text
    register_id = register.json()["id"]

    denied = await client.get(
        f"/api/v1/pos-registers/{register_id}", headers=tenant_headers(TENANT_B)
    )
    assert denied.status_code == 404


@pytest.mark.asyncio
async def test_pos_ticket_line_quantity_validation(client):
    seed = await _seed_venue_item(client, TENANT_A, venue_code="pos-qty-v1", item_code="pos-qty-i1")
    h = seed["headers"]

    register = await client.post(
        "/api/v1/pos-registers",
        json={"venue_id": seed["venue_id"], "code": "qty-reg", "name": "Qty Register"},
        headers=h,
    )
    assert register.status_code == 201, register.text
    register_id = register.json()["id"]

    ticket = await client.post(
        "/api/v1/pos-tickets",
        json={"venue_id": seed["venue_id"], "register_id": register_id, "code": "qty-t1"},
        headers=h,
    )
    assert ticket.status_code == 201, ticket.text
    ticket_id = ticket.json()["id"]

    bad = await client.post(
        "/api/v1/pos-ticket-lines",
        json={
            "venue_id": seed["venue_id"],
            "ticket_id": ticket_id,
            "menu_item_id": seed["item_id"],
            "quantity": 0,
        },
        headers=h,
    )
    assert bad.status_code == 422


@pytest.mark.asyncio
async def test_capabilities_phase_12_4(client):
    resp = await client.get("/capabilities")
    assert resp.status_code == 200
    body = resp.json()
    assert body["features"]["pos_lite"] is True
    assert body["features"]["pos_engine"] is False
