"""Perfil de músico: lo que se muestra y se busca geográficamente."""
from datetime import datetime, timezone

from geoalchemy2 import Geography
from sqlalchemy import Boolean, DateTime, Float, ForeignKey, Integer, String, Text
from sqlalchemy.dialects.postgresql import ARRAY
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.core.database import Base


def _now() -> datetime:
    return datetime.now(timezone.utc)


class MusicianProfile(Base):
    __tablename__ = "musician_profiles"

    id: Mapped[int] = mapped_column(primary_key=True)
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"), unique=True)

    stage_name: Mapped[str] = mapped_column(String(120), nullable=False)
    bio: Mapped[str | None] = mapped_column(Text)
    # Descripción del espectáculo que ofrece (el bloque "Nuestro espectáculo" del perfil)
    show_description: Mapped[str | None] = mapped_column(Text)
    years_experience: Mapped[int | None] = mapped_column(Integer)
    photo_url: Mapped[str | None] = mapped_column(String(500))  # avatar

    # Servicios que ofrece (slugs del catálogo), p.ej. ["mariachi", "solista"]
    service_types: Mapped[list[str]] = mapped_column(ARRAY(String), default=list)
    genres: Mapped[list[str]] = mapped_column(ARRAY(String), default=list)

    # Precio de referencia por presentación
    base_price: Mapped[float] = mapped_column(Float, default=0)
    currency: Mapped[str] = mapped_column(String(3), default="USD")

    rating: Mapped[float] = mapped_column(Float, default=0)
    reviews_count: Mapped[int] = mapped_column(Integer, default=0)

    # Estado en vivo
    is_available: Mapped[bool] = mapped_column(Boolean, default=False, index=True)
    # Hasta qué distancia está dispuesto a viajar (km)
    travel_radius_km: Mapped[int] = mapped_column(Integer, default=20)

    # Ubicación actual — PostGIS geography (lon/lat, SRID 4326). Se consulta con ST_DWithin.
    location: Mapped[object | None] = mapped_column(Geography(geometry_type="POINT", srid=4326))
    city: Mapped[str | None] = mapped_column(String(120))
    country: Mapped[str] = mapped_column(String(2), default="VE", index=True)  # ISO-2

    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), default=_now, onupdate=_now
    )

    user: Mapped["User"] = relationship(back_populates="musician_profile")  # noqa: F821
    # Galería tipo Instagram (fotos subidas + videos por link), ordenada por `position`
    media: Mapped[list["MediaItem"]] = relationship(
        back_populates="musician",
        cascade="all, delete-orphan",
        order_by="MediaItem.position",
    )


class MediaItem(Base):
    """Ítem del portfolio: una foto (subida a nuestro storage) o un video (link externo)."""
    __tablename__ = "media_items"

    id: Mapped[int] = mapped_column(primary_key=True)
    musician_id: Mapped[int] = mapped_column(
        ForeignKey("musician_profiles.id", ondelete="CASCADE"), index=True
    )

    kind: Mapped[str] = mapped_column(String(10), nullable=False)  # photo | video
    # foto: ruta en storage (ej. /media/...); video: URL del embed/plataforma
    url: Mapped[str] = mapped_column(String(600), nullable=False)
    # upload | youtube | instagram | tiktok | vimeo
    provider: Mapped[str] = mapped_column(String(20), default="upload")
    caption: Mapped[str | None] = mapped_column(String(200))
    position: Mapped[int] = mapped_column(Integer, default=0)
    is_featured: Mapped[bool] = mapped_column(Boolean, default=False)  # "Video destacado"

    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_now)

    musician: Mapped["MusicianProfile"] = relationship(back_populates="media")
