// =====================================================
// --- SCRIPT 1: CÁLCULO AUTOMÁTICO PLS-5 ---
// =====================================================

// --- Tablas de Conversión PLS-5 (Debes añadir más tablas aquí para otras edades) ---
// Estructura: [{ ageRange: 'X:X-Y:Y', minAgeMonths: MM, maxAgeMonths: MM, caScores: [...], ceScores: [...], totalScores: [...] }]
// rawScore puede ser un número simple (ej: 2) o un string de rango (ej: "0-1", "17-67")
const pls5AgeTables = [
    {
        ageRange: '0:3-0:5', // 3 a 5 meses
        minAgeMonths: 3,
        maxAgeMonths: 5,
        caScores: [ // Comprensión Auditiva
            { rawScore: "0-1", standardScore: 50, percentileRank: 1 },
            { rawScore: 2, standardScore: 54, percentileRank: 1 },
            { rawScore: 3, standardScore: 61, percentileRank: 1 },
            { rawScore: 4, standardScore: 69, percentileRank: 2 },
            { rawScore: 5, standardScore: 76, percentileRank: 5 },
            { rawScore: 6, standardScore: 83, percentileRank: 13 },
            { rawScore: 7, standardScore: 90, percentileRank: 25 },
            { rawScore: 8, standardScore: 96, percentileRank: 39 },
            { rawScore: 9, standardScore: 102, percentileRank: 55 },
            { rawScore: 10, standardScore: 109, percentileRank: 73 },
            { rawScore: 11, standardScore: 115, percentileRank: 84 },
            { rawScore: 12, standardScore: 121, percentileRank: 92 },
            { rawScore: 13, standardScore: 127, percentileRank: 96 },
            { rawScore: 14, standardScore: 133, percentileRank: 99 },
            { rawScore: 15, standardScore: 139, percentileRank: 99 },
            { rawScore: 16, standardScore: 145, percentileRank: 99 },
            { rawScore: "17-67", standardScore: 150, percentileRank: 99 } // Assuming max possible raw score for this age range is 67 based on typical ranges
        ],
        ceScores: [ // Comunicación Expresiva - Tabla proporcionada por el usuario
            { rawScore: "0-1", standardScore: 50, percentileRank: 1 },
            { rawScore: 2, standardScore: 58, percentileRank: 1 },
            { rawScore: 3, standardScore: 65, percentileRank: 1 },
            { rawScore: 4, standardScore: 71, percentileRank: 3 },
            { rawScore: 5, standardScore: 78, percentileRank: 7 },
            { rawScore: 6, standardScore: 84, percentileRank: 14 },
            { rawScore: 7, standardScore: 90, percentileRank: 25 },
            { rawScore: 8, standardScore: 96, percentileRank: 39 },
            { rawScore: 9, standardScore: 103, percentileRank: 58 },
            { rawScore: 10, standardScore: 109, percentileRank: 73 },
            { rawScore: 11, standardScore: 114, percentileRank: 82 },
            { rawScore: 12, standardScore: 119, percentileRank: 90 },
            { rawScore: 13, standardScore: 125, percentileRank: 95 },
            { rawScore: 14, standardScore: 130, percentileRank: 98 },
            { rawScore: 15, standardScore: 135, percentileRank: 99 },
            { rawScore: 16, standardScore: 140, percentileRank: 99 },
            { rawScore: 17, standardScore: 145, percentileRank: 99 },
            { rawScore: 18, standardScore: 148, percentileRank: 99 },
            { rawScore: "19-60", standardScore: 150, percentileRank: 99 } // Assuming max possible raw score based on provided table
        ],
        // totalScores: [ ... ] // TODO: Agregar tabla para Lenguaje Total si se automatiza
    },
    // TODO: --- AGREGAR AQUÍ MÁS OBJETOS CON LAS TABLAS COMPLETAS PARA OTRAS EDADES Y ESCALAS ---
    /*
    {
        ageRange: '0:6-0:8', // 6 a 8 meses
        minAgeMonths: 6,
        maxAgeMonths: 8,
        caScores: [...],
        ceScores: [...],
    },
    // ... etc.
    */
];

// --- Rangos de Interpretación Típicos para Puntuaciones Estándar PLS-5 ---
const interpretationRanges = [
    { minSS: null, maxSS: 69, text: "Muy por debajo del promedio." },
    { minSS: 70, maxSS: 79, text: "Por debajo del promedio." },
    { minSS: 80, maxSS: 89, text: "Algo por debajo del promedio." },
    { minSS: 90, maxSS: 109, text: "Promedio." },
    { minSS: 110, maxSS: 119, text: "Algo encima del promedio." },
    { minSS: 120, maxSS: 129, text: "Encima del promedio." },
    { minSS: 130, maxSS: null, text: "Muy por encima del promedio." }
];


