-- Migration V1.3: Conversion des colonnes ID de BIGINT vers UUID
-- Auteur: UnionFlow Team
-- Date: 2025-01-16
-- Description: Convertit toutes les colonnes ID et clés étrangères de BIGINT vers UUID
-- ATTENTION: Cette migration supprime toutes les données existantes pour simplifier la conversion
-- Pour une migration avec préservation des données, voir V1.3.1__Convert_Ids_To_UUID_With_Data.sql

-- ============================================
-- ÉTAPE 1: Suppression des contraintes de clés étrangères
-- ============================================

-- Supprimer les contraintes de clés étrangères existantes
DO $$
BEGIN
    -- Supprimer FK membres -> organisations
    IF EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_name = 'fk_membre_organisation' 
        AND table_name = 'membres'
    ) THEN
        ALTER TABLE membres DROP CONSTRAINT fk_membre_organisation;
    END IF;

    -- Supprimer FK cotisations -> membres
    IF EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_name LIKE 'fk_cotisation%' 
        AND table_name = 'cotisations'
    ) THEN
        ALTER TABLE cotisations DROP CONSTRAINT IF EXISTS fk_cotisation_membre CASCADE;
    END IF;

    -- Supprimer FK evenements -> organisations
    IF EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_name LIKE 'fk_evenement%' 
        AND table_name = 'evenements'
    ) THEN
        ALTER TABLE evenements DROP CONSTRAINT IF EXISTS fk_evenement_organisation CASCADE;
    END IF;

    -- Supprimer FK inscriptions_evenement -> membres et evenements
    IF EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_name LIKE 'fk_inscription%' 
        AND table_name = 'inscriptions_evenement'
    ) THEN
        ALTER TABLE inscriptions_evenement DROP CONSTRAINT IF EXISTS fk_inscription_membre CASCADE;
        ALTER TABLE inscriptions_evenement DROP CONSTRAINT IF EXISTS fk_inscription_evenement CASCADE;
    END IF;

    -- Supprimer FK demandes_aide -> membres et organisations
    IF EXISTS (
        SELECT 1 FROM information_schema.table_constraints 
        WHERE constraint_name LIKE 'fk_demande%' 
        AND table_name = 'demandes_aide'
    ) THEN
        ALTER TABLE demandes_aide DROP CONSTRAINT IF EXISTS fk_demande_demandeur CASCADE;
        ALTER TABLE demandes_aide DROP CONSTRAINT IF EXISTS fk_demande_evaluateur CASCADE;
        ALTER TABLE demandes_aide DROP CONSTRAINT IF EXISTS fk_demande_organisation CASCADE;
    END IF;
END $$;

-- ============================================
-- ÉTAPE 2: Supprimer les séquences (BIGSERIAL)
-- ============================================

DROP SEQUENCE IF EXISTS membres_SEQ CASCADE;
DROP SEQUENCE IF EXISTS cotisations_SEQ CASCADE;
DROP SEQUENCE IF EXISTS evenements_SEQ CASCADE;
DROP SEQUENCE IF EXISTS organisations_id_seq CASCADE;

-- ============================================
-- ÉTAPE 3: Supprimer les tables existantes (pour recréation avec UUID)
-- ============================================

-- Supprimer les tables dans l'ordre inverse des dépendances
DROP TABLE IF EXISTS inscriptions_evenement CASCADE;
DROP TABLE IF EXISTS demandes_aide CASCADE;
DROP TABLE IF EXISTS cotisations CASCADE;
DROP TABLE IF EXISTS evenements CASCADE;
DROP TABLE IF EXISTS membres CASCADE;
DROP TABLE IF EXISTS organisations CASCADE;

-- ============================================
-- ÉTAPE 4: Recréer les tables avec UUID
-- ============================================

