-- 040_streaming_core.sql
-- Core Streaming Entities: Tracks, Playlists (Aligned with ORIGIN)

-- === TRACKS ===
CREATE TABLE public.tracks (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    creator_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
    file_id UUID REFERENCES public.files(id) ON DELETE RESTRICT, -- NULL temporairement avant création fichier
    
    -- Track Info
    title VARCHAR(255) NOT NULL,
    description TEXT,
    artist VARCHAR(255),
    album VARCHAR(255),
    genre VARCHAR(100),
    year INTEGER DEFAULT 0, -- Release year (for Go model compatibility)
    
    -- Audio Properties
    duration INTEGER NOT NULL, -- seconds
    bpm INTEGER,
    musical_key VARCHAR(10),
    
    -- Visibility
    visibility public.visibility NOT NULL DEFAULT 'public',
    is_downloadable BOOLEAN NOT NULL DEFAULT false,
    
    -- Media
    cover_art_file_id UUID REFERENCES public.files(id) ON DELETE SET NULL,
    waveform_data JSONB,
    
    -- Counts (denormalized)
    play_count INTEGER NOT NULL DEFAULT 0,
    like_count INTEGER NOT NULL DEFAULT 0,
    comment_count INTEGER NOT NULL DEFAULT 0,
    download_count INTEGER NOT NULL DEFAULT 0,
    
    -- Legacy/Go Compatibility fields (Denormalized or Mapped)
    user_id UUID, -- Maps to creator_id
    file_path VARCHAR(500), -- Maps to files.url or storage_path
    file_size BIGINT, -- Maps to files.file_size
    format VARCHAR(10),
    bitrate INTEGER,
    sample_rate INTEGER,
    waveform_path VARCHAR(500), -- Legacy
    cover_art_path VARCHAR(500), -- Legacy
    status VARCHAR(20) DEFAULT 'uploading', -- Legacy status
    status_message TEXT,
    stream_status VARCHAR(20) DEFAULT 'pending', -- Legacy stream status (pending, processing, ready, error)
    stream_manifest_url VARCHAR(500), -- Legacy stream manifest URL
    is_public BOOLEAN DEFAULT true, -- Maps to visibility='public'
    
    -- Timestamps
    published_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    deleted_at TIMESTAMPTZ,

    CONSTRAINT chk_tracks_duration_positive CHECK (duration >= 0) -- Permet 0 temporairement avant extraction métadonnées
);

-- Indexes
CREATE INDEX idx_tracks_creator_id ON public.tracks(creator_id);
CREATE INDEX idx_tracks_genre ON public.tracks(genre);
CREATE INDEX idx_tracks_visibility ON public.tracks(visibility);
CREATE INDEX idx_tracks_published_at_desc ON public.tracks(published_at DESC) WHERE published_at IS NOT NULL;
CREATE INDEX idx_tracks_play_count_desc ON public.tracks(play_count DESC);
CREATE INDEX idx_tracks_created_at_desc ON public.tracks(created_at DESC);
CREATE INDEX idx_tracks_search_gin ON public.tracks USING GIN(to_tsvector('english', title || ' ' || COALESCE(artist, '') || ' ' || COALESCE(album, '')));

-- === TRACK VERSIONS (Legacy/Go Support) ===
-- Origin doesn't strictly specify this, but code implies it. Keeping minimal.
CREATE TABLE public.track_versions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    track_id UUID NOT NULL REFERENCES public.tracks(id) ON DELETE CASCADE,
    
    version_number INTEGER NOT NULL,
    file_path VARCHAR(500) NOT NULL,
    file_size BIGINT NOT NULL,
    changelog TEXT,
    
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    deleted_at TIMESTAMPTZ
);

CREATE INDEX idx_track_versions_track_id ON public.track_versions(track_id);
CREATE INDEX idx_track_versions_created_at ON public.track_versions(created_at DESC);