// =====================================================
// --- SCRIPT 2: CÁLCULO Y VISUALIZACIÓN DE EDAD ---
// --- Define calcular() globally for onclick attribute ---
// =====================================================

// Function to calculate age difference - Needs to be globally accessible for onclick
function getDateDifference(startDate, endDate) {
    if (startDate > endDate) {
        return null;
    }

    let years = endDate.getFullYear() - startDate.getFullYear();
    let months = endDate.getMonth() - startDate.getMonth();
    let days = endDate.getDate() - startDate.getDate();

    if (days < 0) {
        months--;
        let daysInLastMonth = new Date(endDate.getFullYear(), endDate.getMonth(), 0).getDate();
        days += daysInLastMonth;
    }

    if (months < 0) {
        years--;
        months += 12;
    }

    years = Math.max(0, years);
    months = Math.max(0, months);
    days = Math.max(0, days);

    return {
        years: years,
        months: months,
        days: days
    };
}

// Function called by the "Calcular Edad" button - Needs to be globally accessible
function calcular() {
    const fromDateStr = document.getElementById('fecha_nacimiento_paciente').value;
    const toDateStr = document.getElementById('fecha_evaluacion').value;
    const edadInput = document.getElementById('edad');

    // Ensure DOM elements are available before proceeding
    if (!edadInput || !document.getElementById('fecha_nacimiento_paciente') || !document.getElementById('fecha_evaluacion')) {
        console.error("Error: DOM elements for age calculation not found.");
        Swal.fire({
            icon: 'error',
            title: 'Error interno',
            text: 'No se pudieron encontrar los campos necesarios para calcular la edad.'
        });
        return; // Stop execution if elements are missing
    }


    if (!fromDateStr || !toDateStr) {
         Swal.fire({
            icon: 'warning',
            title: 'Fechas incompletas',
            text: 'Por favor, seleccione la fecha de nacimiento y la fecha de evaluación para calcular la edad.'
        });
        edadInput.value = ''; // Ensure age is cleared if dates are incomplete

        // Recalculate/reset score fields based on empty age
        // Need to ensure calculate functions are accessible here if they are inside DOMContentLoaded
        // Let's define calculate functions inside DOMContentLoaded and trigger them from there.
        // For 'calcular' called globally, we need a way to trigger the calculation logic.
        // The simplest might be to move the score calculation calls inside DOMContentLoaded and
        // trigger a custom event or call a specific recalculation function *after* setting the age.

        // Alternative: Let's move the calculateComprensionAuditiva/ComunicacionExpresiva definitions
        // *outside* DOMContentLoaded if they are called directly by 'calcular'.
        // Or, even better, calculate can trigger a custom event that DOMContentLoaded listeners pick up.

        // Let's redefine the structure. age calculation is the trigger.
        // The actual PLS-5 calculation and validation should listen for changes
        // in the age input and raw score inputs.
        // The 'calcular' button only updates the age field. Event listeners on the age field
        // and raw score fields should handle the rest.

         // Let's call the recalculation logic from within DOMContentLoaded after setting the age.
         // For now, the original calls inside calcular will likely fail if those functions
         // or element references are inside the DOMContentLoaded block.
         // We'll refine this below.
         if (typeof triggerPLS5Calculations === 'function') {
             triggerPLS5Calculations(); // Call a function defined/accessible in DOMContentLoaded
         }


        return;
    }

    var fromDate = new Date(fromDateStr);
    var toDate = new Date(toDateStr);

    fromDate.setHours(12, 0, 0, 0);
    toDate.setHours(12, 0, 0, 0);

    if (fromDate > toDate) {
         Swal.fire({
            icon: 'error',
            title: 'Error en las fechas',
            text: 'La fecha de nacimiento no puede ser posterior a la fecha de evaluación.'
         });
         edadInput.value = '';

         if (typeof triggerPLS5Calculations === 'function') {
             triggerPLS5Calculations(); // Also recalculate/reset if age becomes invalid
         }
         return;
    }

    try {
        edadInput.value = '';

        var result = getDateDifference(fromDate, toDate);

        if (result) {
            edadInput.value =
                result.years.toString().padStart(2, '0') + 'A' +
                result.months.toString().padStart(2, '0') + 'M' +
                result.days.toString().padStart(2, '0') + 'D';

             // --- DESENCADENAR EL CÁLCULO DE PLS-5 AQUÍ ---
             // Trigger recalculation for PLS-5 scores based on the new age
             if (typeof triggerPLS5Calculations === 'function') {
                triggerPLS5Calculations();
             }


        } else {
             Swal.fire({
                icon: 'error',
                title: 'Error de cálculo',
                text: 'Hubo un error inesperado al calcular la edad.'
             });
             edadInput.value = '';
             if (typeof triggerPLS5Calculations === 'function') {
                 triggerPLS5Calculations();
             }
        }
    } catch (e) {
        console.error('Error al calcular la edad:', e);
         Swal.fire({
            icon: 'error',
            title: 'Error de cálculo',
            text: 'Hubo un error inesperado al calcular la edad.'
         });
        edadInput.value = '';
        if (typeof triggerPLS5Calculations === 'function') {
            triggerPLS5Calculations();
        }
    }
}