-- Table organisations avec UUID
CREATE TABLE organisations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    
    -- Informations de base
    nom VARCHAR(200) NOT NULL,
    nom_court VARCHAR(50),
    type_organisation VARCHAR(50) NOT NULL DEFAULT 'ASSOCIATION',
    statut VARCHAR(50) NOT NULL DEFAULT 'ACTIVE',
    description TEXT,
    date_fondation DATE,
    numero_enregistrement VARCHAR(100) UNIQUE,
    
    -- Informations de contact
    email VARCHAR(255) NOT NULL UNIQUE,
    telephone VARCHAR(20),
    telephone_secondaire VARCHAR(20),
    email_secondaire VARCHAR(255),
    
    -- Adresse
    adresse VARCHAR(500),
    ville VARCHAR(100),
    code_postal VARCHAR(20),
    region VARCHAR(100),
    pays VARCHAR(100),
    
    -- Coordonnées géographiques
    latitude DECIMAL(9,6) CHECK (latitude >= -90 AND latitude <= 90),
    longitude DECIMAL(9,6) CHECK (longitude >= -180 AND longitude <= 180),
    
    -- Web et réseaux sociaux
    site_web VARCHAR(500),
    logo VARCHAR(500),
    reseaux_sociaux VARCHAR(1000),
    
    -- Hiérarchie
    organisation_parente_id UUID,
    niveau_hierarchique INTEGER NOT NULL DEFAULT 0,
    
    -- Statistiques
    nombre_membres INTEGER NOT NULL DEFAULT 0,
    nombre_administrateurs INTEGER NOT NULL DEFAULT 0,
    
    -- Finances
    budget_annuel DECIMAL(14,2) CHECK (budget_annuel >= 0),
    devise VARCHAR(3) DEFAULT 'XOF',
    cotisation_obligatoire BOOLEAN NOT NULL DEFAULT FALSE,
    montant_cotisation_annuelle DECIMAL(12,2) CHECK (montant_cotisation_annuelle >= 0),
    
    -- Informations complémentaires
    objectifs TEXT,
    activites_principales TEXT,
    certifications VARCHAR(500),
    partenaires VARCHAR(1000),
    notes VARCHAR(1000),
    
    -- Paramètres
    organisation_publique BOOLEAN NOT NULL DEFAULT TRUE,
    accepte_nouveaux_membres BOOLEAN NOT NULL DEFAULT TRUE,
    
    -- Métadonnées (héritées de BaseEntity)
    actif BOOLEAN NOT NULL DEFAULT TRUE,
    date_creation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    date_modification TIMESTAMP,
    cree_par VARCHAR(255),
    modifie_par VARCHAR(255),
    version BIGINT NOT NULL DEFAULT 0,
    
    -- Contraintes
    CONSTRAINT chk_organisation_statut CHECK (statut IN ('ACTIVE', 'SUSPENDUE', 'DISSOUTE', 'EN_ATTENTE')),
    CONSTRAINT chk_organisation_type CHECK (type_organisation IN (
        'ASSOCIATION', 'LIONS_CLUB', 'ROTARY_CLUB', 'COOPERATIVE', 
        'FONDATION', 'ONG', 'SYNDICAT', 'AUTRE'
    )),
    CONSTRAINT chk_organisation_devise CHECK (devise IN ('XOF', 'EUR', 'USD', 'GBP', 'CHF')),
    CONSTRAINT chk_organisation_niveau CHECK (niveau_hierarchique >= 0 AND niveau_hierarchique <= 10),
    CONSTRAINT chk_organisation_membres CHECK (nombre_membres >= 0),
    CONSTRAINT chk_organisation_admins CHECK (nombre_administrateurs >= 0),
    
    -- Clé étrangère pour hiérarchie
    CONSTRAINT fk_organisation_parente FOREIGN KEY (organisation_parente_id) 
        REFERENCES organisations(id) ON DELETE SET NULL
);

