"""SQLAlchemy database models."""
from datetime import datetime
from typing import Optional, List
from uuid import uuid4

from sqlalchemy import Column, String, Float, Integer, Boolean, DateTime, JSON, ARRAY, BigInteger, Index, text
from sqlalchemy.dialects.postgresql import UUID
from pgvector.sqlalchemy import Vector

from .database import Base


class AudioTrack(Base):
    """Audio track model with extracted features and classifications."""

    __tablename__ = "audio_tracks"

    # Primary key
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid4, server_default=text("gen_random_uuid()"))

    # File information
    filepath = Column(String, unique=True, nullable=False, index=True)  # Original file (for download)
    stream_filepath = Column(String, nullable=True, index=True)  # MP3 128kbps (for streaming preview)
    waveform_filepath = Column(String, nullable=True)  # Pre-computed waveform JSON
    filename = Column(String, nullable=False)
    duration_seconds = Column(Float, nullable=True)
    file_size_bytes = Column(BigInteger, nullable=True)
    format = Column(String, nullable=True)  # mp3, wav, flac, etc.
    analyzed_at = Column(DateTime, default=datetime.utcnow, nullable=False)

    # Musical features (extracted via librosa)
    tempo_bpm = Column(Float, nullable=True, index=True)
    key = Column(String, nullable=True)  # e.g., "C major", "D# minor"
    time_signature = Column(String, nullable=True)  # e.g., "4/4", "3/4"
    energy = Column(Float, nullable=True)  # 0-1
    danceability = Column(Float, nullable=True)  # 0-1
    valence = Column(Float, nullable=True)  # 0-1 (positivity)
    loudness_lufs = Column(Float, nullable=True)  # LUFS
    spectral_centroid = Column(Float, nullable=True)  # Hz
    zero_crossing_rate = Column(Float, nullable=True)  # 0-1

    # Genre classification (via Essentia)
    genre_primary = Column(String, nullable=True, index=True)
    genre_secondary = Column(ARRAY(String), nullable=True)
    genre_confidence = Column(Float, nullable=True)  # 0-1

    # Mood classification (via Essentia)
    mood_primary = Column(String, nullable=True, index=True)
    mood_secondary = Column(ARRAY(String), nullable=True)
    mood_arousal = Column(Float, nullable=True)  # 0-1
    mood_valence = Column(Float, nullable=True)  # 0-1

    # Instrument detection (via Essentia)
    instruments = Column(ARRAY(String), nullable=True)  # List of detected instruments

    # Vocal detection (future feature)
    has_vocals = Column(Boolean, nullable=True)
    vocal_gender = Column(String, nullable=True)  # male, female, mixed, null

    # Embeddings (optional - for CLAP/semantic search)
    embedding = Column(Vector(512), nullable=True)  # 512D vector for CLAP
    embedding_model = Column(String, nullable=True)  # Model name used

    # Additional metadata (JSON for flexibility)
    extra_metadata = Column(JSON, nullable=True)

    # Indexes
    __table_args__ = (
        Index("idx_genre_primary", "genre_primary"),
        Index("idx_mood_primary", "mood_primary"),
        Index("idx_tempo_bpm", "tempo_bpm"),
        Index("idx_filepath", "filepath"),
        # Vector index for similarity search (created via migration)
        # Index("idx_embedding", "embedding", postgresql_using="ivfflat", postgresql_ops={"embedding": "vector_cosine_ops"}),
    )

    def __repr__(self) -> str:
        return f"<AudioTrack(id={self.id}, filename={self.filename}, genre={self.genre_primary})>"

    def to_dict(self) -> dict:
        """Convert model to dictionary.

        Returns:
            Dictionary representation of the track
        """
        return {
            "id": str(self.id),
            "filepath": self.filepath,
            "stream_filepath": self.stream_filepath,
            "waveform_filepath": self.waveform_filepath,
            "filename": self.filename,
            "duration_seconds": self.duration_seconds,
            "file_size_bytes": self.file_size_bytes,
            "format": self.format,
            "analyzed_at": self.analyzed_at.isoformat() if self.analyzed_at else None,
            "features": {
                "tempo_bpm": self.tempo_bpm,
                "key": self.key,
                "time_signature": self.time_signature,
                "energy": self.energy,
                "danceability": self.danceability,
                "valence": self.valence,
                "loudness_lufs": self.loudness_lufs,
                "spectral_centroid": self.spectral_centroid,
                "zero_crossing_rate": self.zero_crossing_rate,
            },
            "classification": {
                "genre": {
                    "primary": self.genre_primary,
                    "secondary": self.genre_secondary or [],
                    "confidence": self.genre_confidence,
                },
                "mood": {
                    "primary": self.mood_primary,
                    "secondary": self.mood_secondary or [],
                    "arousal": self.mood_arousal,
                    "valence": self.mood_valence,
                },
                "instruments": self.instruments or [],
                "vocals": {
                    "present": self.has_vocals,
                    "gender": self.vocal_gender,
                },
            },
            "embedding": {
                "model": self.embedding_model,
                "dimension": 512 if self.embedding else None,
                # Don't include actual vector in API responses (too large)
            },
            "metadata": self.extra_metadata or {},
        }
