-- Migration: Convertir users.id de BIGINT vers UUID
-- CRITIQUE: Cette migration doit être exécutée AVANT tout déploiement utilisant les nouveaux modèles UUID
-- Date: 2024-11-27
-- Impact: BREAKING CHANGE - Toutes les FK doivent être migrées

-- =====================================================
-- ÉTAPE 1: Créer une colonne temporaire UUID
-- =====================================================

-- Activer l'extension UUID si pas déjà fait
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgcrypto"; -- Pour gen_random_uuid()

-- Ajouter une colonne temporaire pour stocker les nouveaux UUIDs
ALTER TABLE users ADD COLUMN IF NOT EXISTS id_uuid UUID;

-- Générer un UUID pour chaque utilisateur existant (mapping déterministe depuis l'ID)
-- Note: On utilise uuid_generate_v5 pour créer un UUID déterministe basé sur l'ID existant
UPDATE users 
SET id_uuid = uuid_generate_v5(
    '6ba7b810-9dad-11d1-80b4-00c04fd430c8'::uuid, -- Namespace UUID arbitraire mais fixe
    id::text
)
WHERE id_uuid IS NULL;

-- =====================================================
-- ÉTAPE 2: Migrer les tables dépendantes (FK)
-- =====================================================

-- Pour chaque table avec user_id en BIGINT, créer une colonne temporaire UUID

-- user_roles
ALTER TABLE user_roles ADD COLUMN IF NOT EXISTS user_id_uuid UUID;
UPDATE user_roles ur 
SET user_id_uuid = u.id_uuid 
FROM users u 
WHERE ur.user_id = u.id AND ur.user_id_uuid IS NULL;

-- tracks
ALTER TABLE tracks ADD COLUMN IF NOT EXISTS user_id_uuid UUID;
UPDATE tracks t 
SET user_id_uuid = u.id_uuid 
FROM users u 
WHERE t.user_id = u.id AND t.user_id_uuid IS NULL;

-- playlists
ALTER TABLE playlists ADD COLUMN IF NOT EXISTS user_id_uuid UUID;
UPDATE playlists p 
SET user_id_uuid = u.id_uuid 
FROM users u 
WHERE p.user_id = u.id AND p.user_id_uuid IS NULL;

-- refresh_tokens
ALTER TABLE refresh_tokens ADD COLUMN IF NOT EXISTS user_id_uuid UUID;
UPDATE refresh_tokens rt 
SET user_id_uuid = u.id_uuid 
FROM users u 
WHERE rt.user_id = u.id AND rt.user_id_uuid IS NULL;

-- sessions (déjà en UUID, mais vérifier cohérence)
-- Si sessions.user_id est déjà UUID, créer un mapping inverse
-- Note: Cette table semble déjà utiliser UUID, donc on va juste s'assurer de la cohérence
-- UPDATE sessions s SET user_id = u.id_uuid FROM users u WHERE ... (si nécessaire)

-- messages
ALTER TABLE messages ADD COLUMN IF NOT EXISTS sender_id_uuid UUID;
UPDATE messages m 
SET sender_id_uuid = u.id_uuid 
FROM users u 
WHERE m.sender_id = u.id AND m.sender_id_uuid IS NULL;

-- rooms (owner_id)
ALTER TABLE rooms ADD COLUMN IF NOT EXISTS owner_id_uuid UUID;
UPDATE rooms r 
SET owner_id_uuid = u.id_uuid 
FROM users u 
WHERE r.owner_id = u.id AND r.owner_id_uuid IS NULL;

-- room_members
ALTER TABLE room_members ADD COLUMN IF NOT EXISTS user_id_uuid UUID;
UPDATE room_members rm 
SET user_id_uuid = u.id_uuid 
FROM users u 
WHERE rm.user_id = u.id AND rm.user_id_uuid IS NULL;

-- track_likes
ALTER TABLE track_likes ADD COLUMN IF NOT EXISTS user_id_uuid UUID;
UPDATE track_likes tl 
SET user_id_uuid = u.id_uuid 
FROM users u 
WHERE tl.user_id = u.id AND tl.user_id_uuid IS NULL;

-- track_comments
ALTER TABLE track_comments ADD COLUMN IF NOT EXISTS user_id_uuid UUID;
UPDATE track_comments tc 
SET user_id_uuid = u.id_uuid 
FROM users u 
WHERE tc.user_id = u.id AND tc.user_id_uuid IS NULL;

-- track_shares
ALTER TABLE track_shares ADD COLUMN IF NOT EXISTS user_id_uuid UUID;
UPDATE track_shares ts 
SET user_id_uuid = u.id_uuid 
FROM users u 
WHERE ts.user_id = u.id AND ts.user_id_uuid IS NULL;

-- playlist_collaborators
ALTER TABLE playlist_collaborators ADD COLUMN IF NOT EXISTS user_id_uuid UUID;
UPDATE playlist_collaborators pc 
SET user_id_uuid = u.id_uuid 
FROM users u 
WHERE pc.user_id = u.id AND pc.user_id_uuid IS NULL;

-- playlist_follows
ALTER TABLE playlist_follows ADD COLUMN IF NOT EXISTS user_id_uuid UUID;
UPDATE playlist_follows pf 
SET user_id_uuid = u.id_uuid 
FROM users u 
WHERE pf.user_id = u.id AND pf.user_id_uuid IS NULL;

-- user_settings
ALTER TABLE user_settings ADD COLUMN IF NOT EXISTS user_id_uuid UUID;
UPDATE user_settings us 
SET user_id_uuid = u.id_uuid 
FROM users u 
WHERE us.user_id = u.id AND us.user_id_uuid IS NULL;

-- =====================================================
-- ÉTAPE 3: Supprimer anciennes colonnes et renommer UUID
-- =====================================================

-- NOTE: Ces étapes sont DESTRUCTIVES et ne peuvent être annulées sans backup
-- En production, exécuter avec précaution et APRÈS validation complète

-- Supprimer les anciennes FK constraints
ALTER TABLE user_roles DROP CONSTRAINT IF EXISTS user_roles_user_id_fkey;
ALTER TABLE tracks DROP CONSTRAINT IF EXISTS tracks_user_id_fkey;
ALTER TABLE playlists DROP CONSTRAINT IF EXISTS playlists_user_id_fkey;
ALTER TABLE refresh_tokens DROP CONSTRAINT IF EXISTS refresh_tokens_user_id_fkey;
ALTER TABLE messages DROP CONSTRAINT IF EXISTS messages_sender_id_fkey;
ALTER TABLE rooms DROP CONSTRAINT IF EXISTS rooms_owner_id_fkey;
ALTER TABLE room_members DROP CONSTRAINT IF EXISTS room_members_user_id_fkey;
ALTER TABLE track_likes DROP CONSTRAINT IF EXISTS track_likes_user_id_fkey;
ALTER TABLE track_comments DROP CONSTRAINT IF EXISTS track_comments_user_id_fkey;
ALTER TABLE track_shares DROP CONSTRAINT IF EXISTS track_shares_user_id_fkey;
ALTER TABLE playlist_collaborators DROP CONSTRAINT IF EXISTS playlist_collaborators_user_id_fkey;
ALTER TABLE playlist_follows DROP CONSTRAINT IF EXISTS playlist_follows_user_id_fkey;
ALTER TABLE user_settings DROP CONSTRAINT IF EXISTS user_settings_user_id_fkey;

-- Supprimer anciennes colonnes INT
ALTER TABLE user_roles DROP COLUMN IF EXISTS user_id;
ALTER TABLE tracks DROP COLUMN IF EXISTS user_id;
ALTER TABLE playlists DROP COLUMN IF EXISTS user_id;
ALTER TABLE refresh_tokens DROP COLUMN IF EXISTS user_id;
ALTER TABLE messages DROP COLUMN IF EXISTS sender_id;
ALTER TABLE rooms DROP COLUMN IF EXISTS owner_id;
ALTER TABLE room_members DROP COLUMN IF EXISTS user_id;
ALTER TABLE track_likes DROP COLUMN IF EXISTS user_id;
ALTER TABLE track_comments DROP COLUMN IF EXISTS user_id;
ALTER TABLE track_shares DROP COLUMN IF EXISTS user_id;
ALTER TABLE playlist_collaborators DROP COLUMN IF EXISTS user_id;
ALTER TABLE playlist_follows DROP COLUMN IF EXISTS user_id;
ALTER TABLE user_settings DROP COLUMN IF EXISTS user_id;

-- Renommer colonnes UUID vers le nom standard
ALTER TABLE user_roles RENAME COLUMN user_id_uuid TO user_id;
ALTER TABLE tracks RENAME COLUMN user_id_uuid TO user_id;
ALTER TABLE playlists RENAME COLUMN user_id_uuid TO user_id;
ALTER TABLE refresh_tokens RENAME COLUMN user_id_uuid TO user_id;
ALTER TABLE messages RENAME COLUMN sender_id_uuid TO sender_id;
ALTER TABLE rooms RENAME COLUMN owner_id_uuid TO owner_id;
ALTER TABLE room_members RENAME COLUMN user_id_uuid TO user_id;
ALTER TABLE track_likes RENAME COLUMN user_id_uuid TO user_id;
ALTER TABLE track_comments RENAME COLUMN user_id_uuid TO user_id;
ALTER TABLE track_shares RENAME COLUMN user_id_uuid TO user_id;
ALTER TABLE playlist_collaborators RENAME COLUMN user_id_uuid TO user_id;
ALTER TABLE playlist_follows RENAME COLUMN user_id_uuid TO user_id;
ALTER TABLE user_settings RENAME COLUMN user_id_uuid TO user_id;

-- Définir NOT NULL sur les colonnes
ALTER TABLE user_roles ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE tracks ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE playlists ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE refresh_tokens ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE messages ALTER COLUMN sender_id SET NOT NULL;
ALTER TABLE rooms ALTER COLUMN owner_id SET NOT NULL;
ALTER TABLE room_members ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE track_likes ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE track_comments ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE track_shares ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE playlist_collaborators ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE playlist_follows ALTER COLUMN user_id SET NOT NULL;
ALTER TABLE user_settings ALTER COLUMN user_id SET NOT NULL;

-- =====================================================
-- ÉTAPE 4: Migrer users.id vers UUID
-- =====================================================

-- Supprimer l'ancienne colonne id (BIGINT)
ALTER TABLE users DROP CONSTRAINT IF EXISTS users_pkey;
ALTER TABLE users DROP COLUMN IF EXISTS id;

-- Renommer id_uuid vers id
ALTER TABLE users RENAME COLUMN id_uuid TO id;

-- Définir comme PRIMARY KEY
ALTER TABLE users ADD PRIMARY KEY (id);

-- =====================================================
-- ÉTAPE 5: Recréer les FK constraints avec UUID
-- =====================================================

ALTER TABLE user_roles 
ADD CONSTRAINT fk_user_roles_users 
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;

ALTER TABLE tracks 
ADD CONSTRAINT fk_tracks_users 
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;

ALTER TABLE playlists 
ADD CONSTRAINT fk_playlists_users 
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;

ALTER TABLE refresh_tokens 
ADD CONSTRAINT fk_refresh_tokens_users 
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;

ALTER TABLE messages 
ADD CONSTRAINT fk_messages_users 
FOREIGN KEY (sender_id) REFERENCES users(id) ON DELETE CASCADE;

ALTER TABLE rooms 
ADD CONSTRAINT fk_rooms_users 
FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE;

ALTER TABLE room_members 
ADD CONSTRAINT fk_room_members_users 
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;

ALTER TABLE track_likes 
ADD CONSTRAINT fk_track_likes_users 
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;

ALTER TABLE track_comments 
ADD CONSTRAINT fk_track_comments_users 
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;

ALTER TABLE track_shares 
ADD CONSTRAINT fk_track_shares_users 
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;

ALTER TABLE playlist_collaborators 
ADD CONSTRAINT fk_playlist_collaborators_users 
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;

ALTER TABLE playlist_follows 
ADD CONSTRAINT fk_playlist_follows_users 
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;

ALTER TABLE user_settings 
ADD CONSTRAINT fk_user_settings_users 
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;

-- =====================================================
-- ÉTAPE 6: Recréer les indexes
-- =====================================================

CREATE INDEX IF NOT EXISTS idx_user_roles_user_id ON user_roles(user_id);
CREATE INDEX IF NOT EXISTS idx_tracks_user_id ON tracks(user_id);
CREATE INDEX IF NOT EXISTS idx_playlists_user_id ON playlists(user_id);
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user_id ON refresh_tokens(user_id);
CREATE INDEX IF NOT EXISTS idx_messages_sender_id ON messages(sender_id);
CREATE INDEX IF NOT EXISTS idx_rooms_owner_id ON rooms(owner_id);
CREATE INDEX IF NOT EXISTS idx_room_members_user_id ON room_members(user_id);
CREATE INDEX IF NOT EXISTS idx_track_likes_user_id ON track_likes(user_id);
CREATE INDEX IF NOT EXISTS idx_track_comments_user_id ON track_comments(user_id);
CREATE INDEX IF NOT EXISTS idx_track_shares_user_id ON track_shares(user_id);
CREATE INDEX IF NOT EXISTS idx_playlist_collaborators_user_id ON playlist_collaborators(user_id);
CREATE INDEX IF NOT EXISTS idx_playlist_follows_user_id ON playlist_follows(user_id);
CREATE INDEX IF NOT EXISTS idx_user_settings_user_id ON user_settings(user_id);

-- =====================================================
-- VERIFICATION
-- =====================================================

-- Vérifier que tous les users ont un UUID valide
DO $$
DECLARE
    user_count INT;
    null_uuid_count INT;
BEGIN
    SELECT COUNT(*) INTO user_count FROM users;
    SELECT COUNT(*) INTO null_uuid_count FROM users WHERE id IS NULL;
    
    RAISE NOTICE 'Migration UUID - Total users: %, Users avec UUID NULL: %', user_count, null_uuid_count;
    
    IF null_uuid_count > 0 THEN
        RAISE EXCEPTION 'Migration échouée: % utilisateurs ont un UUID NULL', null_uuid_count;
    END IF;
END $$;

-- Vérifier l'intégrité référentielle
-- TODO: Ajouter des checks supplémentaires si nécessaire

COMMENT ON COLUMN users.id IS 'UUID unique de l''utilisateur (migré de BIGINT)';

