-- 050_data_validation_constraints.sql
-- Data Validation Constraints (BE-DB-011: Add database constraints for data validation)
-- Add CHECK constraints for status values, enum constraints
-- Note: PostgreSQL doesn't support IF NOT EXISTS with ADD CONSTRAINT, so we use DO blocks

-- === TRACKS STATUS CONSTRAINTS ===
-- Constraint for track status (uploading, processing, completed, failed)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'tracks' 
        AND constraint_name = 'chk_tracks_status_valid'
    ) THEN
        ALTER TABLE public.tracks 
        ADD CONSTRAINT chk_tracks_status_valid 
        CHECK (status IN ('uploading', 'processing', 'completed', 'failed'));
    END IF;
END $$;

-- Constraint for stream_status (pending, processing, ready, error)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'tracks' 
        AND constraint_name = 'chk_tracks_stream_status_valid'
    ) THEN
        ALTER TABLE public.tracks 
        ADD CONSTRAINT chk_tracks_stream_status_valid 
        CHECK (stream_status IN ('pending', 'processing', 'ready', 'error'));
    END IF;
END $$;

-- Constraint for counts (non-negative)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'tracks' 
        AND constraint_name = 'chk_tracks_counts_non_negative'
    ) THEN
        ALTER TABLE public.tracks 
        ADD CONSTRAINT chk_tracks_counts_non_negative 
        CHECK (play_count >= 0 AND like_count >= 0 AND comment_count >= 0 AND download_count >= 0);
    END IF;
END $$;

-- Constraint for year (reasonable range)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'tracks' 
        AND constraint_name = 'chk_tracks_year_valid'
    ) THEN
        ALTER TABLE public.tracks 
        ADD CONSTRAINT chk_tracks_year_valid 
        CHECK (year >= 0 AND year <= EXTRACT(YEAR FROM CURRENT_DATE) + 10);
    END IF;
END $$;

-- === PLAYLISTS CONSTRAINTS ===
-- Constraint for counts (non-negative)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'playlists' 
        AND constraint_name = 'chk_playlists_counts_non_negative'
    ) THEN
        ALTER TABLE public.playlists 
        ADD CONSTRAINT chk_playlists_counts_non_negative 
        CHECK (track_count >= 0 AND follower_count >= 0);
    END IF;
END $$;

-- === PLAYLIST_TRACKS CONSTRAINTS ===
-- Constraint for position (positive)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'playlist_tracks' 
        AND constraint_name = 'chk_playlist_tracks_position_positive'
    ) THEN
        ALTER TABLE public.playlist_tracks 
        ADD CONSTRAINT chk_playlist_tracks_position_positive 
        CHECK (position >= 0);
    END IF;
END $$;

-- === HLSTranscodeQueue CONSTRAINTS ===
-- Constraint for queue status (pending, processing, completed, failed)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'hls_transcode_queue' 
        AND constraint_name = 'chk_hls_transcode_queue_status_valid'
    ) THEN
        ALTER TABLE public.hls_transcode_queue 
        ADD CONSTRAINT chk_hls_transcode_queue_status_valid 
        CHECK (status IN ('pending', 'processing', 'completed', 'failed'));
    END IF;
END $$;

-- Constraint for retry counts (non-negative)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'hls_transcode_queue' 
        AND constraint_name = 'chk_hls_transcode_queue_retry_valid'
    ) THEN
        ALTER TABLE public.hls_transcode_queue 
        ADD CONSTRAINT chk_hls_transcode_queue_retry_valid 
        CHECK (retry_count >= 0 AND max_retries >= 0);
    END IF;
END $$;

-- Constraint for priority (reasonable range)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'hls_transcode_queue' 
        AND constraint_name = 'chk_hls_transcode_queue_priority_valid'
    ) THEN
        ALTER TABLE public.hls_transcode_queue 
        ADD CONSTRAINT chk_hls_transcode_queue_priority_valid 
        CHECK (priority >= 1 AND priority <= 10);
    END IF;
END $$;

