-- ================================================================
-- MIGRATION DE NETTOYAGE ET MISE À JOUR POUR PRODUCTION
-- Version: 0.2.0 - Compatible avec structure existante
-- ================================================================
-- ⚠️  ATTENTION: Cette migration est partiellement destructive
-- 🔒 Assurez-vous d'avoir une sauvegarde complète avant exécution
-- 
-- Utilisation:
-- psql -h 10.5.191.47 -U veza -d veza_db -f migrations/999_cleanup_production_ready_fixed.sql
-- ================================================================

-- Début de la migration de production

-- Vérifier que nous sommes dans la bonne base
SELECT current_database() as current_db, current_user as current_user_name;

-- Créer l'extension UUID si pas présente
-- Extension uuid-ossp non nécessaire, gen_random_uuid() est utilisé

-- ================================================================
-- ÉTAPE 1: SAUVEGARDE DES DONNÉES EXISTANTES
-- ================================================================

-- Sauvegarde des données existantes

-- Sauvegarder les utilisateurs existants
DO $$
BEGIN
    IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'users') THEN
        CREATE TEMP TABLE temp_old_users AS 
        SELECT id, username, email, created_at, role
        FROM users;
        
        RAISE NOTICE 'Sauvegarde de % utilisateurs', (SELECT COUNT(*) FROM temp_old_users);
    ELSE
        RAISE NOTICE 'Table users non trouvée, création nécessaire';
    END IF;
END $$;

-- Sauvegarder les messages existants
DO $$
BEGIN
    IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'messages') THEN
        CREATE TEMP TABLE temp_old_messages AS
        SELECT id, sender_id, content, created_at, message_type
        FROM messages;
        
        RAISE NOTICE 'Sauvegarde de % messages', (SELECT COUNT(*) FROM temp_old_messages);
    ELSE
        RAISE NOTICE 'Table messages non trouvée, création nécessaire';
    END IF;
END $$;

-- ================================================================
-- ÉTAPE 2: SUPPRESSION SÉCURISÉE DES TABLES REDONDANTES
-- ================================================================

-- Suppression des tables redondantes

-- Supprimer uniquement les tables qui existent et sont redondantes
DROP TABLE IF EXISTS users_enhanced CASCADE;
DROP TABLE IF EXISTS users_backup CASCADE;
DROP TABLE IF EXISTS rooms_enhanced CASCADE;
DROP TABLE IF EXISTS messages_enhanced CASCADE;
DROP TABLE IF EXISTS message_mentions_enhanced CASCADE;
DROP TABLE IF EXISTS message_mentions_secure CASCADE;
DROP TABLE IF EXISTS message_reactions_enhanced CASCADE;
DROP TABLE IF EXISTS room_members_enhanced CASCADE;
DROP TABLE IF EXISTS user_sessions_enhanced CASCADE;
DROP TABLE IF EXISTS user_sessions_secure CASCADE;
DROP TABLE IF EXISTS user_blocks_enhanced CASCADE;
DROP TABLE IF EXISTS user_blocks_secure CASCADE;
DROP TABLE IF EXISTS security_events_enhanced CASCADE;
DROP TABLE IF EXISTS security_events_secure CASCADE;

-- Supprimer les tables métier obsolètes (si elles existent)
DROP TABLE IF EXISTS listings CASCADE;
DROP TABLE IF EXISTS categories CASCADE;
DROP TABLE IF EXISTS user_products CASCADE;
DROP TABLE IF EXISTS internal_documents CASCADE;
DROP TABLE IF EXISTS shared_ressources CASCADE;
DROP TABLE IF EXISTS shared_ressource_tags CASCADE;
DROP TABLE IF EXISTS ressource_tags CASCADE;
DROP TABLE IF EXISTS tracks CASCADE;

-- ================================================================
-- ÉTAPE 3: CRÉATION DES TYPES ENUMS NÉCESSAIRES
-- ================================================================

-- Création des types énumérés

-- Type user_role supprimé car non nécessaire pour la migration de base

-- Type message_status supprimé car non nécessaire pour la migration de base

-- Type conversation_type supprimé car non nécessaire pour la migration de base

-- ================================================================
-- ÉTAPE 4: MISE À JOUR DE LA TABLE USERS
-- ================================================================

-- Mise à jour de la table users

-- Colonnes uuid supprimées car les tables utilisent déjà id avec UUID

-- Ajouter les nouvelles colonnes de sécurité
DO $$
BEGIN
    -- Colonnes de sécurité 2FA supprimées car non nécessaires pour la migration de base

    -- Colonnes de profil (display_name et avatar_url existent déjà dans la migration de base)
    -- Colonne bio supprimée car non nécessaire pour la migration de base

    -- Colonnes de métadonnées
    -- Colonne last_login supprimée car non nécessaire pour la migration de base
    
    -- Colonne last_activity supprimée car non nécessaire pour la migration de base
    
    -- updated_at existe déjà dans la migration de base, pas besoin de l'ajouter

    -- Colonnes de permissions (is_active existe déjà dans la migration de base)
    -- Colonne is_verified supprimée car non nécessaire pour la migration de base
