"""
Modelli Fascicolo e FascicoloMessage — fascicolazione pratiche.
"""

import uuid
from datetime import datetime

from sqlalchemy import DateTime, Enum, ForeignKey, Index, String, Text, func
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.database import Base

FascicoloStato = Enum(
    "aperto", "chiuso", "archiviato",
    name="fascicolo_stato",
    create_type=False,
)


class Fascicolo(Base):
    __tablename__ = "fascicoli"

    id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
    )
    tenant_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True), ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False
    )
    titolo: Mapped[str] = mapped_column(String(255), nullable=False)
    numero_pratica: Mapped[str | None] = mapped_column(String(100), nullable=True)
    stato: Mapped[str] = mapped_column(FascicoloStato, nullable=False, default="aperto")
    categoria: Mapped[str | None] = mapped_column(String(100), nullable=True)
    responsabile_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"), nullable=True
    )
    scadenza: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    note: Mapped[str | None] = mapped_column(Text, nullable=True)
    created_by: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"), nullable=True
    )
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False, server_default=func.now()
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False, server_default=func.now(), onupdate=func.now()
    )

    # Relazioni
    fascicolo_messages: Mapped[list["FascicoloMessage"]] = relationship(
        "FascicoloMessage", back_populates="fascicolo", cascade="all, delete-orphan"
    )
    messages: Mapped[list] = relationship(
        "Message",
        secondary="fascicolo_messages",
        lazy="select",
        viewonly=True,
    )

    __table_args__ = (
        Index("idx_fascicoli_tenant", "tenant_id"),
        Index("idx_fascicoli_stato", "stato"),
        Index("idx_fascicoli_responsabile", "responsabile_id"),
    )

    def __repr__(self) -> str:
        return f"<Fascicolo {self.id} {self.titolo!r} {self.stato!r}>"


class FascicoloMessage(Base):
    __tablename__ = "fascicolo_messages"

    fascicolo_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("fascicoli.id", ondelete="CASCADE"),
        primary_key=True,
    )
    message_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("messages.id", ondelete="CASCADE"),
        primary_key=True,
    )
    added_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False, server_default=func.now()
    )
    added_by: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"), nullable=True
    )

    # Relazioni
    fascicolo: Mapped["Fascicolo"] = relationship("Fascicolo", back_populates="fascicolo_messages")

    __table_args__ = (
        Index("idx_fascicolo_messages_fascicolo", "fascicolo_id"),
        Index("idx_fascicolo_messages_message", "message_id"),
    )
