import uuid
from datetime import date, time
from typing import Any

from sqlalchemy import Column, ForeignKey, String
from sqlalchemy.dialects.postgresql import JSONB
from sqlmodel import Field, SQLModel

from app.db.base import TenantModel


class ServiceBlockBase(SQLModel):
    day_of_week: int = Field(ge=0, le=6, nullable=False)
    name: str = Field(nullable=False)
    block_type: str = Field(nullable=False)  # "open" | "closed"
    start_time: time = Field(nullable=False)
    end_time: time = Field(nullable=False)
    max_covers: int | None = Field(default=None, nullable=True)
    default_duration_minutes: int | None = Field(default=None, nullable=True)
    is_active: bool = Field(default=True, nullable=False)
    display_order: int = Field(default=0, nullable=False)
    slot_interval_minutes: int = Field(default=30, ge=15, nullable=False)


class ServiceBlock(ServiceBlockBase, TenantModel, table=True):
    __tablename__ = "service_block"  # pyright: ignore[reportAssignmentType]

    id: str = Field(
        default_factory=lambda: str(uuid.uuid4()),
        primary_key=True,
    )


class ServiceBlockOverrideBase(SQLModel):
    start_date: date = Field(nullable=False)
    end_date: date = Field(nullable=False)
    name: str = Field(nullable=False)
    blocks: list[dict[str, Any]] | None = Field(
        default=None,
        sa_column=Column(JSONB),
    )
    is_active: bool = Field(default=True, nullable=False)


class ServiceBlockOverride(ServiceBlockOverrideBase, TenantModel, table=True):
    __tablename__ = "service_block_override"  # pyright: ignore[reportAssignmentType]

    id: str = Field(
        default_factory=lambda: str(uuid.uuid4()),
        primary_key=True,
    )


class ServiceBlockZone(SQLModel, table=True):
    """Join table linking ServiceBlock to Zone (open zones per block)."""

    __tablename__ = "service_block_zones"  # pyright: ignore[reportAssignmentType]

    service_block_id: str = Field(
        sa_column=Column(
            String,
            ForeignKey("service_block.id", ondelete="CASCADE"),
            primary_key=True,
            nullable=False,
        )
    )
    zone_id: str = Field(
        sa_column=Column(
            String,
            ForeignKey("zone.id", ondelete="CASCADE"),
            primary_key=True,
            nullable=False,
        )
    )

    restaurant_id: str = Field(foreign_key="restaurant.id", index=True, nullable=False)