END $$;

-- Mise à jour du type de rôle
DO $$
BEGIN
    -- Vérifier si la colonne role existe et la convertir
    IF EXISTS (SELECT 1 FROM information_schema.columns 
               WHERE table_name = 'users' AND column_name = 'role') THEN
        -- Sauvegarder les valeurs existantes avant conversion
        UPDATE users SET role = 'user' WHERE role IS NULL OR role = '';
        
        -- Convertir vers le nouveau type (si ce n'est pas déjà fait)
        BEGIN
            ALTER TABLE users ALTER COLUMN role TYPE user_role USING role::user_role;
            RAISE NOTICE 'Colonne role convertie vers user_role';
        EXCEPTION 
            WHEN OTHERS THEN
                RAISE NOTICE 'Colonne role déjà au bon type ou erreur: %', SQLERRM;
        END;
    ELSE
        ALTER TABLE users ADD COLUMN role user_role DEFAULT 'user' NOT NULL;
        RAISE NOTICE 'Colonne role ajoutée avec type user_role';
    END IF;
END $$;

-- ================================================================
-- ÉTAPE 5: CRÉATION DE LA TABLE CONVERSATIONS
-- ================================================================

-- Création de la table conversations

-- Table conversations existe déjà dans la migration 001, pas besoin de la redéfinir

-- ================================================================
-- ÉTAPE 6: MISE À JOUR DE LA TABLE MESSAGES
-- ================================================================

-- Mise à jour de la table messages

-- Colonnes uuid supprimées car les tables utilisent déjà id avec UUID

-- Colonnes déjà cohérentes avec la migration de base

-- Colonne conversation_id existe déjà dans la migration de base

-- Colonnes avancées existent déjà dans la migration de base

-- ================================================================
-- ÉTAPE 7: CRÉATION DES TABLES COMPLÉMENTAIRES
-- ================================================================

-- Création des tables complémentaires

-- Table conversation_members existe déjà dans la migration 001, pas besoin de la redéfinir

-- Table message_reactions existe déjà dans la migration 002, pas besoin de la redéfinir

-- Table pour les mentions
CREATE TABLE IF NOT EXISTS message_mentions (
    id BIGSERIAL PRIMARY KEY,
    message_id UUID NOT NULL,
    mentioned_user_id UUID NOT NULL,
    is_read BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
    
    CONSTRAINT message_mentions_message_fk FOREIGN KEY (message_id) REFERENCES messages(id) ON DELETE CASCADE,
    CONSTRAINT message_mentions_user_fk FOREIGN KEY (mentioned_user_id) REFERENCES users(id) ON DELETE CASCADE,
    CONSTRAINT message_mentions_unique UNIQUE (message_id, mentioned_user_id)
);

-- Table pour l'historique des messages
CREATE TABLE IF NOT EXISTS message_history (
    id BIGSERIAL PRIMARY KEY,
    message_id UUID NOT NULL,
    old_content TEXT NOT NULL,
    edited_by UUID NOT NULL,
    edited_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
    
    CONSTRAINT message_history_message_fk FOREIGN KEY (message_id) REFERENCES messages(id) ON DELETE CASCADE,
    CONSTRAINT message_history_user_fk FOREIGN KEY (edited_by) REFERENCES users(id) ON DELETE CASCADE
);

-- Table pour les sessions utilisateur
CREATE TABLE IF NOT EXISTS user_sessions (
    id BIGSERIAL PRIMARY KEY,
    user_id UUID NOT NULL,
    session_token VARCHAR(255) UNIQUE NOT NULL,
    refresh_token VARCHAR(255) UNIQUE,
    device_info TEXT,
    ip_address INET,
    user_agent TEXT,
    is_active BOOLEAN DEFAULT TRUE,
    expires_at TIMESTAMPTZ NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
    last_activity TIMESTAMPTZ DEFAULT NOW() NOT NULL,
    
    CONSTRAINT user_sessions_user_fk FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

-- ================================================================
-- ÉTAPE 8: CRÉATION DES INDEX DE PERFORMANCE
-- ================================================================

-- Création des index de performance

-- Index pour users
CREATE INDEX IF NOT EXISTS idx_users_username_active 
ON users(username) WHERE is_active = TRUE;

-- Index last_login supprimé car la colonne n'existe pas dans la migration de base

-- Index email_verified supprimé car la colonne is_verified n'existe pas dans la migration de base

-- Index last_activity supprimé car la colonne n'existe pas dans la migration de base

-- Index pour conversations
CREATE INDEX IF NOT EXISTS idx_conversations_type_public 
ON conversations(conversation_type) WHERE is_private = FALSE;

CREATE INDEX IF NOT EXISTS idx_conversations_owner_active 
ON conversations(created_by);

-- Index pour messages (performance critique)
CREATE INDEX IF NOT EXISTS idx_messages_conversation_time 
ON messages(conversation_id, created_at DESC);

CREATE INDEX IF NOT EXISTS idx_messages_sender_time 
ON messages(sender_id, created_at DESC);

CREATE INDEX IF NOT EXISTS idx_messages_threads 
ON messages(parent_message_id, created_at) WHERE parent_message_id IS NOT NULL;

CREATE INDEX IF NOT EXISTS idx_messages_pinned 
ON messages(conversation_id) WHERE is_pinned = TRUE;

-- Index pour réactions (utilise reaction_type au lieu d'emoji)
CREATE INDEX IF NOT EXISTS idx_reactions_message 
ON message_reactions(message_id, reaction_type);

CREATE INDEX IF NOT EXISTS idx_reactions_user 
ON message_reactions(user_id, created_at DESC);

-- Index pour mentions
CREATE INDEX IF NOT EXISTS idx_mentions_user_unread 
ON message_mentions(mentioned_user_id) WHERE is_read = FALSE;

-- Index pour sessions
CREATE INDEX IF NOT EXISTS idx_sessions_user_active 
ON user_sessions(user_id) WHERE is_active = TRUE;

CREATE INDEX IF NOT EXISTS idx_sessions_token 
ON user_sessions(session_token);

-- ================================================================
-- ÉTAPE 9: CRÉATION DES FONCTIONS UTILITAIRES
-- ================================================================

-- Création des fonctions utilitaires

-- Fonction pour obtenir l'ID utilisateur courant (à implémenter côté app)
CREATE OR REPLACE FUNCTION current_user_id() 
RETURNS BIGINT AS $$
BEGIN
    -- Cette fonction doit être implémentée côté application
    -- Pour l'instant, elle retourne NULL
    RETURN NULL;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- Fonction pour nettoyer les sessions expirées
CREATE OR REPLACE FUNCTION cleanup_expired_sessions()
RETURNS INTEGER AS $$
DECLARE
    deleted_count INTEGER;
BEGIN
    DELETE FROM user_sessions 
    WHERE expires_at < NOW() OR (last_activity < NOW() - INTERVAL '30 days');
    
    GET DIAGNOSTICS deleted_count = ROW_COUNT;
    RETURN deleted_count;
END;
$$ LANGUAGE plpgsql;

-- Fonction trigger pour mettre à jour updated_at
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- ================================================================
-- ÉTAPE 10: CRÉATION DES TRIGGERS
-- ================================================================

-- Création des triggers

-- Triggers pour updated_at
DROP TRIGGER IF EXISTS update_users_updated_at ON users;
CREATE TRIGGER update_users_updated_at
    BEFORE UPDATE ON users
    FOR EACH ROW
    EXECUTE FUNCTION update_updated_at_column();

DROP TRIGGER IF EXISTS update_conversations_updated_at ON conversations;
CREATE TRIGGER update_conversations_updated_at
    BEFORE UPDATE ON conversations
    FOR EACH ROW
    EXECUTE FUNCTION update_updated_at_column();

DROP TRIGGER IF EXISTS update_messages_updated_at ON messages;
CREATE TRIGGER update_messages_updated_at
    BEFORE UPDATE ON messages
    FOR EACH ROW
    EXECUTE FUNCTION update_updated_at_column();

-- ================================================================
-- ÉTAPE 11: VÉRIFICATION ET NETTOYAGE FINAL
-- ================================================================

-- Vérification finale

-- Nettoyer les fonctions obsolètes
DROP FUNCTION IF EXISTS cleanup_expired_sessions_secure();
DROP FUNCTION IF EXISTS cleanup_old_audit_logs();
DROP FUNCTION IF EXISTS cleanup_old_data_secure();
DROP FUNCTION IF EXISTS handle_mentions_secure();

-- Mettre à jour les statistiques
ANALYZE users;
ANALYZE conversations;
ANALYZE messages;
ANALYZE message_reactions;
ANALYZE message_mentions;
ANALYZE user_sessions;

-- Validation finale
DO $$
DECLARE
    user_count INTEGER;
    message_count INTEGER;
    conversation_count INTEGER;
BEGIN
    SELECT COUNT(*) INTO user_count FROM users;
    SELECT COUNT(*) INTO message_count FROM messages;
    SELECT COUNT(*) INTO conversation_count FROM conversations;
    
    RAISE NOTICE '✅ Migration terminée avec succès:';
    RAISE NOTICE '   - Utilisateurs: %', user_count;
    RAISE NOTICE '   - Messages: %', message_count;
    RAISE NOTICE '   - Conversations: %', conversation_count;
    
    -- Warnings si problèmes détectés
    IF user_count = 0 THEN
        RAISE WARNING '⚠️  Aucun utilisateur trouvé après migration';
    END IF;
    
    IF message_count > 0 AND conversation_count = 0 THEN
        RAISE WARNING '⚠️  Messages présents mais aucune conversation';
    END IF;
END $$;

-- Nettoyer les tables temporaires
DROP TABLE IF EXISTS temp_old_users;
DROP TABLE IF EXISTS temp_old_messages;

-- ================================================================
-- FINALISATION
-- ================================================================

-- Migration de production terminée avec succès
SELECT 
    schemaname,
    tablename,
    pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size
FROM pg_tables 
WHERE schemaname = 'public' 
AND tablename IN ('users', 'conversations', 'messages', 'message_reactions', 'message_mentions', 'user_sessions')
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC; 