-- Table membres avec UUID
CREATE TABLE membres (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    
    numero_membre VARCHAR(20) UNIQUE NOT NULL,
    prenom VARCHAR(100) NOT NULL,
    nom VARCHAR(100) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    mot_de_passe VARCHAR(255),
    telephone VARCHAR(20),
    date_naissance DATE NOT NULL,
    date_adhesion DATE NOT NULL,
    roles VARCHAR(500),
    
    -- Clé étrangère vers organisations
    organisation_id UUID,
    
    -- Métadonnées (héritées de BaseEntity)
    actif BOOLEAN NOT NULL DEFAULT TRUE,
    date_creation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    date_modification TIMESTAMP,
    cree_par VARCHAR(255),
    modifie_par VARCHAR(255),
    version BIGINT NOT NULL DEFAULT 0,
    
    CONSTRAINT fk_membre_organisation FOREIGN KEY (organisation_id) 
        REFERENCES organisations(id) ON DELETE SET NULL
);

-- Table cotisations avec UUID
CREATE TABLE cotisations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    
    numero_reference VARCHAR(50) UNIQUE NOT NULL,
    membre_id UUID NOT NULL,
    type_cotisation VARCHAR(50) NOT NULL,
    montant_du DECIMAL(12,2) NOT NULL CHECK (montant_du >= 0),
    montant_paye DECIMAL(12,2) NOT NULL DEFAULT 0 CHECK (montant_paye >= 0),
    code_devise VARCHAR(3) NOT NULL DEFAULT 'XOF',
    statut VARCHAR(30) NOT NULL,
    date_echeance DATE NOT NULL,
    date_paiement TIMESTAMP,
    description VARCHAR(500),
    periode VARCHAR(20),
    annee INTEGER NOT NULL CHECK (annee >= 2020 AND annee <= 2100),
    mois INTEGER CHECK (mois >= 1 AND mois <= 12),
    observations VARCHAR(1000),
    recurrente BOOLEAN NOT NULL DEFAULT FALSE,
    nombre_rappels INTEGER NOT NULL DEFAULT 0 CHECK (nombre_rappels >= 0),
    date_dernier_rappel TIMESTAMP,
    valide_par_id UUID,
    nom_validateur VARCHAR(100),
    date_validation TIMESTAMP,
    methode_paiement VARCHAR(50),
    reference_paiement VARCHAR(100),
    
    -- Métadonnées (héritées de BaseEntity)
    actif BOOLEAN NOT NULL DEFAULT TRUE,
    date_creation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    date_modification TIMESTAMP,
    cree_par VARCHAR(255),
    modifie_par VARCHAR(255),
    version BIGINT NOT NULL DEFAULT 0,
    
    CONSTRAINT fk_cotisation_membre FOREIGN KEY (membre_id) 
        REFERENCES membres(id) ON DELETE CASCADE,
    CONSTRAINT chk_cotisation_statut CHECK (statut IN ('EN_ATTENTE', 'PAYEE', 'EN_RETARD', 'PARTIELLEMENT_PAYEE', 'ANNULEE')),
    CONSTRAINT chk_cotisation_devise CHECK (code_devise ~ '^[A-Z]{3}$')
);

-- Table evenements avec UUID
CREATE TABLE evenements (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    
    titre VARCHAR(200) NOT NULL,
    description VARCHAR(2000),
    date_debut TIMESTAMP NOT NULL,
    date_fin TIMESTAMP,
    lieu VARCHAR(255) NOT NULL,
    adresse VARCHAR(500),
    ville VARCHAR(100),
    pays VARCHAR(100),
    code_postal VARCHAR(20),
    latitude DECIMAL(9,6),
    longitude DECIMAL(9,6),
    type_evenement VARCHAR(50) NOT NULL,
    statut VARCHAR(50) NOT NULL,
    url_inscription VARCHAR(500),
    url_informations VARCHAR(500),
    image_url VARCHAR(500),
    capacite_max INTEGER,
    cout_participation DECIMAL(12,2),
    devise VARCHAR(3),
    est_public BOOLEAN NOT NULL DEFAULT TRUE,
    tags VARCHAR(500),
    notes VARCHAR(1000),
    
    -- Clé étrangère vers organisations
    organisation_id UUID,
    
    -- Métadonnées (héritées de BaseEntity)
    actif BOOLEAN NOT NULL DEFAULT TRUE,
    date_creation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    date_modification TIMESTAMP,
    cree_par VARCHAR(255),
    modifie_par VARCHAR(255),
    version BIGINT NOT NULL DEFAULT 0,
    
    CONSTRAINT fk_evenement_organisation FOREIGN KEY (organisation_id) 
        REFERENCES organisations(id) ON DELETE SET NULL
);