// =====================================================
// --- ALL DOM-DEPENDENT CODE GOES INSIDE DOMContentLoaded ---
// =====================================================
document.addEventListener('DOMContentLoaded', function() {

    // --- Elementos del DOM ---
    // Define DOM elements *inside* DOMContentLoaded where they are guaranteed to exist
    const ageInput = document.getElementById('edad'); // Campo de edad calculada

    // Comprensión Auditiva Elements
    const rawScoreInputCA = document.getElementById('comp_audi_punt_bruta');
    const standardScoreOutputCA = document.getElementById('compren_audit_punt_stand');
    const percentileRankOutputCA = document.getElementById('compre_audit_rango_percent');
    const interpretationOutputCA = document.getElementById('comp_audit_interpre');

    // Comunicación Expresiva Elements
    const rawScoreInputCE = document.getElementById('expre_comuni_puntua_bruta');
    const standardScoreOutputCE = document.getElementById('expr_comun_punt_estandar');
    const percentileRankOutputCE = document.getElementById('expr_comunic_rango_percent');
    const interpretationOutputCE = document.getElementById('expr_comunic_interpret');

    // Lenguaje Total Elements (TODO: Uncomment and use when implementing LT)
    const rawScoreInputLT = document.getElementById('leng_tota_punt_bruta');
    const standardScoreOutputLT = document.getElementById('leng_tota_punt_standa');
    const percentileRankOutputLT = document('leng_tota_rang_percent'); // FIX: This was missing getElementById
    const interpretationOutputLT = document.getElementById('lengua_tot_interpret');


    // --- Funciones de Ayuda (Moved or kept here if only called by functions inside this block) ---

    // Convierte la edad del formato "00A00M00D" a meses totales
    // This function can stay here if only called by calculate functions inside this block
    function parseAgeToMonths(ageString) {
        if (!ageString) return null;
        const match = ageString.match(/^(\d{2})A(\d{2})M(\d{2})D$/i);
        if (match && match[1] !== undefined && match[2] !== undefined) {
            const years = parseInt(match[1], 10);
            const months = parseInt(match[2], 10);
            return (years * 12) + months;
        }
        return null;
    }

    // Encuentra la tabla de edad correcta para los meses totales dados
    function findAgeTable(totalMonths) {
        if (totalMonths === null) return null;
        for (const table of pls5AgeTables) { // pls5AgeTables is globally defined
            if (totalMonths >= table.minAgeMonths && totalMonths <= table.maxAgeMonths) {
                return table;
            }
        }
        return null;
    }

    // Busca la Puntuación Estándar y el Percentil en la tabla de edad encontrada
    function lookupScoresInTable(rawScoreInt, ageTable, scoreType) {
        if (!ageTable || rawScoreInt === null || typeof rawScoreInt !== 'number') {
            return { standardScore: null, percentileRank: null };
        }

        const scoresArray = ageTable[`${scoreType}Scores`];
        if (!scoresArray) {
            console.warn(`No scores array found for type: ${scoreType} in age table ${ageTable.ageRange}`);
            return { standardScore: null, percentileRank: null };
        }

        for (const entry of scoresArray) {
            if (typeof entry.rawScore === 'number') {
                if (rawScoreInt === entry.rawScore) {
                    return {
                        standardScore: entry.standardScore,
                        percentileRank: entry.percentileRank
                    };
                }
            } else if (typeof entry.rawScore === 'string' && entry.rawScore.includes('-')) {
                const [min, max] = entry.rawScore.split('-').map(Number);
                if (rawScoreInt >= min && rawScoreInt <= max) {
                     return {
                        standardScore: entry.standardScore,
                        percentileRank: entry.percentileRank
                    };
                }
            }
        }
        return { standardScore: null, percentileRank: null };
    }

    // Obtiene la interpretación basada en la Puntuación Estándar
    function getInterpretation(standardScore) { // interpretationRanges is globally defined
        if (standardScore === null || typeof standardScore !== 'number') {
            return "";
        }
        for (const range of interpretationRanges) {
            const minCheck = (range.minSS === null || standardScore >= range.minSS);
            const maxCheck = (range.maxSS === null || standardScore <= range.maxSS);
            if (minCheck && maxCheck) {
                return range.text;
            }
        }
        return "";
    }

    // --- Función Genérica para manejar la actualización de campos de resultado ---
    function updateOutputFields(ssElement, prElement, interpElement, standardScore, percentileRank, interpretationText, rawScoreValue, ageValue, scoreType) {
         // Check if elements exist before trying to update them
         if (!ssElement || !prElement || !interpElement) {
             console.error(`Error: Missing output elements for score type ${scoreType}`);
             return false; // Indicate failure
         }

         ssElement.classList.remove('is-invalid');
         prElement.classList.remove('is-invalid');
         interpElement.classList.remove('is-invalid');

        // Handle NA or empty input
        if (!rawScoreValue || rawScoreValue.toUpperCase() === 'NA' || rawScoreValue.toUpperCase() === 'N/A') {
            const displayValue = (rawScoreValue.toUpperCase() === 'NA' || rawScoreValue.toUpperCase() === 'N/A') ? 'NA' : '';
            ssElement.value = displayValue;
            prElement.value = displayValue;
            interpElement.value = (displayValue === 'NA') ? 'No administrado o no aplica' : '';

            ssElement.readOnly = false;
            prElement.readOnly = false;
            interpElement.readOnly = false;
            ssElement.classList.remove('auto-filled');
            prElement.classList.remove('auto-filled');
            interpElement.classList.remove('auto-filled');
            ssElement.removeAttribute('required');
            prElement.removeAttribute('required');
            interpElement.removeAttribute('required');

            return true;
        }

        // Handle calculation success
        if (standardScore !== null && percentileRank !== null) {
            ssElement.value = standardScore;
            prElement.value = percentileRank;
            interpElement.value = interpretationText;

            ssElement.readOnly = true;
            prElement.readOnly = true;
            interpElement.readOnly = true;
            ssElement.classList.add('auto-filled');
            prElement.classList.add('auto-filled');
            interpElement.classList.add('auto-filled');

            ssElement.removeAttribute('required');
            prElement.removeAttribute('required');
            interpElement.removeAttribute('required');

             return true;
        } else {
             // Handle calculation failure
             const errorText = (!ageValue.trim()) ? 'Edad no disponible' :
                               (!findAgeTable(parseAgeToMonths(ageValue))) ? `Sin tabla para ${ageValue}` :
                               `Puntuación fuera de rango para esta edad`;

            ssElement.value = '';
            prElement.value = '';
            interpElement.value = errorText;

             ssElement.readOnly = false;
             prElement.readOnly = false;
             interpElement.readOnly = false;
             ssElement.classList.remove('auto-filled');
             prElement.classList.remove('auto-filled');
             interpElement.classList.remove('auto-filled');
             ssElement.setAttribute('required', '');
             prElement.setAttribute('required', '');
             interpElement.setAttribute('required', '');

             return false; // Indicates calculation failed
         }
    }


    // --- Calculation Functions (Defined inside DOMContentLoaded) ---
    function calculateComprensionAuditiva() {
        if (!rawScoreInputCA || !ageInput) return; // Basic check for elements

        const rawScoreValue = rawScoreInputCA.value.trim();
        const ageValue = ageInput.value.trim();
        const totalMonths = parseAgeToMonths(ageValue);
        const ageTable = findAgeTable(totalMonths);
        const rawScoreInt = parseInt(rawScoreValue, 10);
        const isNumericInput = !isNaN(rawScoreInt) && rawScoreInt >= 0 && rawScoreInt.toString() === rawScoreValue;

        let standardScore = null;
        let percentileRank = null;
        let interpretationText = '';

        if (isNumericInput && ageTable) {
             const scores = lookupScoresInTable(rawScoreInt, ageTable, 'ca');
             standardScore = scores.standardScore;
             percentileRank = scores.percentileRank;
             if (standardScore !== null) {
                 interpretationText = getInterpretation(standardScore);
             }
        }

        const success = updateOutputFields(
            standardScoreOutputCA,
            percentileRankOutputCA,
            interpretationOutputCA,
            standardScore,
            percentileRank,
            interpretationText,
            rawScoreValue,
            ageValue,
            'ca'
        );

        if (rawScoreValue && rawScoreValue.toUpperCase() !== 'NA' && isNumericInput && !success && ageTable) {
             Swal.fire({
                 icon: 'warning',
                 title: 'Puntuación Bruta fuera de rango',
                 text: `La puntuación bruta ${rawScoreInt} está fuera del rango válido para Comprensión Auditiva en la tabla de edad ${ageTable.ageRange}.`
             });
         } else if (rawScoreValue && rawScoreValue.toUpperCase() !== 'NA' && isNumericInput && !ageTable) {
              // Specific message if age was calculated but no table found
               Swal.fire({
                   icon: 'warning',
                   title: 'Sin tabla de edad',
                   text: `No hay tabla de conversión disponible para la edad calculada (${ageValue}) para Comprensión Auditiva.`
               });
         }
    }

    function calculateComunicacionExpresiva() {
         if (!rawScoreInputCE || !ageInput) return; // Basic check for elements

         const rawScoreValue = rawScoreInputCE.value.trim();
         const ageValue = ageInput.value.trim();
         const totalMonths = parseAgeToMonths(ageValue);
         const ageTable = findAgeTable(totalMonths);
         const rawScoreInt = parseInt(rawScoreValue, 10);
         const isNumericInput = !isNaN(rawScoreInt) && rawScoreInt >= 0 && rawScoreInt.toString() === rawScoreValue;


         let standardScore = null;
         let percentileRank = null;
         let interpretationText = '';

         if (isNumericInput && ageTable) {
              const scores = lookupScoresInTable(rawScoreInt, ageTable, 'ce');
              standardScore = scores.standardScore;
              percentileRank = scores.percentileRank;
              if (standardScore !== null) {
                  interpretationText = getInterpretation(standardScore);
              }
         }

         const success = updateOutputFields(
             standardScoreOutputCE,
             percentileRankOutputCE,
             interpretationOutputCE,
             standardScore,
             percentileRank,
             interpretationText,
             rawScoreValue,
             ageValue,
             'ce'
         );

          if (rawScoreValue && rawScoreValue.toUpperCase() !== 'NA' && isNumericInput && !success && ageTable) {
               Swal.fire({
                   icon: 'warning',
                   title: 'Puntuación Bruta fuera de rango',
                   text: `La puntuación bruta ${rawScoreInt} está fuera del rango válido para Comunicación Expresiva en la tabla de edad ${ageTable.ageRange}.`
               });
           } else if (rawScoreValue && rawScoreValue.toUpperCase() !== 'NA' && isNumericInput && !ageTable) {
                Swal.fire({
                    icon: 'warning',
                    title: 'Sin tabla de edad',
                    text: `No hay tabla de conversión disponible para la edad calculada (${ageValue}) para Comunicación Expresiva.`
                });
           }
    }

    // TODO: Function to calculate Lenguaje Total (LT)
    function calculateLenguajeTotal() {
         if (!rawScoreInputLT || !ageInput) return; // Basic check

         const rawScoreValue = rawScoreInputLT.value.trim(); // Or sum of CA and CE brutas? (Consult manual PLS-5)
         const ageValue = ageInput.value.trim();
         const totalMonths = parseAgeToMonths(ageValue);
         const ageTable = findAgeTable(totalMonths); // Need a table that contains totalScores

         const rawScoreInt = parseInt(rawValue, 10);
         const isNumericInput = !isNaN(rawScoreInt) && rawScoreInt >= 0 && rawScoreInt.toString() === rawScoreValue;

         let standardScore = null;
         let percentileRank = null;
         let interpretationText = '';

         // Example logic (adjust based on PLS-5 manual):
         if (isNumericInput && ageTable && ageTable.totalScores) { // Check if totalScores exist for this age
             const scores = lookupScoresInTable(rawScoreInt, ageTable, 'total'); // Use 'total' scoreType
             standardScore = scores.standardScore;
             percentileRank = scores.percentileRank;
              if (standardScore !== null) {
                  interpretationText = getInterpretation(standardScore);
              }
         }


          const success = updateOutputFields(
              standardScoreOutputLT,
              percentileRankOutputLT,
              interpretationOutputLT,
              standardScore,
              percentileRank,
              interpretationText,
              rawScoreValue,
              ageValue,
              'total'
          );

          if (rawScoreValue && rawScoreValue.toUpperCase() !== 'NA' && isNumericInput && !success && ageTable) {
               Swal.fire({
                   icon: 'warning',
                   title: 'Puntuación Bruta fuera de rango',
                   text: `La puntuación bruta ${rawScoreInt} está fuera del rango válido para Lenguaje Total en la tabla de edad ${ageTable.ageRange}.`
               });
           } else if (rawScoreValue && rawScoreValue.toUpperCase() !== 'NA' && isNumericInput && !ageTable) {
                 Swal.fire({
                     icon: 'warning',
                     title: 'Sin tabla de edad',
                     text: `No hay tabla de conversión disponible para la edad calculada (${ageValue}) para Lenguaje Total.`
                 });
            } else if (rawScoreValue && rawScoreValue.toUpperCase() !== 'NA' && isNumericInput && ageTable && !ageTable.totalScores) {
                  Swal.fire({
                     icon: 'warning',
                     title: 'Escala no aplicable',
                     text: `La escala de Lenguaje Total no aplica o no tiene tabla de conversión para la edad ${ageTable.ageRange}.`
                 });
            }
    }


    // --- Centralized function to trigger PLS-5 calculations ---
    // This function can be called by the global 'calcular' or on page load
    window.triggerPLS5Calculations = function() {
         calculateComprensionAuditiva();
         calculateComunicacionExpresiva();
         calculateLenguajeTotal(); // Call the LT calculation
    };


    // --- Event Listeners for Raw Score Inputs ---
    // These must be inside DOMContentLoaded
    const rawScoreInputs = [
        { id: 'comp_audi_punt_bruta', calculate: calculateComprensionAuditiva, ss: standardScoreOutputCA, pr: percentileRankOutputCA, interp: interpretationOutputCA },
        { id: 'expre_comuni_puntua_bruta', calculate: calculateComunicacionExpresiva, ss: standardScoreOutputCE, pr: percentileRankOutputCE, interp: interpretationOutputCE },
        // Add Lenguaje Total here
        { id: 'leng_tota_punt_bruta', calculate: calculateLenguajeTotal, ss: standardScoreOutputLT, pr: percentileRankOutputLT, interp: interpretationOutputLT },
    ];

     rawScoreInputs.forEach(item => {
         const input = document.getElementById(item.id);
         if (input) {
             // Guardar el valor inicial para posible restauración
             input.setAttribute('data-prev-value', input.value.trim());

             const validateInput = function(event) {
                 let valor = event.target.value.trim();
                 event.target.classList.remove('is-invalid');

                 // Permite una cadena vacía, números enteros (0 o más dígitos), 'NA', 'Na', 'na', 'N/A', 'n/a'
                 if (/^(\d*|NA|Na|na|N\/A|n\/a)$/i.test(valor)) {
                     if (valor === '' || valor === '-' || valor === '.') {
                           // Don't set prev value for incomplete numeric input fragments
                     } else {
                         event.target.setAttribute('data-prev-value', valor);
                     }
                     item.calculate(); // Trigger calculation *after* validation
                 } else {
                     let prevValue = event.target.getAttribute('data-prev-value') || '';
                     event.target.value = prevValue;
                     event.target.classList.add('is-invalid');

                     // Clear associated output fields and reset their state to required/editable
                     if (item.ss) item.ss.value = '';
                     if (item.pr) item.pr.value = '';
                     if (item.interp) item.interp.value = '';
                     if (item.ss) item.ss.readOnly = false;
                     if (item.pr) item.pr.readOnly = false;
                     if (item.interp) item.interp.readOnly = false;
                     if (item.ss) item.ss.classList.remove('auto-filled');
                     if (item.pr) item.pr.classList.remove('auto-filled');
                     if (item.interp) item.interp.classList.remove('auto-filled');
                     if (item.ss) item.ss.setAttribute('required', '');
                     if (item.pr) item.pr.setAttribute('required', '');
                     if (item.interp) item.interp.setAttribute('required', '');


                      if (valor !== '') {
                          Swal.fire({
                             icon: 'warning',
                             title: 'Entrada inválida',
                             text: `"${valor}" no es un número entero válido ni "NA". Por favor, ingrese un número entero positivo o "NA".`
                         });
                      }
                 }
             };

             input.addEventListener('input', validateInput);
              input.addEventListener('change', validateInput);
         } else {
              console.warn(`Raw score input element not found for id: ${item.id}`);
         }
     });


     // Validation for output fields that can be manually filled
     // Including textareas which don't have validate attributes but might be required
     document.querySelectorAll('input.input-field[validate="escalar"]:not([readonly]), input.input-field[validate="percentil"]:not([readonly]), textarea.input-field:not([readonly])').forEach(function(input) {
         // Ensure the element exists before adding listener
         if (!input) return;

          input.setAttribute('data-prev-value', input.value.trim());

          input.addEventListener('input', function(event) {
              if (!event.target.readOnly) {
                 let valor = event.target.value.trim();
                 event.target.classList.remove('is-invalid');

                 let isValid = true;
                 const validationType = event.target.getAttribute('validate'); // Will be null for textareas

                 if (validationType === 'escalar') {
                     // Permite cadena vacía, números enteros del 0 al 19, 'NA', etc.
                     if (!/^(1[0-9]|[0-9]|NA|Na|na|N\/A|n\/a)?$/i.test(valor)) {
                         isValid = false;
                     }
                 } else if (validationType === 'percentil') {
                      // Permite cadena vacía, 0-100 con/sin decimal, <, NA, etc.
                     if (!/^(100(\.0+)?|[1-9]?\d(\.\d*)?|0(\.\d+)?|N|A|NA|na|N\/A|n\/a|<|<0\.1|<0|<0\.)?$/i.test(valor)) {
                           isValid = false;
                     } else {
                           if (valor.indexOf('.') !== valor.lastIndexOf('.') && valor.indexOf('.') !== -1) {
                               isValid = false; // Multiple decimal points
                           }
                     }
                 }
                 // No specific format validation for textareas, just content presence handled by form submit check

                 if (isValid) {
                    event.target.setAttribute('data-prev-value', valor);
                 } else {
                     let prevValue = event.target.getAttribute('data-prev-value') || '';
                     event.target.value = prevValue;
                     event.target.classList.add('is-invalid');
                      if (valor !== '') {
                          Swal.fire({
                             icon: 'warning',
                             title: 'Entrada inválida',
                             text: `"${valor}" no es un valor válido para este campo. Por favor, corrija el formato.`
                         });
                      }
                 }
              }
         });

         input.addEventListener('change', function(event) {
              if (!event.target.readOnly) {
                  let valor = event.target.value.trim();
                  event.target.classList.remove('is-invalid');
                   let isValid = true;
                   const validationType = event.target.getAttribute('validate');

                  if (validationType === 'escalar') {
                     if (!/^(1[0-9]|[0-9]|NA|Na|na|N\/A|n\/a)?$/i.test(valor)) {
                         isValid = false;
                     }
                 } else if (validationType === 'percentil') {
                     if (!/^(100(\.0+)?|[1-9]?\d(\.\d*)?|0(\.\d+)?|N|A|NA|na|N\/A|n\/a|<|<0\.1|<0|<0\.)?$/i.test(valor)) {
                          isValid = false;
                     } else {
                           if (valor.indexOf('.') !== valor.lastIndexOf('.') && valor.indexOf('.') !== -1) {
                               isValid = false;
                           }
                     }
                 }

                  if (!isValid && valor !== '') {
                       let prevValue = event.target.getAttribute('data-prev-value') || '';
                       event.target.value = prevValue;
                       event.target.classList.add('is-invalid');
                       Swal.fire({
                           icon: 'warning',
                           title: 'Entrada inválida',
                           text: `"${valor}" no es un valor válido para este campo. Por favor, corrija el formato.`
                       });
                  } else {
                        event.target.setAttribute('data-prev-value', valor);
                  }
              }
         });
     });


     // Function to check required fields before submitting the form
     function verificarForm(event) {
        const form = document.getElementById('myForm');
        if (!form) {
             console.error("Form element not found!");
             event.preventDefault(); // Stop submit if form isn't found
             return;
        }

        const requiredFields = form.querySelectorAll('[required]:not([type="button"])');

        let allValid = true;
        let firstInvalidField = null;

        requiredFields.forEach(field => {
            const value = (field.type === 'text' || field.tagName === 'TEXTAREA' || field.type === 'date') ? field.value.trim() : field.value;

            if (!value) {
                allValid = false;
                field.classList.add('is-invalid');
                if (!firstInvalidField) {
                    firstInvalidField = field;
                }
            } else {
                 field.classList.remove('is-invalid');
            }
        });

        // Additional check for raw score inputs that should have triggered outputs, but didn't
         rawScoreInputs.forEach(item => {
              // Ensure elements exist
              const rawInput = document.getElementById(item.id);
              const ssElement = document.getElementById(item.ss.id);
              const prElement = document.getElementById(item.pr.id);
              const interpElement = document.getElementById(item.interp.id);

              if (!rawInput || !ssElement || !prElement || !interpElement) {
                  console.warn(`Missing elements for raw score input check: ${item.id}`);
                  return; // Skip check for this item if elements are missing
              }


             const rawValue = rawInput.value.trim().toUpperCase();
             // If raw is numeric and outputs are empty, mark outputs as invalid
             if (rawValue !== '' && rawValue !== 'NA' && !isNaN(parseInt(rawInput.value.trim(), 10)) &&
                 (ssElement.value.trim() === '' || prElement.value.trim() === '' || interpElement.value.trim() === '')) {

                 allValid = false;
                  if (ssElement.value.trim() === '') ssElement.classList.add('is-invalid');
                  if (prElement.value.trim() === '') prElement.classList.add('is-invalid');
                  if (interpElement.value.trim() === '') interpElement.classList.add('is-invalid');

                 if (!firstInvalidField) {
                     firstInvalidField = rawInput; // Point to the raw input that caused the issue
                 }
             } else {
                   // Ensure invalid class is removed if outputs now have values or raw is NA/empty
                    ssElement.classList.remove('is-invalid');
                    prElement.classList.remove('is-invalid');
                    interpElement.classList.remove('is-invalid');
             }
         });


        if (!allValid) {
            event.preventDefault(); // Prevent form submission
            Swal.fire({
                icon: 'error',
                title: 'Campos incompletos o inválidos',
                text: 'Por favor, complete o corrija todos los campos obligatorios y asegúrese de que las puntuaciones estándar, percentiles e interpretación se calculen correctamente o se ingresen manualmente si es necesario.'
            }).then(() => {
                if (firstInvalidField) {
                    firstInvalidField.scrollIntoView({ behavior: 'smooth', block: 'center' });
                    firstInvalidField.focus();
                }
            });
        }
     }

    // Attach the verification listener to the form's 'submit' event
    const myForm = document.getElementById('myForm');
    if (myForm) {
        myForm.removeEventListener('submit', verificarForm); // Defensive
        myForm.addEventListener('submit', verificarForm);
    } else {
         console.error("Form with id 'myForm' not found!");
    }


     // --- Initial state setup on page load ---
     // This runs when the DOM is ready
     function setInitialOutputState(rawInputId, ssOutputId, prOutputId, interpOutputId) {
         const rawInput = document.getElementById(rawInputId);
         const ssOutput = document.getElementById(ssOutputId);
         const prOutput = document.getElementById(prOutputId);
         const interpOutput = document.getElementById(interpOutputId);

         // Check if elements exist
         if (!rawInput || !ssOutput || !prOutput || !interpOutput) {
             console.warn(`Missing elements for initial state check: ${rawInputId}, ${ssOutputId}, ${prOutputId}, ${interpOutputId}`);
             return;
         }

         const rawValue = rawInput.value.trim();
         const ssValue = ssOutput.value.trim();
         const prValue = prOutput.value.trim();
         const interpValue = interpOutput.value.trim();

         // If the raw score is 'NA' or empty, output fields should be editable and not required (if NA) or required (if empty)
          if (rawValue === '' || rawValue.toUpperCase() === 'NA' || rawValue.toUpperCase() === 'N/A') {
             ssOutput.readOnly = false;
             prOutput.readOnly = false;
             interpOutput.readOnly = false;
             ssOutput.classList.remove('auto-filled');
             prOutput.classList.remove('auto-filled');
             interpOutput.classList.remove('auto-filled');

             if (rawValue.toUpperCase() === 'NA' || rawValue.toUpperCase() === 'N/A') {
                 ssOutput.removeAttribute('required');
                 prOutput.removeAttribute('required');
                 interpOutput.removeAttribute('required');
                  // Set value to NA if raw is NA and outputs were empty
                 if (ssValue === '' && prValue === '' && interpValue === '') {
                      ssOutput.value = 'NA';
                      prOutput.value = 'NA';
                      interpOutput.value = 'No administrado o no aplica';
                 }
             } else { // Raw is empty
                 ssOutput.setAttribute('required', '');
                 prOutput.setAttribute('required', '');
                 interpOutput.setAttribute('required', '');
             }
         }
         // If the raw score has a numeric value AND output fields also have values, assume they were auto-filled/saved
         else if (!isNaN(parseInt(rawValue, 10)) && parseInt(rawValue, 10) >= 0 && ssValue !== '' && prValue !== '' && interpValue !== '') {
              ssOutput.readOnly = true;
              prOutput.readOnly = true;
              interpOutput.readOnly = true;
              ssOutput.classList.add('auto-filled');
              prOutput.classList.add('auto-filled');
              interpOutput.classList.add('auto-filled');
              ssOutput.removeAttribute('required'); // Not required if auto-filled
              prOutput.removeAttribute('required');
              interpOutput.removeAttribute('required');
          } else {
             // If the raw score is numeric but output fields are empty or incomplete,
             // make the output fields editable and required for user to fill or recalculate
             ssOutput.readOnly = false;
             prOutput.readOnly = false;
             interpOutput.readOnly = false;
             ssOutput.classList.remove('auto-filled');
             prOutput.classList.remove('auto-filled');
             interpOutput.classList.remove('auto-filled');
             ssOutput.setAttribute('required', '');
             prOutput.setAttribute('required', '');
             interpOutput.setAttribute('required', '');
         }
     }

     // Apply the initial state to each set of fields
     setInitialOutputState('comp_audi_punt_bruta', 'compren_audit_punt_stand', 'compre_audit_rango_percent', 'comp_audit_interpre');
     setInitialOutputState('expre_comuni_puntua_bruta', 'expr_comun_punt_estandar', 'expr_comunic_rango_percent', 'expr_comunic_interpret');
     // TODO: Call for Lenguaje Total when implemented - ensure elements exist first
     if (document.getElementById('leng_tota_punt_bruta')) { // Check if LT elements are in HTML
         setInitialOutputState('leng_tota_punt_bruta', 'leng_tota_punt_standa', 'leng_tota_rang_percent', 'lengua_tot_interpret');
     }


    // Listener to calculate age automatically if both dates are pre-filled (e.g. on page load)
    // This was already correct, just moved inside DOMContentLoaded as it accesses date inputs
    const dob = document.getElementById('fecha_nacimiento_paciente').value;
    const evalDate = document.getElementById('fecha_evaluacion').value;
    if (dob && evalDate) {
        // Use a small timeout to ensure everything else in DOMContentLoaded is ready
        setTimeout(calcular, 0);
    }

    // Event listener for evaluation date change - recalculate age
    const evalDateInput = document.getElementById('fecha_evaluacion');
    if (evalDateInput) {
         evalDateInput.addEventListener('change', calcular); // Recalculate age when eval date changes
    }
    // Event listener for dob change - recalculate age (though dob is readonly in your HTML)
    const dobInput = document.getElementById('fecha_nacimiento_paciente');
     if (dobInput && !dobInput.readOnly) { // Only add listener if DOB is NOT readonly
         dobInput.addEventListener('change', calcular);
     }


}); // End of DOMContentLoaded listener