-- ================================================================
-- MISE À JOUR DES PROCÉDURES STOCKÉES SEULEMENT
-- ================================================================
-- Ce fichier ne contient que les procédures stockées
-- À exécuter directement dans phpMyAdmin pour mettre à jour
-- ================================================================

-- ----------------------------------------------------------------
-- PROCÉDURE HELPER : OBTENIR PROCHAIN NUMÉRO DE COMPTE
-- ----------------------------------------------------------------

DROP PROCEDURE IF EXISTS obtenir_prochain_numero_compte;

DELIMITER $$

CREATE PROCEDURE obtenir_prochain_numero_compte(
    IN p_id_copro INT,
    IN p_type_compte VARCHAR(3),
    OUT p_prochain_numero INT
)
BEGIN
    INSERT INTO compteurs_comptes (id_copro, type_compte, dernier_numero)
    VALUES (p_id_copro, p_type_compte, 1)
    ON DUPLICATE KEY UPDATE dernier_numero = dernier_numero + 1;
    
    SELECT dernier_numero INTO p_prochain_numero
    FROM compteurs_comptes
    WHERE id_copro = p_id_copro
    AND type_compte = p_type_compte COLLATE utf8mb4_unicode_ci;
END$$

DELIMITER ;

-- ----------------------------------------------------------------
-- PROCÉDURE : GÉNÉRER COMPTE FOURNISSEUR
-- ----------------------------------------------------------------

DROP PROCEDURE IF EXISTS generer_compte_fournisseur;

DELIMITER $$