-- === TRACK_COMMENTS CONSTRAINTS ===
-- Constraint for content length (already exists, but ensure it's there)
-- Note: chk_track_comments_content_length already exists in 041_streaming_analytics.sql

-- === TRACK_PLAYS CONSTRAINTS ===
-- Constraint for duration (non-negative)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'track_plays' 
        AND constraint_name = 'chk_track_plays_duration_non_negative'
    ) THEN
        ALTER TABLE public.track_plays 
        ADD CONSTRAINT chk_track_plays_duration_non_negative 
        CHECK (duration >= 0);
    END IF;
END $$;

-- === PLAYBACK_ANALYTICS CONSTRAINTS ===
-- Note: playback_analytics table may not exist yet (referenced in views but not created)
-- Constraint for completion_rate (0-100)
DO $$
BEGIN
    -- Check if table exists before adding constraints
    IF EXISTS (
        SELECT 1 FROM information_schema.tables 
        WHERE table_schema = 'public' 
        AND table_name = 'playback_analytics'
    ) AND NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'playback_analytics' 
        AND constraint_name = 'chk_playback_analytics_completion_rate'
    ) THEN
        ALTER TABLE public.playback_analytics 
        ADD CONSTRAINT chk_playback_analytics_completion_rate 
        CHECK (completion_rate >= 0 AND completion_rate <= 100);
    END IF;
END $$;

-- Constraint for counts (non-negative)
DO $$
BEGIN
    -- Check if table exists before adding constraints
    IF EXISTS (
        SELECT 1 FROM information_schema.tables 
        WHERE table_schema = 'public' 
        AND table_name = 'playback_analytics'
    ) AND NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'playback_analytics' 
        AND constraint_name = 'chk_playback_analytics_counts_non_negative'
    ) THEN
        ALTER TABLE public.playback_analytics 
        ADD CONSTRAINT chk_playback_analytics_counts_non_negative 
        CHECK (play_time >= 0 AND pause_count >= 0 AND seek_count >= 0);
    END IF;
END $$;

-- === PLAYLIST_VERSION CONSTRAINTS ===
-- Note: playlist_versions table may not exist yet
-- Constraint for version (positive)
DO $$
BEGIN
    -- Check if table exists before adding constraints
    IF EXISTS (
        SELECT 1 FROM information_schema.tables 
        WHERE table_schema = 'public' 
        AND table_name = 'playlist_versions'
    ) AND NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'playlist_versions' 
        AND constraint_name = 'chk_playlist_versions_version_positive'
    ) THEN
        ALTER TABLE public.playlist_versions 
        ADD CONSTRAINT chk_playlist_versions_version_positive 
        CHECK (version > 0);
    END IF;
END $$;

-- Constraint for action (created, updated, restored)
DO $$
BEGIN
    -- Check if table exists before adding constraints
    IF EXISTS (
        SELECT 1 FROM information_schema.tables 
        WHERE table_schema = 'public' 
        AND table_name = 'playlist_versions'
    ) AND NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'playlist_versions' 
        AND constraint_name = 'chk_playlist_versions_action_valid'
    ) THEN
        ALTER TABLE public.playlist_versions 
        ADD CONSTRAINT chk_playlist_versions_action_valid 
        CHECK (action IN ('created', 'updated', 'restored'));
    END IF;
END $$;

-- === TRACK_HISTORY CONSTRAINTS ===
-- Constraint for action (created, updated, deleted, published, unpublished, restored)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'track_history' 
        AND constraint_name = 'chk_track_history_action_valid'
    ) THEN
        ALTER TABLE public.track_history 
        ADD CONSTRAINT chk_track_history_action_valid 
        CHECK (action IN ('created', 'updated', 'deleted', 'published', 'unpublished', 'restored'));
    END IF;
END $$;

-- === BITRATE_ADAPTATION CONSTRAINTS ===
-- Constraint for reason (network_slow, network_fast, user_selected, buffer_low)
DO $$
BEGIN
    -- Check if table exists before adding constraints
    IF EXISTS (
        SELECT 1 FROM information_schema.tables 
        WHERE table_schema = 'public' 
        AND table_name = 'bitrate_adaptation_logs'
    ) AND NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'bitrate_adaptation_logs' 
        AND constraint_name = 'chk_bitrate_adaptation_reason_valid'
    ) THEN
        ALTER TABLE public.bitrate_adaptation_logs 
        ADD CONSTRAINT chk_bitrate_adaptation_reason_valid 
        CHECK (reason IN ('network_slow', 'network_fast', 'user_selected', 'buffer_low'));
    END IF;
