( function () {
    'use strict';

    function parseNum( value ) {
        if ( ! value ) { return 0; }
        value = String( value ).trim();
        if ( value.indexOf( ',' ) !== -1 ) {
            value = value.replace( /\./g, '' ).replace( ',', '.' );
        }
        value = value.replace( /[^0-9.\-]/g, '' );
        var n = parseFloat( value );
        return isNaN( n ) ? 0 : n;
    }

    function formatMoney( n ) {
        return n.toLocaleString( 'de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 2 } );
    }

    function getJSON( id ) {
        var el = document.getElementById( id );
        if ( ! el ) { return {}; }
        try { return JSON.parse( el.textContent ); } catch ( e ) { return {}; }
    }

    function getCatalog() { return getJSON( 'ag-price-catalog' ); }
    function getI18n() { return getJSON( 'ag-i18n-data' ); }

    function currentUnit() {
        var sel = document.querySelector( 'select[name="ag[unit]"]' );
        return sel ? sel.value : 'hl';
    }

    function currentDocLang() {
        var sel = document.getElementById( 'ag-doc-language' );
        return sel ? sel.value : 'ES';
    }

    /* ---- Betragsberechnung ---- */
    function rowDiscPct( row ) {
        var courseSel = row.querySelector( '.ag-course' );
        if ( ! courseSel || ! courseSel.value ) { return 0; }
        var course = getCatalog()[ courseSel.value ];
        if ( ! course ) { return 0; }
        var unit = currentUnit();
        var tiers = ( unit === 'h' ) ? ( course.disc_h || [] ) : ( course.disc_hl || [] );
        var units = parseNum( ( row.querySelector( '.ag-units' ) || {} ).value || '' );
        for ( var i = 0; i < tiers.length; i++ ) {
            var t = tiers[ i ];
            if ( units >= t[ 0 ] && ( t[ 1 ] === null || units <= t[ 1 ] ) ) { return t[ 2 ]; }
        }
        return 0;
    }

    function recalcRow( row ) {
        var price = parseNum( row.querySelector( '.ag-price' ) ? row.querySelector( '.ag-price' ).value : 0 );
        var units = parseNum( row.querySelector( '.ag-units' ) ? row.querySelector( '.ag-units' ).value : 0 );
        var amount = price * units;
        var amountField = row.querySelector( '.ag-amount' );
        if ( amountField ) { amountField.value = amount ? formatMoney( amount ) : ''; }

        // Mengenrabatt der Position (auf 2 Nachkommastellen gerundet)
        var pct = rowDiscPct( row );
        var disc = pct > 0 ? Math.round( ( amount * pct / 100 ) * 100 ) / 100 : 0;
        var discEl = row.querySelector( '.ag-row-disc' );
        if ( discEl ) {
            discEl.textContent = ( pct > 0 && amount > 0 )
                ? '· Mengenrabatt ' + pct + '% = ' + formatMoney( disc ) + ' EUR'
                : '';
        }
        return { amount: amount, disc: disc };
    }

    var agDiscountManual = false;

    function recalcAll() {
        var rows = document.querySelectorAll( '#ag-items .ag-item-row' );
        var sum = 0, autoDisc = 0;
        rows.forEach( function ( row ) {
            var r = recalcRow( row );
            sum += r.amount;
            autoDisc += r.disc;
        } );
        autoDisc = Math.round( autoDisc * 100 ) / 100;

        var discountField = document.querySelector( '.ag-discount' );
        if ( discountField && ! agDiscountManual ) {
            discountField.value = autoDisc > 0 ? formatMoney( autoDisc ) : '';
        }
        var discount = discountField ? parseNum( discountField.value ) : 0;
        var total = Math.max( 0, sum - discount );
        var sumEl = document.getElementById( 'ag-sum' );
        var totalEl = document.getElementById( 'ag-total' );
        if ( sumEl ) { sumEl.textContent = formatMoney( sum ) + ' EUR'; }
        if ( totalEl ) { totalEl.textContent = formatMoney( total ) + ' EUR'; }
    }

    /* ---- Concepto-Satz live zusammenbauen (Spiegel von AG_I18n::compose_concept) ---- */
    function ymdToDisplay( ymd ) {
        if ( ! ymd ) { return ''; }
        var m = /^(\d{4})-(\d{2})-(\d{2})$/.exec( ymd );
        return m ? ( m[3] + '.' + m[2] + '.' + m[1] ) : ymd;
    }

    function weekdayPhrase( row, i18n, lang ) {
        var checked = [];
        row.querySelectorAll( '.ag-c-weekday:checked' ).forEach( function ( c ) { checked.push( parseInt( c.value, 10 ) ); } );
        if ( ! checked.length ) { return ''; }
        var order = [ 1, 2, 3, 4, 5, 6, 0 ];
        var names = ( i18n.weekdays && i18n.weekdays[ lang ] ) ? i18n.weekdays[ lang ] : {};
        var words = [];
        order.forEach( function ( n ) {
            if ( checked.indexOf( n ) !== -1 && names[ n ] ) { words.push( names[ n ] ); }
        } );
        if ( ! words.length ) { return ''; }
        var conj = ( i18n.wd_conj && i18n.wd_conj[ lang ] ) ? i18n.wd_conj[ lang ] : ' y ';
        var prefix = ( i18n.wd_prefix && i18n.wd_prefix[ lang ] !== undefined ) ? i18n.wd_prefix[ lang ] : 'los ';
        var joined;
        if ( words.length === 1 ) { joined = words[ 0 ]; }
        else {
            var last = words.pop();
            joined = words.join( ', ' ) + conj + last;
        }
        return prefix + joined;
    }

    function composeConcept( row ) {
        var i18n = getI18n();
        var lang = currentDocLang();
        var taughtSel = row.querySelector( '.ag-c-taught' );
        var taught = taughtSel ? taughtSel.value : '';
        var idioma = ( i18n.taught && i18n.taught[ lang ] && i18n.taught[ lang ][ taught ] ) ? i18n.taught[ lang ][ taught ] : taught;

        var motivo = ( row.querySelector( '.ag-c-motivo' ) || {} ).value || '';
        var sessions = ( row.querySelector( '.ag-c-sessions' ) || {} ).value || '';
        var duration = ( row.querySelector( '.ag-c-duration' ) || {} ).value || '';
        var unit = currentUnit();
        var from = ymdToDisplay( ( row.querySelector( '.ag-c-from' ) || {} ).value || '' );
        var to = ymdToDisplay( ( row.querySelector( '.ag-c-to' ) || {} ).value || '' );
        var modSel = row.querySelector( '.ag-c-modality' );
        var modCode = modSel ? modSel.value : '';
        var modality = ( i18n.modality && i18n.modality[ lang ] && i18n.modality[ lang ][ modCode ] ) ? i18n.modality[ lang ][ modCode ] : '';
        var wd = weekdayPhrase( row, i18n, lang );

        motivo = motivo.trim(); sessions = sessions.trim(); duration = duration.trim();
        var s;
        if ( lang === 'EN' ) {
            s = 'Private ' + idioma + ' lessons';
            if ( motivo ) { s += ' - ' + motivo; }
            if ( sessions ) { s += ', ' + sessions + ' session(s) per week'; }
            if ( wd ) { s += sessions ? ' (' + wd + ')' : ', ' + wd; }
            if ( duration ) { s += ' of ' + duration + ' ' + unit + ' each'; }
            if ( from && to ) { s += ', from ' + from + ' to ' + to; }
            s += '.';
            if ( modality ) { s += ' Format: ' + modality + '.'; }
        } else if ( lang === 'DE' ) {
            s = idioma + '-Privatunterricht';
            if ( motivo ) { s += ' - ' + motivo; }
            if ( sessions ) { s += ', ' + sessions + ' Einheit(en) pro Woche'; }
            if ( wd ) { s += sessions ? ' (' + wd + ')' : ', ' + wd; }
            if ( duration ) { s += ' a ' + duration + ' ' + unit; }
            if ( from && to ) { s += ', vom ' + from + ' bis ' + to; }
            s += '.';
            if ( modality ) { s += ' Format: ' + modality + '.'; }
        } else {
            s = 'Clases particulares de ' + idioma;
            if ( motivo ) { s += ' - ' + motivo; }
            if ( sessions ) { s += ', ' + sessions + ' sesion(es) por semana'; }
            if ( wd ) { s += sessions ? ' (' + wd + ')' : ', ' + wd; }
            if ( duration ) { s += ' de ' + duration + ' ' + unit + ' cada una'; }
            if ( from && to ) { s += ', del ' + from + ' al ' + to; }
            s += '.';
            if ( modality ) { s += ' Modalidad: ' + modality + '.'; }
        }
        return s;
    }

    function hasParts( row ) {
        var sel = [ '.ag-c-motivo', '.ag-c-sessions', '.ag-c-duration', '.ag-c-from', '.ag-c-to' ];
        for ( var k = 0; k < sel.length; k++ ) {
            var f = row.querySelector( sel[ k ] );
            if ( f && f.value.trim() !== '' ) { return true; }
        }
        var mod = row.querySelector( '.ag-c-modality' );
        if ( mod && mod.value !== '' ) { return true; }
        if ( row.querySelector( '.ag-c-weekday:checked' ) ) { return true; }
        return false;
    }

    function updatePreview( row ) {
        var previewEl = row.querySelector( '.ag-concept-preview-text' );
        if ( ! previewEl ) { return; }
        var manual = row.querySelector( '.ag-concept' );
        if ( manual && manual.value.trim() !== '' ) {
            previewEl.textContent = manual.value.trim() + '  (manueller Text)';
        } else if ( hasParts( row ) ) {
            previewEl.textContent = composeConcept( row );
        } else {
            previewEl.textContent = '-';
        }
    }

    /* ---- Kursart uebernehmen (Preis-Prefill) ---- */
    function applyCourse( row ) {
        var courseSel = row.querySelector( '.ag-course' );
        if ( ! courseSel || ! courseSel.value ) { return; }
        var course = getCatalog()[ courseSel.value ];
        if ( ! course ) { return; }
        var unit = currentUnit();
        var price = ( unit === 'h' ) ? course.h : course.hl;
        var priceField = row.querySelector( '.ag-price' );
        if ( priceField && price != null ) {
            priceField.value = String( price ).replace( '.', ',' );
        }
        // Kalendertyp automatisch setzen: kj_* = Kinder & Jugendliche
        var calSel = row.querySelector( '.ag-c-calendar' );
        if ( calSel ) {
            calSel.value = ( courseSel.value.indexOf( 'kj_' ) === 0 ) ? 'kids' : 'adults';
        }
        recalcAll();
    }

    /* ---- Enddatum-Berechnung (Feiertage/Schulferien) ---- */
    function getCalendarData() { return getJSON( 'ag-calendar-data' ); }

    function fmtYmd( d ) {
        var m = ( d.getMonth() + 1 ), day = d.getDate();
        return d.getFullYear() + '-' + ( m < 10 ? '0' : '' ) + m + '-' + ( day < 10 ? '0' : '' ) + day;
    }

    function computeEndDate( row ) {
        var resBox = row.querySelector( '.ag-cal-result' );
        function say( msg, isError ) {
            if ( resBox ) {
                resBox.style.display = 'block';
                resBox.textContent = msg;
                resBox.className = 'ag-cal-result' + ( isError ? ' ag-cal-error' : '' );
            }
        }

        var fromField = row.querySelector( '.ag-c-from' );
        var start = fromField ? fromField.value : '';
        if ( ! start ) { say( 'Bitte zuerst ein Startdatum (Del) wählen.', true ); return; }

        var weekdays = [];
        row.querySelectorAll( '.ag-c-weekday:checked' ).forEach( function ( c ) { weekdays.push( parseInt( c.value, 10 ) ); } );
        if ( ! weekdays.length ) { say( 'Bitte mindestens einen Wochentag anhaken.', true ); return; }

        var units = parseNum( ( row.querySelector( '.ag-units' ) || {} ).value || '' );
        var duration = parseNum( ( row.querySelector( '.ag-c-duration' ) || {} ).value || '' );
        if ( units <= 0 ) { say( 'Bitte zuerst die Unidades (Gesamt-Einheiten) eintragen.', true ); return; }
        var sessions = Math.ceil( units / ( duration > 0 ? duration : 1 ) );

        var calType = ( row.querySelector( '.ag-c-calendar' ) || {} ).value || 'adults';
        var cal = getCalendarData();
        var holidays = {};
        ( cal.holidays || [] ).forEach( function ( h ) { holidays[ h ] = true; } );
        var ranges = ( calType === 'kids' ) ? ( cal.school_ranges || [] ) : [];

        var d = new Date( start + 'T12:00:00' );
        if ( isNaN( d.getTime() ) ) { say( 'Startdatum ungültig.', true ); return; }

        var count = 0, skippedHol = 0, skippedVac = 0, guard = 0, lastYmd = null;
        while ( count < sessions && guard < 3000 ) {
            if ( weekdays.indexOf( d.getDay() ) !== -1 ) {
                var ymd = fmtYmd( d );
                var inVacation = false;
                for ( var r = 0; r < ranges.length; r++ ) {
                    if ( ymd >= ranges[ r ][ 0 ] && ymd <= ranges[ r ][ 1 ] ) { inVacation = true; break; }
                }
                if ( holidays[ ymd ] ) { skippedHol++; }
                else if ( inVacation ) { skippedVac++; }
                else { count++; lastYmd = ymd; }
            }
            d.setDate( d.getDate() + 1 );
            guard++;
        }

        if ( ! lastYmd ) { say( 'Keine Termine berechenbar – bitte Eingaben prüfen.', true ); return; }

        var toField = row.querySelector( '.ag-c-to' );
        if ( toField ) { toField.value = lastYmd; toField.dispatchEvent( new Event( 'change' ) ); }

        // Sesiones/Woche mit Anzahl gewählter Wochentage vorbelegen, falls leer
        var sessField = row.querySelector( '.ag-c-sessions' );
        if ( sessField && sessField.value.trim() === '' ) {
            sessField.value = String( weekdays.length );
        }

        var parts = [ sessions + ' Termine' ];
        if ( skippedHol ) { parts.push( skippedHol + ' Feiertag(e) übersprungen' ); }
        if ( skippedVac ) { parts.push( skippedVac + ' Ferientag(e) übersprungen' ); }
        var pretty = lastYmd.split( '-' );
        say( 'Enddatum: ' + pretty[ 2 ] + '.' + pretty[ 1 ] + '.' + pretty[ 0 ] + ' — ' + parts.join( ', ' ) + '.' );
        updatePreview( row );
    }

    /* ---- Umgekehrt: Unidades aus Start-/Enddatum berechnen ---- */
    function computeUnits( row ) {
        var resBox = row.querySelector( '.ag-cal-result' );
        function say( msg, isError ) {
            if ( resBox ) {
                resBox.style.display = 'block';
                resBox.textContent = msg;
                resBox.className = 'ag-cal-result' + ( isError ? ' ag-cal-error' : '' );
            }
        }

        var start = ( row.querySelector( '.ag-c-from' ) || {} ).value || '';
        var end   = ( row.querySelector( '.ag-c-to' ) || {} ).value || '';
        if ( ! start || ! end ) { say( 'Bitte Start- (Del) und Enddatum (Al) wählen.', true ); return; }
        if ( end < start ) { say( 'Das Enddatum liegt vor dem Startdatum.', true ); return; }

        var weekdays = [];
        row.querySelectorAll( '.ag-c-weekday:checked' ).forEach( function ( c ) { weekdays.push( parseInt( c.value, 10 ) ); } );
        if ( ! weekdays.length ) { say( 'Bitte mindestens einen Wochentag anhaken.', true ); return; }

        var duration = parseNum( ( row.querySelector( '.ag-c-duration' ) || {} ).value || '' );
        if ( duration <= 0 ) { duration = 1; }

        var calType = ( row.querySelector( '.ag-c-calendar' ) || {} ).value || 'adults';
        var cal = getCalendarData();
        var holidays = {};
        ( cal.holidays || [] ).forEach( function ( h ) { holidays[ h ] = true; } );
        var ranges = ( calType === 'kids' ) ? ( cal.school_ranges || [] ) : [];

        var d = new Date( start + 'T12:00:00' );
        if ( isNaN( d.getTime() ) ) { say( 'Startdatum ungültig.', true ); return; }

        var sessions = 0, skippedHol = 0, skippedVac = 0, guard = 0;
        while ( fmtYmd( d ) <= end && guard < 3000 ) {
            if ( weekdays.indexOf( d.getDay() ) !== -1 ) {
                var ymd = fmtYmd( d );
                var inVacation = false;
                for ( var r = 0; r < ranges.length; r++ ) {
                    if ( ymd >= ranges[ r ][ 0 ] && ymd <= ranges[ r ][ 1 ] ) { inVacation = true; break; }
                }
                if ( holidays[ ymd ] ) { skippedHol++; }
                else if ( inVacation ) { skippedVac++; }
                else { sessions++; }
            }
            d.setDate( d.getDate() + 1 );
            guard++;
        }

        if ( sessions <= 0 ) { say( 'Im gewählten Zeitraum liegt kein Termin – bitte Eingaben prüfen.', true ); return; }

        var units = Math.round( sessions * duration * 100 ) / 100;
        var unitsField = row.querySelector( '.ag-units' );
        if ( unitsField ) {
            unitsField.value = String( units ).replace( '.', ',' );
        }

        // Sesiones/Woche vorbelegen, falls leer
        var sessField = row.querySelector( '.ag-c-sessions' );
        if ( sessField && sessField.value.trim() === '' ) {
            sessField.value = String( weekdays.length );
        }

        var parts = [ sessions + ' Termine × ' + String( duration ).replace( '.', ',' ) + ' ' + currentUnit() + ' = ' + String( units ).replace( '.', ',' ) + ' ' + currentUnit() ];
        if ( skippedHol ) { parts.push( skippedHol + ' Feiertag(e) übersprungen' ); }
        if ( skippedVac ) { parts.push( skippedVac + ' Ferientag(e) übersprungen' ); }
        say( 'Unidades: ' + String( units ).replace( '.', ',' ) + ' — ' + parts.join( ', ' ) + '.' );

        recalcAll();
        updatePreview( row );
    }

    /* ---- Reindex + Attach ---- */
    function reindexRows() {
        var rows = document.querySelectorAll( '#ag-items .ag-item-row' );
        rows.forEach( function ( row, i ) {
            row.querySelectorAll( 'input, textarea, select' ).forEach( function ( field ) {
                if ( field.name ) {
                    field.name = field.name.replace( /ag\[items\]\[\d+\]/, 'ag[items][' + i + ']' );
                }
            } );
            var nr = row.querySelector( '.ag-item-nr' );
            if ( nr ) { nr.textContent = 'Position ' + ( i + 1 ); }
        } );
    }

    function attachRow( row ) {
        row.querySelectorAll( '.ag-price, .ag-units' ).forEach( function ( f ) {
            f.addEventListener( 'input', recalcAll );
        } );
        var courseSel = row.querySelector( '.ag-course' );
        if ( courseSel ) {
            courseSel.addEventListener( 'change', function () { applyCourse( row ); } );
        }
        var computeBtn = row.querySelector( '.ag-c-compute' );
        if ( computeBtn ) {
            computeBtn.addEventListener( 'click', function () { computeEndDate( row ); } );
        }
        var computeUnitsBtn = row.querySelector( '.ag-c-compute-units' );
        if ( computeUnitsBtn ) {
            computeUnitsBtn.addEventListener( 'click', function () { computeUnits( row ); } );
        }
        row.querySelectorAll( '.ag-c-taught, .ag-c-motivo, .ag-c-sessions, .ag-c-duration, .ag-c-from, .ag-c-to, .ag-c-modality, .ag-concept' ).forEach( function ( f ) {
            var ev = ( f.tagName === 'SELECT' || f.type === 'date' ) ? 'change' : 'input';
            f.addEventListener( ev, function () { updatePreview( row ); } );
        } );
        row.querySelectorAll( '.ag-c-weekday' ).forEach( function ( c ) {
            c.addEventListener( 'change', function () { updatePreview( row ); } );
        } );
        var rm = row.querySelector( '.ag-remove' );
        if ( rm ) {
            rm.addEventListener( 'click', function () {
                var rows = document.querySelectorAll( '#ag-items .ag-item-row' );
                if ( rows.length > 1 ) {
                    row.parentNode.removeChild( row );
                } else {
                    row.querySelectorAll( 'input, textarea' ).forEach( function ( f ) {
                        if ( f.type === 'checkbox' ) { f.checked = false; } else { f.value = ''; }
                    } );
                    row.querySelectorAll( 'select' ).forEach( function ( f ) { f.selectedIndex = 0; } );
                    var rb2 = row.querySelector( '.ag-cal-result' );
                    if ( rb2 ) { rb2.style.display = 'none'; rb2.textContent = ''; }
                }
                reindexRows();
                recalcAll();
            } );
        }
        updatePreview( row );
    }

    document.addEventListener( 'DOMContentLoaded', function () {
        var container = document.getElementById( 'ag-items' );
        if ( ! container ) { return; }

        container.querySelectorAll( '.ag-item-row' ).forEach( attachRow );

        var discountField = document.querySelector( '.ag-discount' );
        if ( discountField ) {
            // Vorbelegter Wert (gespeichertes Angebot) gilt als manuell gesetzt.
            if ( discountField.value.trim() !== '' && parseNum( discountField.value ) !== 0 ) {
                agDiscountManual = true;
            }
            discountField.addEventListener( 'input', function () {
                agDiscountManual = ( discountField.value.trim() !== '' );
                recalcAll();
            } );
        }

        var unitSel = document.querySelector( 'select[name="ag[unit]"]' );
        if ( unitSel ) {
            unitSel.addEventListener( 'change', function () {
                container.querySelectorAll( '.ag-item-row' ).forEach( function ( row ) {
                    var cs = row.querySelector( '.ag-course' );
                    if ( cs && cs.value ) { applyCourse( row ); }
                    updatePreview( row );
                } );
            } );
        }

        var docLangSel = document.getElementById( 'ag-doc-language' );
        if ( docLangSel ) {
            docLangSel.addEventListener( 'change', function () {
                container.querySelectorAll( '.ag-item-row' ).forEach( updatePreview );
            } );
        }

        var addBtn = document.getElementById( 'ag-add-row' );
        if ( addBtn ) {
            addBtn.addEventListener( 'click', function () {
                var rows = container.querySelectorAll( '.ag-item-row' );
                var last = rows[ rows.length - 1 ];
                var clone = last.cloneNode( true );
                clone.querySelectorAll( 'input, textarea' ).forEach( function ( f ) {
                    if ( f.type === 'checkbox' ) { f.checked = false; } else { f.value = ''; }
                } );
                clone.querySelectorAll( 'select' ).forEach( function ( f ) { f.selectedIndex = 0; } );
                var rb = clone.querySelector( '.ag-cal-result' );
                if ( rb ) { rb.style.display = 'none'; rb.textContent = ''; }
                container.appendChild( clone );
                reindexRows();
                attachRow( clone );
                recalcAll();
            } );
        }

        recalcAll();
    } );
}() );