-- === PLAYLISTS ===
CREATE TABLE public.playlists (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
    
    -- Playlist Info
    name VARCHAR(255) NOT NULL,
    description TEXT,
    
    -- Media
    cover_url TEXT,
    
    -- Properties
    visibility public.visibility NOT NULL DEFAULT 'public',
    is_collaborative BOOLEAN NOT NULL DEFAULT false,
    
    -- Counts
    track_count INTEGER NOT NULL DEFAULT 0,
    duration_seconds INTEGER NOT NULL DEFAULT 0,
    follower_count INTEGER NOT NULL DEFAULT 0,
    
    -- Legacy
    title VARCHAR(200), -- Maps to name
    is_public BOOLEAN DEFAULT true, -- Maps to visibility
    
    -- Timestamps
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    deleted_at TIMESTAMPTZ
);

-- Indexes
CREATE INDEX idx_playlists_user_id ON public.playlists(user_id);
CREATE INDEX idx_playlists_visibility ON public.playlists(visibility);
CREATE INDEX idx_playlists_created_at_desc ON public.playlists(created_at DESC);

-- === PLAYLIST TRACKS (Junction) ===
CREATE TABLE public.playlist_tracks (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    playlist_id UUID NOT NULL REFERENCES public.playlists(id) ON DELETE CASCADE,
    track_id UUID NOT NULL REFERENCES public.tracks(id) ON DELETE CASCADE,
    
    -- Order
    position INTEGER NOT NULL,
    
    -- Metadata
    added_by UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
    added_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    CONSTRAINT uq_playlist_tracks_playlist_track UNIQUE (playlist_id, track_id)
);

CREATE INDEX idx_playlist_tracks_playlist_id_position ON public.playlist_tracks(playlist_id, position);
CREATE INDEX idx_playlist_tracks_track_id ON public.playlist_tracks(track_id);
CREATE INDEX idx_playlist_tracks_added_by ON public.playlist_tracks(added_by);

-- === PLAYLIST COLLABORATORS (Legacy/Lab) ===
CREATE TABLE public.playlist_collaborators (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    playlist_id UUID NOT NULL REFERENCES public.playlists(id) ON DELETE CASCADE,
    user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
    
    permission public.playlist_permission NOT NULL DEFAULT 'read',
    
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    deleted_at TIMESTAMPTZ
);

CREATE INDEX idx_playlist_collaborators_playlist_id ON public.playlist_collaborators(playlist_id);
CREATE INDEX idx_playlist_collaborators_user_id ON public.playlist_collaborators(user_id);

-- === PLAYLIST FOLLOWS (Legacy/Lab - likely covered by 'follows' or custom logic) ===
CREATE TABLE public.playlist_follows (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    playlist_id UUID NOT NULL REFERENCES public.playlists(id) ON DELETE CASCADE,
    user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
    
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    deleted_at TIMESTAMPTZ
);

CREATE INDEX idx_playlist_follows_playlist_id ON public.playlist_follows(playlist_id);
CREATE INDEX idx_playlist_follows_user_id ON public.playlist_follows(user_id);

-- === QUEUES ===
CREATE TABLE public.queues (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE UNIQUE,
    
    -- Current Track
    current_track_id UUID REFERENCES public.tracks(id) ON DELETE SET NULL,
    current_position INTEGER NOT NULL DEFAULT 0,
    
    -- Playback State
    is_playing BOOLEAN NOT NULL DEFAULT false,
    shuffle BOOLEAN NOT NULL DEFAULT false,
    repeat_mode VARCHAR(20) NOT NULL DEFAULT 'off',
    volume INTEGER NOT NULL DEFAULT 100,
    
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE UNIQUE INDEX idx_queues_user_id ON public.queues(user_id);

-- === QUEUE ITEMS ===
CREATE TABLE public.queue_items (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    queue_id UUID NOT NULL REFERENCES public.queues(id) ON DELETE CASCADE,
    track_id UUID NOT NULL REFERENCES public.tracks(id) ON DELETE CASCADE,
    
    position INTEGER NOT NULL,
    added_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_queue_items_queue_id_position ON public.queue_items(queue_id, position);