-- Table inscriptions_evenement avec UUID
CREATE TABLE inscriptions_evenement (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    
    membre_id UUID NOT NULL,
    evenement_id UUID NOT NULL,
    date_inscription TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    statut VARCHAR(20) DEFAULT 'CONFIRMEE',
    commentaire VARCHAR(500),
    
    -- Métadonnées (héritées de BaseEntity)
    actif BOOLEAN NOT NULL DEFAULT TRUE,
    date_creation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    date_modification TIMESTAMP,
    cree_par VARCHAR(255),
    modifie_par VARCHAR(255),
    version BIGINT NOT NULL DEFAULT 0,
    
    CONSTRAINT fk_inscription_membre FOREIGN KEY (membre_id) 
        REFERENCES membres(id) ON DELETE CASCADE,
    CONSTRAINT fk_inscription_evenement FOREIGN KEY (evenement_id) 
        REFERENCES evenements(id) ON DELETE CASCADE,
    CONSTRAINT chk_inscription_statut CHECK (statut IN ('CONFIRMEE', 'EN_ATTENTE', 'ANNULEE', 'REFUSEE')),
    CONSTRAINT uk_inscription_membre_evenement UNIQUE (membre_id, evenement_id)
);

-- Table demandes_aide avec UUID
CREATE TABLE demandes_aide (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    
    titre VARCHAR(200) NOT NULL,
    description TEXT NOT NULL,
    type_aide VARCHAR(50) NOT NULL,
    statut VARCHAR(50) NOT NULL,
    montant_demande DECIMAL(10,2),
    montant_approuve DECIMAL(10,2),
    date_demande TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    date_evaluation TIMESTAMP,
    date_versement TIMESTAMP,
    justification TEXT,
    commentaire_evaluation TEXT,
    urgence BOOLEAN NOT NULL DEFAULT FALSE,
    documents_fournis VARCHAR(500),
    
    -- Clés étrangères
    demandeur_id UUID NOT NULL,
    evaluateur_id UUID,
    organisation_id UUID NOT NULL,
    
    -- Métadonnées (héritées de BaseEntity)
    actif BOOLEAN NOT NULL DEFAULT TRUE,
    date_creation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    date_modification TIMESTAMP,
    cree_par VARCHAR(255),
    modifie_par VARCHAR(255),
    version BIGINT NOT NULL DEFAULT 0,
    
    CONSTRAINT fk_demande_demandeur FOREIGN KEY (demandeur_id) 
        REFERENCES membres(id) ON DELETE CASCADE,
    CONSTRAINT fk_demande_evaluateur FOREIGN KEY (evaluateur_id) 
        REFERENCES membres(id) ON DELETE SET NULL,
    CONSTRAINT fk_demande_organisation FOREIGN KEY (organisation_id) 
        REFERENCES organisations(id) ON DELETE CASCADE
);

-- ============================================
-- ÉTAPE 5: Recréer les index
-- ============================================

