/**
 * ═══════════════════════════════════════════════════════════════════════════
 * RC SYNCHRONIZATION UTILITIES
 * ═══════════════════════════════════════════════════════════════════════════
 * 
 * Ce module contient toutes les fonctions utilitaires pour la synchronisation
 * bidirectionnelle entre les formulaires Tarif RC et Projet RC.
 * 
 * @author AXA Transport Team
 * @version 2.0.0
 * @since 2026-02-17
 */

(function(window) {
    'use strict';

    // ═══════════════════════════════════════════════════════════════════════
    // CONSTANTES
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * Liste exhaustive des champs qui impactent le calcul du tarif.
     * Si l'un de ces champs est modifié dans le projet, un modal
     * demandera à l'utilisateur de retourner au tarif.
     * 
     * @constant {Array<string>}
     */
    const TARIF_IMPACTING_FIELDS = [
        // Chiffre d'affaires et type de contrat
        'ca', 'chiffreAffaires', 'CA',
        'typeCotisation', 'cotisation',
        'nombreVehicules', 'nbVehicules',
        
        // Activités RCC
        'checkVoiturier', 'capitalVoiturier', 'actVoiturier',
        'checkCommissionnaire', 'capitalCommissionnaire', 'actMultimodal',
        'checkDemenageur', 'capitalDemenageur',
        'checkLogistique', 'capitalLogistique',
        'checkAutocariste', 'capitalAutocariste',
        'checkAutres', 'capitalAutres',
        
        // RCE
        'checkRCE', 'autresRC',
        
        // Activités complémentaires
        'actComplVoiturier', 'actComplCommissionnaire', 'actComplDemenageur', 'actComplLogistique',
        'activitesVoiturier', 'activitesCommissionnaire', 'activitesDemenageur', 'activitesLogistique',
        
        // Marchandises
        'marchandisesVoiturier', 'marchandisesCommissionnaire', 'marchandisesDemenageur',
        'marchandisesLogistique', 'marchandisesAutocariste', 'marchandisesAutres',
        'marOrdinaire', 'marRoulant', 'marEngins', 'marRoulantDem', 'marMobilerUsag',
        'marPerissable', 'marAnimaux', 'marCiterne', 'marBeton', 'marExceptionnels', 'marVrac',
        
        // Zones géographiques
        'zone1', 'zone2', 'zone3', 'zone4', 'zone5', 'zone6',
        
        // Extensions de garantie RCC
        'extRCCModifCalArrim', 'extRCCFerroutage', 'extRCCFraisRecons',
        'extRCCConfie', 'typeExtConfies', 'extRCCTPPC', 'extRCCRegie', 'extRCCSansMontageDemontage',
        'checkDomImmat', 'capitalDomImmat', 'checkContConf', 'capitalContConf',
        'checkDiffInv', 'capitalDiffInv', 'checkTPPC', 'capitalTPPC', 'vehiculesTPPC',
        
        // Extensions de garantie RCE
        'extRCEBraDebra', 'extRCEMontageDemontage',
        
        // Garanties additionnelles
        'checkStationLavage', 'checkGarageInterne', 'checkCSE', 'checkPJ', 'pj',
        
        // Sinistralité
        'sinistre', 'nbSinistres3ans', 'montantSinistres3ans'
    ];

    // ═══════════════════════════════════════════════════════════════════════
    // HELPERS - MANIPULATION DE VALEURS
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * Convertit une valeur en nombre en gérant les formats français et internationaux.
     * Gère les espaces, virgules, points, et valeurs nulles/undefined.
     * 
     * @param {string|number|null|undefined} x - Valeur à convertir
     * @returns {number} Nombre converti ou 0 si impossible
     * 
     * @example
     * toNumber("1 234,56")  // 1234.56
     * toNumber("1.234,56")  // 1234.56
     * toNumber("1,234.56")  // 1234.56
     * toNumber(null)        // 0
     */
    function toNumber(x) {
        if (x == null) return 0;

        let value = String(x).trim();
        if (!value) return 0;

        value = value
            .replace(/\s/g, '')
            .replace(/[^\d.,-]/g, '');

        if (!value) return 0;

        const isNegative = value.startsWith('-');
        value = value.replace(/-/g, '');
        if (isNegative && value) {
            value = '-' + value;
        }

        const hasComma = value.includes(',');
        const hasDot = value.includes('.');

        if (hasComma) {
            value = value.replace(/\./g, '').replace(/,/g, '.');
        } else if (hasDot) {
            const dotMatches = value.match(/\./g);
            const dotCount = dotMatches ? dotMatches.length : 0;
            if (dotCount > 1) {
                const parts = value.split('.');
                const lastSegment = parts[parts.length - 1];
                if (lastSegment.length === 3) {
                    value = parts.join('');
                } else {
                    value = parts.slice(0, -1).join('') + '.' + lastSegment;
                }
            }
        }

        const parsed = Number(value);
        return Number.isFinite(parsed) ? parsed : 0;
    }

    /**
     * Récupère la valeur d'un élément par son ID de manière flexible.
     * Gère les différents types d'éléments (input, select, textarea, etc.)
     * et les cas où l'ID contient des caractères spéciaux.
     * 
     * @param {string} id - ID de l'élément
     * @returns {HTMLElement|null} Élément trouvé ou null
     * 
     * @example
     * const element = getElementByIdFlexible("my-element");
     */
    function getElementByIdFlexible(id) {
        if (!id) return null;
        const direct = document.getElementById(id);
        if (direct) return direct;
        try {
            return document.querySelector(`[id="${id.replace(/"/g, '\\"')}"]`);
        } catch (err) {
            return null;
        }
    }

    /**
     * Récupère la valeur d'un champ de formulaire de manière sécurisée.
     * Gère les inputs, selects, textareas, checkboxes, et contenus textuels.
     * 
     * @param {string} elementId - ID de l'élément
     * @returns {string|number|boolean|null} Valeur du champ
     * 
     * @example
     * getValue("ca")  // "100000"
     * getValue("checkPJ")  // true
     */
    function getValue(elementId) {
        const element = getElementByIdFlexible(elementId);
        if (!element) return null;

        if (element.type === 'checkbox') {
            return element.checked;
        } else if (element.type === 'radio') {
            const checked = document.querySelector(`input[name="${element.name}"]:checked`);
            return checked ? checked.value : null;
        } else if (element.tagName === 'SELECT') {
            return element.value;
        } else if (element.value !== undefined) {
            return element.value;
        } else {
            return element.textContent || element.innerText || null;
        }
    }

    /**
     * Définit la valeur d'un champ de formulaire.
     * Gère automatiquement le type de champ et met à jour l'interface.
     * 
     * @param {string} elementId - ID de l'élément
     * @param {any} value - Valeur à définir
     * 
     * @example
     * setValue("ca", 100000);
     * setValue("checkPJ", true);
     */
    function setValue(elementId, value) {
        const element = getElementByIdFlexible(elementId);
        if (!element) {
            console.warn(`Élément non trouvé: ${elementId}`);
            return;
        }

        if (element.type === 'checkbox') {
            element.checked = Boolean(value);
        } else if (element.type === 'radio') {
            const radio = document.querySelector(`input[name="${element.name}"][value="${value}"]`);
            if (radio) radio.checked = true;
        } else if (element.tagName === 'SELECT') {
            element.value = value;
            // Réinitialiser Materialize select si présent
            if (window.M && window.M.FormSelect) {
                const instance = window.M.FormSelect.getInstance(element);
                if (instance) instance.destroy();
                window.M.FormSelect.init(element);
            }
        } else if (element.value !== undefined) {
            element.value = value;
        } else {
            element.textContent = value;
        }
    }

    // ═══════════════════════════════════════════════════════════════════════
    // COMPARAISON DE DONNÉES
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * Compare deux tableaux pour vérifier leur égalité.
     * Effectue une comparaison profonde élément par élément.
     * 
     * @param {Array} arr1 - Premier tableau
     * @param {Array} arr2 - Deuxième tableau
     * @returns {boolean} true si les tableaux sont égaux
     * 
     * @example
     * arraysEqual([1,2,3], [1,2,3])  // true
     * arraysEqual([1,2], [1,2,3])    // false
     */
    function arraysEqual(arr1, arr2) {
        if (!Array.isArray(arr1) || !Array.isArray(arr2)) return false;
        if (arr1.length !== arr2.length) return false;
        
        const sorted1 = [...arr1].sort();
        const sorted2 = [...arr2].sort();
        
        return sorted1.every((val, idx) => val === sorted2[idx]);
    }

    /**
     * Compare deux valeurs en tenant compte de leur type.
     * Gère les tableaux, objets, null, undefined, et valeurs primitives.
     * 
     * @param {any} value1 - Première valeur
     * @param {any} value2 - Deuxième valeur
     * @returns {boolean} true si les valeurs sont égales
     * 
     * @example
     * valuesEqual([1,2], [2,1])  // true (ordre indépendant)
     * valuesEqual(null, undefined)  // true
     * valuesEqual(100, "100")  // true (conversion automatique)
     */
    function valuesEqual(value1, value2) {
        // Normaliser null et undefined
        if (value1 == null && value2 == null) return true;
        if (value1 == null || value2 == null) return false;

        // Comparer les tableaux
        if (Array.isArray(value1) && Array.isArray(value2)) {
            return arraysEqual(value1, value2);
        }

        // Comparer les objets
        if (typeof value1 === 'object' && typeof value2 === 'object') {
            return JSON.stringify(value1) === JSON.stringify(value2);
        }

        // Comparer les nombres (avec conversion)
        if (!isNaN(value1) && !isNaN(value2)) {
            return toNumber(value1) === toNumber(value2);
        }

        // Comparaison standard
        return value1 === value2;
    }

    // ═══════════════════════════════════════════════════════════════════════
    // DÉTECTION DE CHANGEMENTS IMPACTANTS
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * Vérifie si un champ donné impacte le calcul du tarif.
     * Se base sur la liste TARIF_IMPACTING_FIELDS.
     * 
     * @param {string} fieldName - Nom du champ
     * @returns {boolean} true si le champ impacte le tarif
     * 
     * @example
     * isFieldImpactingTarif("ca")  // true
     * isFieldImpactingTarif("dateEffet")  // false
     */
    function isFieldImpactingTarif(fieldName) {
        return TARIF_IMPACTING_FIELDS.some(field => 
            fieldName.includes(field) || field.includes(fieldName)
        );
    }

    /**
     * Vérifie si un changement de valeur impacte le tarif.
     * Compare la nouvelle valeur avec les données originales du tarif.
     * 
     * @param {string} fieldName - Nom du champ modifié
     * @param {any} newValue - Nouvelle valeur
     * @param {Object} tarifOriginalData - Données originales du tarif
     * @returns {boolean} true si le changement impacte le tarif
     * 
     * @example
     * const impacted = isChangeImpactingTarif("ca", 200000, tarifData);
     * if (impacted) showReturnToTarifModal();
     */
    function isChangeImpactingTarif(fieldName, newValue, tarifOriginalData) {
        // Vérifier si le champ est dans la liste des champs impactants
        if (!isFieldImpactingTarif(fieldName)) {
            return false;
        }

        // Si pas de données originales, pas d'impact possible
        if (!tarifOriginalData) {
            return false;
        }

        // Récupérer la valeur originale
        const originalValue = tarifOriginalData[fieldName];

        // Comparer les valeurs
        return !valuesEqual(newValue, originalValue);
    }

    // ═══════════════════════════════════════════════════════════════════════
    // MODAL DE RETOUR AU TARIF
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * Affiche le modal demandant à l'utilisateur de retourner au tarif.
     * Ce modal s'affiche quand une modification dans le projet impacte
     * le calcul du tarif.
     * 
     * @param {string} [fieldName] - Nom du champ modifié (optionnel, pour info)
     * 
     * @example
     * showReturnToTarifModal("ca");
     */
    function showReturnToTarifModal(fieldName) {
        const modalId = 'modalRetourTarif';
        let modal = document.getElementById(modalId);

        // Créer le modal s'il n'existe pas
        if (!modal) {
            modal = createReturnToTarifModal();
            document.body.appendChild(modal);
        }

        // Mettre à jour le message si un champ est spécifié
        if (fieldName) {
            const messageEl = modal.querySelector('#modalRetourTarifMessage');
            if (messageEl) {
                messageEl.innerHTML = `
                    Vous avez modifié <strong>"${fieldName}"</strong> qui impacte le calcul du tarif.
                    <br><br>
                    Vous devez retourner sur le formulaire Tarif pour recalculer et valider le nouveau tarif.
                `;
            }
        }

        // Ouvrir le modal
        if (window.M && window.M.Modal) {
            const instance = window.M.Modal.getInstance(modal) || window.M.Modal.init(modal);
            instance.open();
        }
    }

    /**
     * Crée l'élément DOM du modal de retour au tarif.
     * 
     * @returns {HTMLElement} Élément modal créé
     * @private
     */
    function createReturnToTarifModal() {
        const modal = document.createElement('div');
        modal.id = 'modalRetourTarif';
        modal.className = 'modal';
        
        modal.innerHTML = `
            <div class="modal-content">
                <h5>⚠️ Modification impactant le tarif</h5>
                <p id="modalRetourTarifMessage">
                    Vous avez modifié une donnée qui impacte le calcul du tarif.
                    <br><br>
                    <strong>Vous devez retourner sur le formulaire Tarif pour recalculer et valider le nouveau tarif.</strong>
                </p>
            </div>
            <div class="modal-footer">
                <a href="#!" class="modal-close waves-effect waves-red btn-flat">Annuler</a>
                <a href="#!" class="waves-effect waves-green btn" onclick="window.RCSync.navigateToTarif()">
                    Aller au Tarif
                </a>
            </div>
        `;

        return modal;
    }

    /**
     * Navigate vers l'onglet Tarif depuis le Projet.
     * 
     * @example
     * navigateToTarif();
     */
    function navigateToTarif() {
        // Fermer le modal
        const modal = document.getElementById('modalRetourTarif');
        if (modal && window.M) {
            const instance = window.M.Modal.getInstance(modal);
            if (instance) instance.close();
        }

        // Naviguer vers le tarif
        const numParcours = new URLSearchParams(window.location.search).get('numParcours');
        if (numParcours) {
            window.location.href = `/navParcours?numParcours=${numParcours}&submenu=tarif`;
        }
    }

    // ═══════════════════════════════════════════════════════════════════════
    // EXPORT PUBLIC
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * API publique du module RC Sync.
     * Toutes les fonctions exportées ici sont accessibles via window.RCSync.
     */
    window.RCSync = {
        // Helpers
        toNumber,
        getValue,
        setValue,
        getElementByIdFlexible,
        
        // Comparaison
        arraysEqual,
        valuesEqual,
        
        // Détection changements
        isFieldImpactingTarif,
        isChangeImpactingTarif,
        
        // Modal
        showReturnToTarifModal,
        navigateToTarif,
        
        // Constantes
        TARIF_IMPACTING_FIELDS
    };

    console.log('✅ RC Sync Utils loaded');

})(window);