CREATE PROCEDURE generer_compte_fournisseur(
    IN p_id_fournisseur INT
)
BEGIN
    DECLARE v_nom VARCHAR(255);
    DECLARE v_compte VARCHAR(50);
    DECLARE v_id_copro INT;
    DECLARE v_compte_clean VARCHAR(20);
    
    SELECT nom, compte_401, id_copro INTO v_nom, v_compte, v_id_copro
    FROM fournisseurs WHERE id = p_id_fournisseur;
    
    IF v_compte IS NULL OR v_compte = '' THEN
        SET v_compte_clean = UPPER(v_nom);
        SET v_compte_clean = REPLACE(v_compte_clean, ' ', '');
        SET v_compte_clean = REPLACE(v_compte_clean, '-', '');
        SET v_compte_clean = REPLACE(v_compte_clean, '''', '');
        SET v_compte_clean = REPLACE(v_compte_clean, 'É', 'E');
        SET v_compte_clean = REPLACE(v_compte_clean, 'È', 'E');
        SET v_compte_clean = REPLACE(v_compte_clean, 'À', 'A');
        SET v_compte_clean = SUBSTRING(v_compte_clean, 1, 12);
        SET v_compte = CONCAT('401', v_compte_clean);
        
        UPDATE fournisseurs SET compte_401 = v_compte WHERE id = p_id_fournisseur;
    END IF;
    
    INSERT INTO plan_comptable (numero_compte, libelle, type_compte, classe, id_copro, id_entite, type_entite)
    VALUES (v_compte, v_nom, 'tiers', '4', v_id_copro, p_id_fournisseur, 'fournisseur')
    ON DUPLICATE KEY UPDATE libelle = v_nom;
END$$

DELIMITER ;

-- ----------------------------------------------------------------
-- PROCÉDURE : GÉNÉRER COMPTE COPROPRIÉTAIRE
-- ----------------------------------------------------------------

DROP PROCEDURE IF EXISTS generer_compte_coproprietaire;

DELIMITER $$

CREATE PROCEDURE generer_compte_coproprietaire(
    IN p_id_user INT
)
BEGIN
    DECLARE v_nom VARCHAR(255);
    DECLARE v_prenom VARCHAR(255);
    DECLARE v_compte VARCHAR(50);
    DECLARE v_copro INT;
    DECLARE v_nom_clean VARCHAR(20);
    DECLARE v_dernier_numero INT;
    
    SELECT nom, prenom, compte_450, copro INTO v_nom, v_prenom, v_compte, v_copro
    FROM users WHERE id = p_id_user;
    
    IF v_compte IS NULL OR v_compte = '' THEN
        SELECT COALESCE(MAX(CAST(SUBSTRING(compte_450, 4, 6) AS UNSIGNED)), 0) INTO v_dernier_numero
        FROM users
        WHERE copro = v_copro AND compte_450 REGEXP '^450[0-9]{6}';
        
        SET v_dernier_numero = v_dernier_numero + 1;
        SET v_nom_clean = UPPER(v_nom);
        SET v_nom_clean = REPLACE(v_nom_clean, ' ', '');
        SET v_nom_clean = REPLACE(v_nom_clean, '-', '');
        SET v_nom_clean = REPLACE(v_nom_clean, 'É', 'E');
        SET v_nom_clean = REPLACE(v_nom_clean, 'È', 'E');
        SET v_nom_clean = REPLACE(v_nom_clean, 'À', 'A');
        SET v_nom_clean = SUBSTRING(v_nom_clean, 1, 8);
        SET v_compte = CONCAT('450', LPAD(v_dernier_numero, 6, '0'), v_nom_clean);
        
        UPDATE users SET compte_450 = v_compte WHERE id = p_id_user;
    END IF;
    
    INSERT INTO plan_comptable (numero_compte, libelle, type_compte, classe, id_copro, id_entite, type_entite)
    VALUES (v_compte, CONCAT(v_prenom, ' ', v_nom), 'tiers', '4', v_copro, p_id_user, 'coproprietaire')
    ON DUPLICATE KEY UPDATE libelle = CONCAT(v_prenom, ' ', v_nom);
END$$

DELIMITER ;

-- ----------------------------------------------------------------
-- PROCÉDURE : CRÉER ÉCRITURE BANCAIRE (AVEC VIREMENTS VIA 580000)
-- ----------------------------------------------------------------

DROP PROCEDURE IF EXISTS creer_ecriture_bancaire;

DELIMITER $$

CREATE PROCEDURE creer_ecriture_bancaire(
    IN p_id_bank BIGINT
)
BEGIN
    DECLARE v_id_ecriture BIGINT;
    DECLARE v_numero_ecriture VARCHAR(50);
    DECLARE v_id_copro INT;
    DECLARE v_exercice INT;
    DECLARE v_date DATE;
    DECLARE v_description TEXT;
    DECLARE v_debit DECIMAL(10,2);
    DECLARE v_credit DECIMAL(10,2);
    DECLARE v_id_bank_account INT;
    DECLARE v_id_fournisseur INT;
    DECLARE v_id_coproprietaire INT;
    DECLARE v_transfer_id INT;
    DECLARE v_compte_banque VARCHAR(20);
    DECLARE v_compte_contrepartie VARCHAR(20);
    DECLARE v_libelle_contrepartie VARCHAR(255);
    DECLARE v_type_plan VARCHAR(10);
    DECLARE v_montant DECIMAL(10,2);
    DECLARE v_dernier_numero INT;
    DECLARE v_annee VARCHAR(4);
    DECLARE v_nouveau_compte INT;
    
    SELECT id_copro, exercice, date, description, debit, credit, id_bank, fournisseur, coproprietaire, transfer_id
    INTO v_id_copro, v_exercice, v_date, v_description, v_debit, v_credit, v_id_bank_account, v_id_fournisseur, v_id_coproprietaire, v_transfer_id
    FROM bank 
    WHERE id = p_id_bank;
    
    SELECT numero_compte_512 INTO v_compte_banque
    FROM bank_account 
    WHERE id = v_id_bank_account;
    
    IF v_compte_banque IS NULL THEN
        CALL obtenir_prochain_numero_compte(v_id_copro, '512', v_nouveau_compte);
        SET v_compte_banque = CONCAT('512', LPAD(v_nouveau_compte, 3, '0'));

        UPDATE bank_account 
        SET numero_compte_512 = v_compte_banque 
        WHERE id = v_id_bank_account;

        INSERT INTO plan_comptable (numero_compte, libelle, type_compte, classe, id_copro, id_entite, type_entite)
        SELECT v_compte_banque, nom_banque, 'tiers', '5', v_id_copro, v_id_bank_account, 'banque'
        FROM bank_account WHERE id = v_id_bank_account
        ON DUPLICATE KEY UPDATE libelle = nom_banque, id_entite = v_id_bank_account, type_entite = 'banque';
    END IF;
    
    SET v_montant = COALESCE(v_debit, v_credit);
    
    SELECT YEAR(debut) INTO v_annee 
    FROM exercices 
    WHERE id = v_exercice 
    LIMIT 1;
    
    SELECT COALESCE(MAX(CAST(SUBSTRING_INDEX(numero_ecriture, '-', -1) AS UNSIGNED)), 0) INTO v_dernier_numero
    FROM ecritures_comptables
    WHERE id_copro = v_id_copro 
      AND id_exercice = v_exercice 
      AND type_ecriture = 'banque';
    
    SET v_dernier_numero = v_dernier_numero + 1;
    SET v_numero_ecriture = CONCAT('BQ-', v_annee, '-', LPAD(v_dernier_numero, 4, '0'));
    
    INSERT INTO ecritures_comptables 
        (numero_ecriture, id_copro, id_exercice, date_ecriture, libelle, type_ecriture, source_id, source_type, montant_total, valide)
    VALUES
        (v_numero_ecriture, v_id_copro, v_exercice, v_date, v_description, 'banque', p_id_bank, 'bank', v_montant, 1);
    
    SET v_id_ecriture = LAST_INSERT_ID();

    -- ========== DÉBIT (Sortie d'argent du compte) ==========
    IF v_debit IS NOT NULL AND v_debit > 0 THEN
        IF v_transfer_id IS NOT NULL THEN
            -- VIREMENT COMPTE À COMPTE via 580000
            SELECT numero_compte_512 INTO v_compte_contrepartie
            FROM bank_account WHERE id = v_transfer_id;

            IF v_compte_contrepartie IS NULL THEN
                CALL obtenir_prochain_numero_compte(v_id_copro, '512', v_nouveau_compte);
                SET v_compte_contrepartie = CONCAT('512', LPAD(v_nouveau_compte, 3, '0'));

                UPDATE bank_account 
                SET numero_compte_512 = v_compte_contrepartie 
                WHERE id = v_transfer_id;

                INSERT INTO plan_comptable (numero_compte, libelle, type_compte, classe, id_copro, id_entite, type_entite)
                SELECT v_compte_contrepartie, nom_banque, 'tiers', '5', v_id_copro, v_transfer_id, 'banque'
                FROM bank_account WHERE id = v_transfer_id
                ON DUPLICATE KEY UPDATE libelle = nom_banque, id_entite = v_transfer_id, type_entite = 'banque';
            END IF;

            -- Créer compte 580000 si nécessaire
            INSERT INTO plan_comptable (numero_compte, libelle, type_compte, classe, id_copro, id_entite, type_entite)
            VALUES ('580000', 'Virements internes', 'tiers', '5', v_id_copro, NULL, 'autre')
            ON DUPLICATE KEY UPDATE libelle = 'Virements internes';

            -- Ligne 1 : Débit 580000 (l'argent arrive dans le compte de virements internes)
            INSERT INTO lignes_ecritures 
                (id_ecriture, numero_ligne, numero_compte, libelle_ligne, debit, credit)
            VALUES
                (v_id_ecriture, 1, '580000', v_description, v_debit, 0);

            -- Ligne 2 : Crédit 512 source (l'argent sort du compte source)
            INSERT INTO lignes_ecritures 
                (id_ecriture, numero_ligne, numero_compte, libelle_ligne, debit, credit)
            VALUES
                (v_id_ecriture, 2, v_compte_banque, v_description, 0, v_debit);

            -- Ligne 3 : Débit 512 destination (l'argent arrive sur le compte destination)
            INSERT INTO lignes_ecritures 
                (id_ecriture, numero_ligne, numero_compte, libelle_ligne, debit, credit)
            VALUES
                (v_id_ecriture, 3, v_compte_contrepartie, v_description, v_debit, 0);

            -- Ligne 4 : Crédit 580000 (l'argent quitte le compte de virements internes)
            INSERT INTO lignes_ecritures 
                (id_ecriture, numero_ligne, numero_compte, libelle_ligne, debit, credit)
            VALUES
                (v_id_ecriture, 4, '580000', v_description, 0, v_debit);

        ELSEIF v_id_fournisseur IS NOT NULL AND v_id_fournisseur > 0 THEN
            -- PAIEMENT FOURNISSEUR
            SELECT compte_401 INTO v_compte_contrepartie 
            FROM fournisseurs WHERE id = v_id_fournisseur;

            INSERT INTO lignes_ecritures 
                (id_ecriture, numero_ligne, numero_compte, libelle_ligne, debit, credit, id_tiers, type_tiers)
            VALUES
                (v_id_ecriture, 1, v_compte_contrepartie, v_description, v_debit, 0, v_id_fournisseur, 'fournisseur');

            INSERT INTO lignes_ecritures 
                (id_ecriture, numero_ligne, numero_compte, libelle_ligne, debit, credit)
            VALUES
                (v_id_ecriture, 2, v_compte_banque, v_description, 0, v_debit);
                
        ELSEIF v_id_coproprietaire IS NOT NULL AND v_id_coproprietaire > 0 THEN
            -- REMBOURSEMENT / PAIEMENT COPROPRIÉTAIRE (ex: trop-perçu)
            SELECT compte_450 INTO v_compte_contrepartie 
            FROM users WHERE id = v_id_coproprietaire;

            INSERT INTO lignes_ecritures 
                (id_ecriture, numero_ligne, numero_compte, libelle_ligne, debit, credit, id_tiers, type_tiers)
            VALUES
                (v_id_ecriture, 1, v_compte_contrepartie, v_description, v_debit, 0, v_id_coproprietaire, 'coproprietaire');

            INSERT INTO lignes_ecritures 
                (id_ecriture, numero_ligne, numero_compte, libelle_ligne, debit, credit)
            VALUES
                (v_id_ecriture, 2, v_compte_banque, v_description, 0, v_debit);
                
        ELSE
            -- CHARGE SANS TIERS (par défaut : 471000 Compte d'attente)
            SET v_compte_contrepartie = '471000';
            SET v_libelle_contrepartie = 'Compte d''attente';
            SET v_type_plan = 'charge';

            INSERT INTO plan_comptable (numero_compte, libelle, type_compte, classe, id_copro, id_entite, type_entite)
            VALUES (v_compte_contrepartie, v_libelle_contrepartie, v_type_plan, '4', v_id_copro, NULL, 'autre')
            ON DUPLICATE KEY UPDATE libelle = v_libelle_contrepartie;

            INSERT INTO lignes_ecritures 
                (id_ecriture, numero_ligne, numero_compte, libelle_ligne, debit, credit)
            VALUES
                (v_id_ecriture, 1, v_compte_contrepartie, v_description, v_debit, 0);

            INSERT INTO lignes_ecritures 
                (id_ecriture, numero_ligne, numero_compte, libelle_ligne, debit, credit)
            VALUES
                (v_id_ecriture, 2, v_compte_banque, v_description, 0, v_debit);
        END IF;
    END IF;

    -- ========== CRÉDIT (Entrée d'argent sur le compte) ==========
    IF v_credit IS NOT NULL AND v_credit > 0 THEN
        IF v_transfer_id IS NOT NULL THEN
            -- VIREMENT COMPTE À COMPTE : Récupérer l'écriture créée par le débit
            -- transfer_id contient maintenant l'ID du COMPTE BANCAIRE destination
            -- On cherche l'écriture du virement opposé : compte source = notre transfer_id, compte dest = notre id_bank_account
            SELECT ec.id INTO v_id_ecriture
            FROM ecritures_comptables ec
            JOIN bank b ON b.id = ec.source_id
            WHERE ec.source_type = 'bank'
              AND b.id_bank = v_transfer_id
              AND b.transfer_id = v_id_bank_account
              AND b.debit IS NOT NULL
              AND b.debit > 0
              AND b.id_copro = v_id_copro
              AND DATE(b.date) = DATE(v_date)
            ORDER BY ec.id DESC
            LIMIT 1;
            
            -- Si pas trouvé (cas rare), on ne fait rien - l'écriture sera créée par le débit
            IF v_id_ecriture IS NULL THEN
                SET v_id_ecriture = 0;
            END IF;
            
        ELSEIF v_id_coproprietaire IS NOT NULL AND v_id_coproprietaire > 0 THEN
            -- RÈGLEMENT COPROPRIÉTAIRE
            SELECT compte_450 INTO v_compte_contrepartie 
            FROM users WHERE id = v_id_coproprietaire;

            INSERT INTO lignes_ecritures 
                (id_ecriture, numero_ligne, numero_compte, libelle_ligne, debit, credit)
            VALUES
                (v_id_ecriture, 1, v_compte_banque, v_description, v_credit, 0);

            INSERT INTO lignes_ecritures 
                (id_ecriture, numero_ligne, numero_compte, libelle_ligne, debit, credit, id_tiers, type_tiers)
            VALUES
                (v_id_ecriture, 2, v_compte_contrepartie, v_description, 0, v_credit, v_id_coproprietaire, 'coproprietaire');
        ELSE
            -- APPEL DE FONDS (706001 ou 706002)
            INSERT INTO lignes_ecritures 
                (id_ecriture, numero_ligne, numero_compte, libelle_ligne, debit, credit)
            VALUES
                (v_id_ecriture, 1, v_compte_banque, v_description, v_credit, 0);
            
            IF LOWER(v_description) REGEXP 'travaux|exceptionnel|fonds\\s*travaux|\bft\b' THEN
                SET v_compte_contrepartie = '706002';
                SET v_libelle_contrepartie = 'Appels de fonds exceptionnels';
            ELSE
                SET v_compte_contrepartie = '706001';
                SET v_libelle_contrepartie = 'Appels de fonds (charges courantes)';
            END IF;

            SET v_type_plan = 'produit';

            INSERT INTO plan_comptable (numero_compte, libelle, type_compte, classe, id_copro, id_entite, type_entite)
            VALUES (v_compte_contrepartie, v_libelle_contrepartie, v_type_plan, '7', v_id_copro, NULL, 'autre')
            ON DUPLICATE KEY UPDATE libelle = v_libelle_contrepartie;

            INSERT INTO lignes_ecritures 
                (id_ecriture, numero_ligne, numero_compte, libelle_ligne, debit, credit)
            VALUES
                (v_id_ecriture, 2, v_compte_contrepartie, v_description, 0, v_credit);
        END IF;
    END IF;

    UPDATE bank 
    SET id_ecriture_comptable = v_id_ecriture 
    WHERE id = p_id_bank;
END$$

DELIMITER ;

-- ================================================================
-- FIN DU SCRIPT DE MISE À JOUR DES PROCÉDURES
-- ================================================================
