import uuid
from enum import StrEnum
from typing import Any

from pydantic import field_validator
from sqlalchemy import Column
from sqlalchemy.dialects.postgresql import JSONB
from sqlmodel import Field, SQLModel

from app.db.base import TenantModel


class OrderStatus(StrEnum):
    """Allowed order statuses for dashboard lifecycle."""

    PENDING = "pending"
    PREPARING = "preparing"
    READY = "ready"
    COMPLETED = "completed"
    CANCELLED = "cancelled"


class OrderBase(SQLModel):
    status: str = Field(default="pending", index=True, nullable=False)
    total_cents: int = Field(default=0, nullable=False)
    mollie_payment_id: str | None = Field(default=None, index=True)


class Order(OrderBase, TenantModel, table=True):
    __tablename__ = "order"

    id: str = Field(
        default_factory=lambda: str(uuid.uuid4()),
        primary_key=True,
    )
    customer_id: str | None = Field(
        default=None,
        foreign_key="customer.id",
        index=True,
        nullable=True,
    )


class OrderItem(SQLModel, table=True):
    """Order line items — scoped to restaurant via order FK (not TenantModel directly)."""

    __tablename__ = "order_item"

    id: str = Field(
        default_factory=lambda: str(uuid.uuid4()),
        primary_key=True,
    )
    order_id: str = Field(foreign_key="order.id", nullable=False, index=True)
    menu_item_name: str = Field(nullable=False)
    quantity: int = Field(ge=1, nullable=False)
    unit_price_cents: int = Field(ge=1, nullable=False)
    options: dict[str, Any] | None = Field(
        default=None,
        sa_column=Column(JSONB),
    )
    restaurant_id: str = Field(foreign_key="restaurant.id", nullable=False, index=True)


class OrderItemCreate(SQLModel):
    menu_item_name: str
    quantity: int = Field(ge=1)
    unit_price_cents: int = Field(ge=1)
    options: dict[str, Any] | None = None


class OrderCreate(OrderBase):
    items: list[OrderItemCreate] = Field(default_factory=list)


class OrderRead(OrderBase):
    id: str
    restaurant_id: str
    customer_id: str | None = None


class OrderStatusUpdate(SQLModel):
    """Payload for PATCH /orders/{id}/status."""

    new_status: str

    @field_validator("new_status")
    @classmethod
    def validate_status(cls, v: str) -> str:
        allowed = {s.value for s in OrderStatus}
        if v not in allowed:
            raise ValueError(f"Invalid status {v!r}. Allowed: {', '.join(sorted(allowed))}")
        return v


class OrderStatusResponse(SQLModel):
    """Response for status mutation endpoints."""

    id: str
    status: str
    restaurant_id: str