-- Index pour organisations
CREATE INDEX idx_organisation_nom ON organisations(nom);
CREATE INDEX idx_organisation_email ON organisations(email);
CREATE INDEX idx_organisation_statut ON organisations(statut);
CREATE INDEX idx_organisation_type ON organisations(type_organisation);
CREATE INDEX idx_organisation_ville ON organisations(ville);
CREATE INDEX idx_organisation_pays ON organisations(pays);
CREATE INDEX idx_organisation_parente ON organisations(organisation_parente_id);
CREATE INDEX idx_organisation_numero_enregistrement ON organisations(numero_enregistrement);
CREATE INDEX idx_organisation_actif ON organisations(actif);
CREATE INDEX idx_organisation_date_creation ON organisations(date_creation);
CREATE INDEX idx_organisation_publique ON organisations(organisation_publique);
CREATE INDEX idx_organisation_accepte_membres ON organisations(accepte_nouveaux_membres);
CREATE INDEX idx_organisation_statut_actif ON organisations(statut, actif);

-- Index pour membres
CREATE INDEX idx_membre_email ON membres(email);
CREATE INDEX idx_membre_numero ON membres(numero_membre);
CREATE INDEX idx_membre_actif ON membres(actif);
CREATE INDEX idx_membre_organisation ON membres(organisation_id);

-- Index pour cotisations
CREATE INDEX idx_cotisation_membre ON cotisations(membre_id);
CREATE INDEX idx_cotisation_reference ON cotisations(numero_reference);
CREATE INDEX idx_cotisation_statut ON cotisations(statut);
CREATE INDEX idx_cotisation_echeance ON cotisations(date_echeance);
CREATE INDEX idx_cotisation_type ON cotisations(type_cotisation);
CREATE INDEX idx_cotisation_annee_mois ON cotisations(annee, mois);

-- Index pour evenements
CREATE INDEX idx_evenement_date_debut ON evenements(date_debut);
CREATE INDEX idx_evenement_statut ON evenements(statut);
CREATE INDEX idx_evenement_type ON evenements(type_evenement);
CREATE INDEX idx_evenement_organisation ON evenements(organisation_id);

-- Index pour inscriptions_evenement
CREATE INDEX idx_inscription_membre ON inscriptions_evenement(membre_id);
CREATE INDEX idx_inscription_evenement ON inscriptions_evenement(evenement_id);
CREATE INDEX idx_inscription_date ON inscriptions_evenement(date_inscription);

-- Index pour demandes_aide
CREATE INDEX idx_demande_demandeur ON demandes_aide(demandeur_id);
CREATE INDEX idx_demande_evaluateur ON demandes_aide(evaluateur_id);
CREATE INDEX idx_demande_organisation ON demandes_aide(organisation_id);
CREATE INDEX idx_demande_statut ON demandes_aide(statut);
CREATE INDEX idx_demande_type ON demandes_aide(type_aide);
CREATE INDEX idx_demande_date_demande ON demandes_aide(date_demande);

-- ============================================
-- ÉTAPE 6: Commentaires sur les tables
-- ============================================

COMMENT ON TABLE organisations IS 'Table des organisations (Lions Clubs, Associations, Coopératives, etc.) avec UUID';
COMMENT ON TABLE membres IS 'Table des membres avec UUID';
COMMENT ON TABLE cotisations IS 'Table des cotisations avec UUID';
COMMENT ON TABLE evenements IS 'Table des événements avec UUID';
COMMENT ON TABLE inscriptions_evenement IS 'Table des inscriptions aux événements avec UUID';
COMMENT ON TABLE demandes_aide IS 'Table des demandes d''aide avec UUID';

COMMENT ON COLUMN organisations.id IS 'UUID unique de l''organisation';
COMMENT ON COLUMN membres.id IS 'UUID unique du membre';
COMMENT ON COLUMN cotisations.id IS 'UUID unique de la cotisation';
COMMENT ON COLUMN evenements.id IS 'UUID unique de l''événement';
COMMENT ON COLUMN inscriptions_evenement.id IS 'UUID unique de l''inscription';
COMMENT ON COLUMN demandes_aide.id IS 'UUID unique de la demande d''aide';

