/*!
 * 1MZ Date Picker — JavaScript isolado.
 *
 * @package OneMZ_For_Artists
 * @since   1.5.147
 *
 * Componente standalone (não depende de jQuery).
 * Auto-inicializa-se em DOMContentLoaded e procura todos os
 * elementos com [data-rmbz-dp] na página.
 *
 * IIFE para não poluir o global scope.
 */
( function () {
    'use strict';

    // Apenas 1 modal partilhado por todos os triggers.
    var modal = null;
    var activePicker = null;

    // Estado do calendário interno do modal.
    var calState = {
        year: null,
        month: null,    // 0-11
        selected: null, // YYYY-MM-DD
        minDate: null,  // YYYY-MM-DD
        maxDate: null,  // YYYY-MM-DD
        suggestedDays: 14,
        // [1.5.152] Catálogo legado: legacyAllowed = picker permite, legacyActive = utilizador confirmou
        legacyAllowed: false,
        legacyActive: false
    };

    var MESES_LONG = [
        'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
        'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'
    ];

    var MESES_SHORT = [
        'Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun',
        'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'
    ];

    // ============================================================
    // UTILS — formatação e parsing de datas
    // ============================================================

    function pad2( n ) {
        return n < 10 ? '0' + n : '' + n;
    }

    /**
     * Formata Date → "YYYY-MM-DD" (formato ISO usado no backend).
     */
    function fmtIso( d ) {
        return d.getFullYear() + '-' + pad2( d.getMonth() + 1 ) + '-' + pad2( d.getDate() );
    }

    /**
     * Formata "YYYY-MM-DD" → "25.Jan.2026" (estilo Amadea).
     */
    function fmtPtShort( iso ) {
        var d = parseIso( iso );
        if ( ! d ) return '';
        return pad2( d.getDate() ) + '.' + MESES_SHORT[ d.getMonth() ] + '.' + d.getFullYear();
    }

    /**
     * Formata "YYYY-MM-DD" → "25 de Janeiro de 2026" (longo).
     */
    function fmtPtLong( iso ) {
        var d = parseIso( iso );
        if ( ! d ) return '';
        return d.getDate() + ' de ' + MESES_LONG[ d.getMonth() ] + ' de ' + d.getFullYear();
    }

    /**
     * Parse "YYYY-MM-DD" → Date (timezone-safe).
     */
    function parseIso( iso ) {
        if ( ! iso || typeof iso !== 'string' ) return null;
        var parts = iso.split( '-' );
        if ( parts.length !== 3 ) return null;
        var y = parseInt( parts[0], 10 );
        var m = parseInt( parts[1], 10 );
        var d = parseInt( parts[2], 10 );
        if ( isNaN( y ) || isNaN( m ) || isNaN( d ) ) return null;
        var date = new Date( y, m - 1, d );
        date.setHours( 0, 0, 0, 0 );
        if ( isNaN( date.getTime() ) ) return null;
        return date;
    }

    /**
     * Devolve "hoje" às 00:00 (timezone-safe).
     */
    function today() {
        var d = new Date();
        d.setHours( 0, 0, 0, 0 );
        return d;
    }

    /**
     * Calcula data sugerida = hoje + N dias.
     */
    function calcSuggested( days ) {
        var d = today();
        d.setDate( d.getDate() + days );
        return d;
    }

    /**
     * Compara dois ISO dates: -1, 0, 1.
     */
    function cmpIso( a, b ) {
        if ( a < b ) return -1;
        if ( a > b ) return 1;
        return 0;
    }

    // ============================================================
    // CALENDÁRIO — renderização da grelha
    // ============================================================

    /**
     * Popula os <select> de mês e ano com as opções.
     * [1.5.153] Range de anos depende de:
     *   - default: hoje-5 ... hoje+5
     *   - se legacyAllowed: hoje-50 ... hoje+5 (catálogo antigo pode ir muito atrás)
     *   - min/max date podem expandir ainda mais
     * Re-popula sempre que chamada (idempotente, limpa antes).
     */
    function populateSelects() {
        var monthSel = modal.querySelector( '[data-rmbz-dp-month]' );
        var yearSel  = modal.querySelector( '[data-rmbz-dp-year]' );
        if ( ! monthSel || ! yearSel ) return;

        // Meses: popular só se vazio (não muda)
        if ( monthSel.options.length === 0 ) {
            for ( var m = 0; m < 12; m++ ) {
                var opt = document.createElement( 'option' );
                opt.value = m;
                opt.textContent = MESES_LONG[ m ];
                monthSel.appendChild( opt );
            }
        }

        // Anos: re-popular sempre (range pode mudar quando legacy é activado)
        var now = today();
        var startYear, endYear;

        if ( calState.legacyAllowed ) {
            // [1.5.156] Catálogo antigo: limite inferior 1999 (era da música digital).
            // Mais antigo que isto raramente faz sentido para distribuição.
            startYear = 1999;
            endYear   = now.getFullYear() + 5;
        } else {
            // Modo normal: 5 anos para trás (raramente útil) e 5 para a frente
            startYear = now.getFullYear() - 5;
            endYear   = now.getFullYear() + 5;
        }

        // Expandir range se min/max forçarem (mas nunca mais para trás que 1999 em legacy)
        if ( calState.minDate ) {
            var minD = parseIso( calState.minDate );
            if ( minD && minD.getFullYear() < startYear ) startYear = minD.getFullYear();
        }
        if ( calState.maxDate ) {
            var maxD = parseIso( calState.maxDate );
            if ( maxD && maxD.getFullYear() > endYear ) endYear = maxD.getFullYear();
        }
        // Limite duro inferior: 1999 (catálogo digital)
        if ( startYear < 1999 ) startYear = 1999;

        // Limpar e re-popular
        yearSel.innerHTML = '';
        for ( var y = endYear; y >= startYear; y-- ) {  // ordem decrescente: ano actual no topo
            var yopt = document.createElement( 'option' );
            yopt.value = y;
            yopt.textContent = y;
            yearSel.appendChild( yopt );
        }
    }

    /**
     * Sincroniza os selects com calState.year/month.
     */
    function syncSelects() {
        var monthSel = modal.querySelector( '[data-rmbz-dp-month]' );
        var yearSel  = modal.querySelector( '[data-rmbz-dp-year]' );
        if ( monthSel ) monthSel.value = calState.month;
        if ( yearSel )  yearSel.value  = calState.year;
    }

    /**
     * Renderiza a grelha de dias para o mês actual de calState.
     */
    function renderGrid() {
        var grid = modal.querySelector( '[data-rmbz-dp-grid]' );
        if ( ! grid ) return;

        grid.innerHTML = '';

        var year  = calState.year;
        var month = calState.month;
        var firstDay = new Date( year, month, 1 );
        var lastDay  = new Date( year, month + 1, 0 );
        var startWeekday = firstDay.getDay(); // 0 = Dom
        var daysInMonth  = lastDay.getDate();

        var todayIso = fmtIso( today() );
        var minIso   = calState.minDate || null;
        var maxIso   = calState.maxDate || null;
        var selIso   = calState.selected || null;

        // [1.5.154] Autodetecção: se o picker permite legacy E o mês inteiro
        // visível está antes do minDate, activar modo legacy silenciosamente.
        // Isto evita o caso onde utilizador navega para 2007 e vê todos os
        // dias bloqueados sem saber porquê.
        if ( calState.legacyAllowed && ! calState.legacyActive && minIso ) {
            var lastDayIso = fmtIso( lastDay );
            if ( cmpIso( lastDayIso, minIso ) < 0 ) {
                // Todo o mês visível é anterior ao mínimo → activar legacy auto
                calState.legacyActive = true;
                hideLegacyPrompt();
                showLegacyInfo();   // [1.5.155] Sinalizar que legacy foi activado
                grid.classList.add( 'rmbz-dp-cal-grid-legacy' );
                if ( activePicker ) activePicker.classList.add( 'rmbz-dp-legacy-mode' );
            }
        }

        // Dias do mês anterior (preenchimento da 1ª linha)
        var prevMonthLastDay = new Date( year, month, 0 ).getDate();
        for ( var i = startWeekday - 1; i >= 0; i-- ) {
            var dayNum = prevMonthLastDay - i;
            var prevDate = new Date( year, month - 1, dayNum );
            var prevIso  = fmtIso( prevDate );
            grid.appendChild( buildDayBtn( dayNum, prevIso, true, todayIso, minIso, maxIso, selIso ) );
        }

        // Dias do mês actual
        for ( var d = 1; d <= daysInMonth; d++ ) {
            var curDate = new Date( year, month, d );
            var curIso  = fmtIso( curDate );
            grid.appendChild( buildDayBtn( d, curIso, false, todayIso, minIso, maxIso, selIso ) );
        }

        // Dias do mês seguinte (preenchimento até completar 6 linhas)
        var totalCells = grid.children.length;
        var remaining  = ( 7 - ( totalCells % 7 ) ) % 7;
        for ( var n = 1; n <= remaining; n++ ) {
            var nextDate = new Date( year, month + 1, n );
            var nextIso  = fmtIso( nextDate );
            grid.appendChild( buildDayBtn( n, nextIso, true, todayIso, minIso, maxIso, selIso ) );
        }
    }

    /**
     * Cria um botão de dia.
     */
    function buildDayBtn( dayNum, iso, otherMonth, todayIso, minIso, maxIso, selIso ) {
        var btn = document.createElement( 'button' );
        btn.type = 'button';
        btn.className = 'rmbz-dp-cal-day';
        btn.textContent = dayNum;
        btn.setAttribute( 'data-iso', iso );

        if ( otherMonth ) {
            btn.classList.add( 'rmbz-dp-cal-day-other-month' );
        }
        if ( iso === todayIso ) {
            btn.classList.add( 'rmbz-dp-cal-day-today' );
        }
        if ( selIso && iso === selIso ) {
            btn.classList.add( 'rmbz-dp-cal-day-selected' );
        }

        // Verificar se está fora do min/max permitido
        var beforeMin = minIso && cmpIso( iso, minIso ) < 0;
        var afterMax  = maxIso && cmpIso( iso, maxIso ) > 0;
        var disabled  = beforeMin || afterMax;

        // [1.5.152] Se legacy está ACTIVO, datas anteriores ao min são permitidas.
        // (datas posteriores ao max continuam sempre proibidas)
        if ( disabled && calState.legacyActive && beforeMin && ! afterMax ) {
            disabled = false;
        }

        if ( disabled ) {
            btn.disabled = true;
        }

        btn.addEventListener( 'click', function ( e ) {
            // [1.5.152] Click em data desabilitada por ser ANTES do min:
            // se o picker permite legacy, mostrar caixa amarela.
            // Se já passar (max ultrapassado), não mostra (data futura excessiva é sempre erro).
            if ( btn.disabled ) {
                if ( calState.legacyAllowed && ! calState.legacyActive && beforeMin && ! afterMax ) {
                    showLegacyPrompt( iso );
                }
                return;
            }
            calState.selected = iso;
            hideLegacyPrompt();
            // Se clicou em "outro mês", saltar para esse mês
            var dParts = iso.split( '-' );
            calState.year  = parseInt( dParts[0], 10 );
            calState.month = parseInt( dParts[1], 10 ) - 1;
            syncSelects();
            renderGrid();
        } );

        return btn;
    }

    // ============================================================
    // [1.5.152] CATÁLOGO LEGADO — mostrar/esconder caixa amarela
    // ============================================================

    /**
     * Pendente de selecção quando utilizador carrega numa data passada.
     * Guardado para aplicar quando confirma "Sim, é catálogo antigo".
     */
    var pendingLegacyIso = null;

    function showLegacyPrompt( iso ) {
        var prompt = modal.querySelector( '[data-rmbz-dp-legacy-prompt]' );
        if ( ! prompt ) return;
        pendingLegacyIso = iso || null;
        prompt.removeAttribute( 'hidden' );
    }

    function hideLegacyPrompt() {
        var prompt = modal.querySelector( '[data-rmbz-dp-legacy-prompt]' );
        if ( ! prompt ) return;
        prompt.setAttribute( 'hidden', '' );
    }

    // [1.5.155] Caixa info verde — sinalização quando legacy auto-activa
    function showLegacyInfo() {
        var info = modal.querySelector( '[data-rmbz-dp-legacy-info]' );
        if ( ! info ) return;
        info.removeAttribute( 'hidden' );
    }

    function hideLegacyInfo() {
        var info = modal.querySelector( '[data-rmbz-dp-legacy-info]' );
        if ( ! info ) return;
        info.setAttribute( 'hidden', '' );
    }

    /**
     * Activa o modo legacy: liberta datas passadas no calendário,
     * pré-selecciona a data que o utilizador estava a tentar clicar.
     */
    function activateLegacyMode() {
        calState.legacyActive = true;

        // Se havia uma data pendente, seleccioná-la e navegar até ela
        if ( pendingLegacyIso ) {
            calState.selected = pendingLegacyIso;
            var d = parseIso( pendingLegacyIso );
            if ( d ) {
                calState.year  = d.getFullYear();
                calState.month = d.getMonth();
            }
            pendingLegacyIso = null;
        }

        hideLegacyPrompt();
        showLegacyInfo();   // [1.5.155] Mostra confirmação verde após activar

        // Marca CSS no grid para visualizar que datas passadas agora são clicáveis
        var grid = modal.querySelector( '[data-rmbz-dp-grid]' );
        if ( grid ) grid.classList.add( 'rmbz-dp-cal-grid-legacy' );

        // Marca o picker para indicar visualmente
        if ( activePicker ) activePicker.classList.add( 'rmbz-dp-legacy-mode' );

        syncSelects();
        renderGrid();
    }

    function resetLegacyMode() {
        calState.legacyActive = false;
        pendingLegacyIso = null;
        hideLegacyPrompt();
        hideLegacyInfo();   // [1.5.155]
        var grid = modal.querySelector( '[data-rmbz-dp-grid]' );
        if ( grid ) grid.classList.remove( 'rmbz-dp-cal-grid-legacy' );
    }

    // ============================================================
    // MODAL — abrir, fechar, escrever valor
    // ============================================================

    function openModal( picker ) {
        if ( ! modal ) return;
        activePicker = picker;

        // Carregar config do trigger para o calState
        calState.suggestedDays = parseInt(
            picker.getAttribute( 'data-suggested-days' ) || '14', 10
        );
        calState.minDate = picker.getAttribute( 'data-min-date' ) || null;
        calState.maxDate = picker.getAttribute( 'data-max-date' ) || null;

        // [1.5.152] Reset estado legacy a cada abertura
        calState.legacyAllowed = picker.getAttribute( 'data-allow-legacy' ) === '1';
        calState.legacyActive  = false;
        pendingLegacyIso = null;
        hideLegacyPrompt();
        hideLegacyInfo();   // [1.5.155]
        var grid0 = modal.querySelector( '[data-rmbz-dp-grid]' );
        if ( grid0 ) grid0.classList.remove( 'rmbz-dp-cal-grid-legacy' );

        // Valor actual: o hidden de valor é o que NÃO é legacy flag
        var hidden = picker.querySelector( 'input[type="hidden"]:not(.rmbz-dp-legacy-flag)' );
        if ( ! hidden ) {
            // Fallback: primeiro hidden
            hidden = picker.querySelector( 'input[type="hidden"]' );
        }
        var current = ( hidden && hidden.value ) ? hidden.value : null;

        // [1.5.152] Se o picker já está em modo legacy (vindo do servidor),
        // activar logo o modo na abertura (sem prompt)
        var legacyHidden = picker.querySelector( '.rmbz-dp-legacy-flag' );
        if ( legacyHidden && legacyHidden.value === '1' ) {
            calState.legacyActive = true;
            if ( grid0 ) grid0.classList.add( 'rmbz-dp-cal-grid-legacy' );
            showLegacyInfo();   // [1.5.155]
        }

        if ( current ) {
            calState.selected = current;
            var d = parseIso( current );
            if ( d ) {
                calState.year  = d.getFullYear();
                calState.month = d.getMonth();
            }
        } else {
            calState.selected = null;
            var sug = calcSuggested( calState.suggestedDays );
            calState.year  = sug.getFullYear();
            calState.month = sug.getMonth();
        }

        // Mostrar sugestão na coluna esquerda
        var sugDateEl = modal.querySelector( '[data-rmbz-dp-suggested]' );
        if ( sugDateEl ) {
            sugDateEl.textContent = fmtPtShort( fmtIso( calcSuggested( calState.suggestedDays ) ) );
        }

        // Re-popular selects (caso min/max tenham mudado)
        populateSelects();
        syncSelects();
        renderGrid();

        modal.removeAttribute( 'hidden' );
        document.body.classList.add( 'rmbz-dp-open' );
    }

    function closeModal() {
        if ( ! modal ) return;
        modal.setAttribute( 'hidden', '' );
        document.body.classList.remove( 'rmbz-dp-open' );
        activePicker = null;
    }

    /**
     * Escreve o valor no hidden + actualiza display do trigger.
     * [1.5.152] Também escreve na flag legacy se modo legacy estiver activo.
     */
    function applyValue( iso ) {
        if ( ! activePicker || ! iso ) return;

        // Hidden de valor (NÃO o de legacy)
        var hidden  = activePicker.querySelector( 'input[type="hidden"]:not(.rmbz-dp-legacy-flag)' );
        if ( ! hidden ) {
            hidden = activePicker.querySelector( 'input[type="hidden"]' );
        }

        var legacyHidden = activePicker.querySelector( '.rmbz-dp-legacy-flag' );
        var trigger      = activePicker.querySelector( '.rmbz-dp-trigger' );
        var textEl       = activePicker.querySelector( '.rmbz-dp-trigger-text' );

        if ( hidden ) {
            hidden.value = iso;
            try {
                hidden.dispatchEvent( new Event( 'input',  { bubbles: true } ) );
                hidden.dispatchEvent( new Event( 'change', { bubbles: true } ) );
            } catch ( e ) { /* IE fallback ignored */ }
        }

        // [1.5.152] Escrever flag legacy
        if ( legacyHidden ) {
            legacyHidden.value = calState.legacyActive ? '1' : '';
            try {
                legacyHidden.dispatchEvent( new Event( 'change', { bubbles: true } ) );
            } catch ( e ) {}
        }

        if ( trigger ) {
            trigger.classList.remove( 'rmbz-dp-trigger-empty' );
        }

        if ( textEl ) {
            // Se for legacy, prepender ícone discreto para o utilizador saber
            textEl.textContent = ( calState.legacyActive ? '⏳ ' : '' ) + fmtPtShort( iso );
        }

        closeModal();
    }

    // ============================================================
    // EVENT HANDLERS — delegação no modal
    // ============================================================

    function handleAction( e ) {
        var actionEl = e.target.closest( '[data-rmbz-dp-action]' );
        if ( ! actionEl ) return;

        var action = actionEl.getAttribute( 'data-rmbz-dp-action' );

        // [1.5.152] Confirmar catálogo antigo — liberta datas passadas
        if ( action === 'confirm-legacy' ) {
            activateLegacyMode();
            return;
        }

        if ( action === 'use-suggested' ) {
            applyValue( fmtIso( calcSuggested( calState.suggestedDays ) ) );
            return;
        }

        if ( action === 'use-selected' ) {
            if ( ! calState.selected ) {
                // Avisar (sem alert intrusivo — só shake do calendário)
                var grid = modal.querySelector( '[data-rmbz-dp-grid]' );
                if ( grid ) {
                    grid.style.outline = '2px solid #ef4444';
                    setTimeout( function () { grid.style.outline = ''; }, 1500 );
                }
                return;
            }
            applyValue( calState.selected );
            return;
        }

        if ( action === 'prev-month' ) {
            calState.month--;
            if ( calState.month < 0 ) {
                calState.month = 11;
                calState.year--;
            }
            syncSelects();
            renderGrid();
            return;
        }

        if ( action === 'next-month' ) {
            calState.month++;
            if ( calState.month > 11 ) {
                calState.month = 0;
                calState.year++;
            }
            syncSelects();
            renderGrid();
            return;
        }
    }

    function handleClose( e ) {
        var closeEl = e.target.closest( '[data-rmbz-dp-close]' );
        if ( closeEl ) closeModal();
    }

    function handleSelectChange() {
        var monthSel = modal.querySelector( '[data-rmbz-dp-month]' );
        var yearSel  = modal.querySelector( '[data-rmbz-dp-year]' );
        if ( monthSel ) calState.month = parseInt( monthSel.value, 10 );
        if ( yearSel )  calState.year  = parseInt( yearSel.value, 10 );
        renderGrid();
    }

    // ============================================================
    // INIT
    // ============================================================

    function init() {
        modal = document.getElementById( 'rmbz-dp-modal' );
        if ( ! modal ) return; // Sem modal renderizado, nada a fazer

        // Event delegation no modal
        modal.addEventListener( 'click', function ( e ) {
            handleAction( e );
            handleClose( e );
        } );

        // Selects de mês/ano
        var monthSel = modal.querySelector( '[data-rmbz-dp-month]' );
        var yearSel  = modal.querySelector( '[data-rmbz-dp-year]' );
        if ( monthSel ) monthSel.addEventListener( 'change', handleSelectChange );
        if ( yearSel )  yearSel.addEventListener(  'change', handleSelectChange );

        // Escape para fechar
        document.addEventListener( 'keydown', function ( e ) {
            if ( e.key === 'Escape' && ! modal.hasAttribute( 'hidden' ) ) {
                closeModal();
            }
        } );

        // Listeners nos triggers
        var pickers = document.querySelectorAll( '[data-rmbz-dp]' );
        pickers.forEach( function ( picker ) {
            var trigger = picker.querySelector( '.rmbz-dp-trigger' );
            if ( ! trigger ) return;
            trigger.addEventListener( 'click', function ( e ) {
                e.preventDefault();
                openModal( picker );
            } );
        } );
    }

    if ( document.readyState === 'loading' ) {
        document.addEventListener( 'DOMContentLoaded', init );
    } else {
        init();
    }

} )();