END $$;

-- Constraint for bitrates (positive)
DO $$
BEGIN
    -- Check if table exists before adding constraints
    IF EXISTS (
        SELECT 1 FROM information_schema.tables 
        WHERE table_schema = 'public' 
        AND table_name = 'bitrate_adaptation_logs'
    ) AND NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'bitrate_adaptation_logs' 
        AND constraint_name = 'chk_bitrate_adaptation_bitrates_positive'
    ) THEN
        ALTER TABLE public.bitrate_adaptation_logs 
        ADD CONSTRAINT chk_bitrate_adaptation_bitrates_positive 
        CHECK (old_bitrate > 0 AND new_bitrate > 0);
    END IF;
END $$;

-- === NOTIFICATIONS CONSTRAINTS ===
-- Constraint for type (reasonable length)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'notifications' 
        AND constraint_name = 'chk_notifications_type_length'
    ) THEN
        ALTER TABLE public.notifications 
        ADD CONSTRAINT chk_notifications_type_length 
        CHECK (LENGTH(type) >= 1 AND LENGTH(type) <= 50);
    END IF;
END $$;

-- Constraint for title (reasonable length)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'notifications' 
        AND constraint_name = 'chk_notifications_title_length'
    ) THEN
        ALTER TABLE public.notifications 
        ADD CONSTRAINT chk_notifications_title_length 
        CHECK (LENGTH(title) >= 1 AND LENGTH(title) <= 255);
    END IF;
END $$;

-- === USER_PROFILES CONSTRAINTS ===
-- Constraint for counts (non-negative)
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'user_profiles' 
        AND constraint_name = 'chk_user_profiles_counts_non_negative'
    ) THEN
        ALTER TABLE public.user_profiles 
        ADD CONSTRAINT chk_user_profiles_counts_non_negative 
        CHECK (follower_count >= 0 AND following_count >= 0 AND track_count >= 0 AND playlist_count >= 0);
    END IF;
END $$;

-- Comments (only add comments if constraints exist)
DO $$
BEGIN
    IF EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'tracks' 
        AND constraint_name = 'chk_tracks_status_valid'
    ) THEN
        COMMENT ON CONSTRAINT chk_tracks_status_valid ON public.tracks IS 'Validates track status values';
    END IF;
    
    IF EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'tracks' 
        AND constraint_name = 'chk_tracks_stream_status_valid'
    ) THEN
        COMMENT ON CONSTRAINT chk_tracks_stream_status_valid ON public.tracks IS 'Validates stream status values';
    END IF;
    
    IF EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'hls_transcode_queue' 
        AND constraint_name = 'chk_hls_transcode_queue_status_valid'
    ) THEN
        COMMENT ON CONSTRAINT chk_hls_transcode_queue_status_valid ON public.hls_transcode_queue IS 'Validates queue status values';
    END IF;
    
    IF EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'playlist_versions' 
        AND constraint_name = 'chk_playlist_versions_action_valid'
    ) THEN
        COMMENT ON CONSTRAINT chk_playlist_versions_action_valid ON public.playlist_versions IS 'Validates playlist version action values';
    END IF;
    
    IF EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'track_history' 
        AND constraint_name = 'chk_track_history_action_valid'
    ) THEN
        COMMENT ON CONSTRAINT chk_track_history_action_valid ON public.track_history IS 'Validates track history action values';
    END IF;
    
    IF EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_schema = 'public' 
        AND table_name = 'bitrate_adaptation_logs' 
        AND constraint_name = 'chk_bitrate_adaptation_reason_valid'
    ) THEN
        COMMENT ON CONSTRAINT chk_bitrate_adaptation_reason_valid ON public.bitrate_adaptation_logs IS 'Validates bitrate adaptation reason values';
    END IF;
END $$;
