(function(){
    const L10N = (window.plantshop_wc_shipping_weeks && plantshop_wc_shipping_weeks.l10n) ? plantshop_wc_shipping_weeks.l10n : {};
    function t(key, fallback) {
        return (L10N && L10N[key]) ? L10N[key] : fallback;
    }

    const container = document.getElementById(window.plantshop_wc_shipping_weeks?.helper_id);
    if(!container) return;
    const textarea = document.getElementById(container.dataset.forTextarea);
    const chips = container.querySelector('.plantshop-wc-chips');
    const stats = container.querySelector('.plantshop-wc-stats');
    const errorsBox = container.querySelector('.plantshop-wc-errors');
    const w1 = container.querySelector('.plantshop-wc-w1');
    const w2 = container.querySelector('.plantshop-wc-w2');

    function trimTrailingWhitespace(value) {
        const text = String(value || '');
        let end = text.length;
        while (end > 0) {
            const code = text.codePointAt(end - 1);
            const isWhitespace = code === 32 || code === 9 || code === 10 || code === 13 || code === 12;
            if (!isWhitespace) break;
            end--;
        }
        return end === text.length ? text : text.slice(0, end);
    }

    function getISOWeek(d){
        const date = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));
        const dayNum = date.getUTCDay() || 7;
        date.setUTCDate(date.getUTCDate() + 4 - dayNum);
        const yearStart = new Date(Date.UTC(date.getUTCFullYear(),0,1));
        const weekNo = Math.ceil((((date - yearStart) / 86400000) + 1)/7);
        return {year: date.getUTCFullYear(), week: weekNo};
    }

    // initialize defaults for range inputs (weeks only)
    (function(){
        if(w1 && w2){
            const iso = getISOWeek(new Date());
            w1.value = String(iso.week);
            w2.value = String(Math.min(53, iso.week + 4));
        }
    })();

    function parseLines(src) {
        const lines = src.split(/\r?\n/).map(s => s.trim()).filter(Boolean);
        const weekRe = /^W(\d{1,2})(?:(?:\.\.|-)W(\d{1,2}))?$/i;
        const weeks = new Set();
        const errors = [];
        const invalidLineText = t('invalidLine', 'Invalid line');
        const invalidWeekText = t('invalidWeekNumber', 'Invalid week number');
        const rangeTooLargeText = t('rangeTooLarge', 'Range too large');

        function addWeek(week){
            weeks.add('W' + String(week).padStart(2, '0'));
        }

        function parseWeekOrPushError(rawValue, line) {
            const week = Number.parseInt(rawValue, 10);
            if (week < 1 || week > 53) {
                errors.push(invalidWeekText + ': ' + line);
                return null;
            }
            return week;
        }

        function addRange(startWeek, endWeek, line) {
            let start = startWeek;
            let end = endWeek;
            if (start > end) {
                const tmp = start;
                start = end;
                end = tmp;
            }
            const guard = 60;
            let steps = 0;
            for (let week = start; week <= end; week++) {
                addWeek(week);
                steps++;
                if (steps > guard) {
                    errors.push(rangeTooLargeText + ': ' + line);
                    break;
                }
            }
        }

        function parseLine(line) {
            const match = weekRe.exec(line);
            if (!match) {
                errors.push(invalidLineText);
                return;
            }
            const week1 = parseWeekOrPushError(match[1], line);
            if (week1 === null) {
                return;
            }
            if (match[2] === undefined) {
                addWeek(week1);
                return;
            }
            const week2 = parseWeekOrPushError(match[2], line);
            if (week2 === null) {
                return;
            }
            addRange(week1, week2, line);
        }

        for (let i = 0; i < lines.length; i++) {
            parseLine(lines[i]);
        }
        return {
            weeks: Array.from(weeks).sort(function(a, b){
                return Number.parseInt(a.slice(1), 10) - Number.parseInt(b.slice(1), 10);
            }),
            errors
        };
    }

    function refresh(){
        const {weeks, errors} = parseLines(textarea.value || '');
        chips.innerHTML = weeks.map(w => '<span class="chip">' + w + '</span>').join('');
        stats.textContent = weeks.length ? (t('allowedWeeks', 'Allowed weeks') + ': ' + weeks.length) : t('noWeeksSelected', 'No weeks selected');
        errorsBox.textContent = errors.join('\n');
    }

    function addNextWeeks(n){
        const now = new Date();
        const iso = getISOWeek(now);
        const year = iso.year;
        const start = iso.week;
        function isoWeeksInYear(y){
            const d = new Date(Date.UTC(y, 0, 1));
            const day = d.getUTCDay() || 7;
            if(day === 4) return 53;
            const isLeap = (y%4===0 && (y%100!==0 || y%400===0));
            if(day === 3 && isLeap) return 53;
            return 52;
        }
        const max = isoWeeksInYear(year);
        const pad = (x) => String(x).padStart(2,'0');
        let end = start + n - 1;
        const lines = [];
        if (n <= 1) {
            lines.push('W' + pad(start));
        } else if (end <= max) {
            lines.push('W' + pad(start) + '-W' + pad(end));
        } else {
            const end1 = max;
            const overflow = end - max; // weeks into next year
            const end2 = ((overflow - 1) % 53) + 1; // wrap within 1..53
            lines.push('W' + pad(start) + '-W' + pad(end1));
            lines.push('W01-W' + pad(end2));
        }
        const newText = (textarea.value ? trimTrailingWhitespace(textarea.value) + '\n' : '') + lines.join('\n');
        textarea.value = newText;
        textarea.dispatchEvent(new Event('input', {bubbles:true}));
    }

    function fillCurrentYear(){
        const now = new Date();
        const year = now.getUTCFullYear();
        function isoWeeksInYear(y){
            const d = new Date(Date.UTC(y, 0, 1));
            const day = d.getUTCDay() || 7;
            if(day === 4) return 53;
            const isLeap = (y%4===0 && (y%100!==0 || y%400===0));
            if(day === 3 && isLeap) return 53;
            return 52;
        }
        const max = isoWeeksInYear(year);
        textarea.value = 'W01-W' + String(max).padStart(2,'0');
        textarea.dispatchEvent(new Event('input', {bubbles:true}));
    }

    function normalizeWeekBounds(a, b) {
        const weekA = Math.max(1, Math.min(53, a));
        const weekB = Math.max(1, Math.min(53, b));
        if (weekA <= weekB) {
            return { start: weekA, end: weekB };
        }
        return { start: weekB, end: weekA };
    }

    function appendLineToTextarea(line) {
        const newText = (textarea.value ? trimTrailingWhitespace(textarea.value) + '\n' : '') + line;
        textarea.value = newText;
        textarea.dispatchEvent(new Event('input', {bubbles:true}));
    }

    function handleAddWeeksClick(btn, e) {
        if (addWeeksLock) {
            e.stopImmediatePropagation();
            return;
        }
        addWeeksLock = true;
        addNextWeeks(Number.parseInt(btn.dataset.addWeeks, 10));
        refresh();
        e.stopImmediatePropagation();
        setTimeout(() => { addWeeksLock = false; }, 0);
    }

    function handleAddRangeClick(e) {
        if (addRangeLock) {
            e.stopImmediatePropagation();
            return;
        }
        addRangeLock = true;
        errorsBox.textContent = '';

        const rawW1 = Number.parseInt(w1?.value || '', 10);
        const rawW2 = Number.parseInt(w2?.value || '', 10);
        if (!Number.isInteger(rawW1) || !Number.isInteger(rawW2)) {
            errorsBox.textContent = t('pleaseEnterStartEnd', 'Please enter start and end week (1-53)');
            addRangeLock = false;
            e.stopImmediatePropagation();
            return;
        }

        const bounds = normalizeWeekBounds(rawW1, rawW2);
        const line = bounds.start === bounds.end
            ? ('W' + String(bounds.start).padStart(2, '0'))
            : ('W' + String(bounds.start).padStart(2, '0') + '-W' + String(bounds.end).padStart(2, '0'));
        appendLineToTextarea(line);
        refresh();
        e.stopImmediatePropagation();
        setTimeout(() => { addRangeLock = false; }, 0);
    }

    let addRangeLock = false, addWeeksLock = false;
    container.addEventListener('click', function(e){
        const btn = e.target.closest('button');
        if (!btn) return;
        if (btn.dataset.addWeeks) {
            handleAddWeeksClick(btn, e);
            return;
        }
        if (btn.dataset.fillYear === 'current') {
            fillCurrentYear();
            refresh();
            return;
        }
        if (btn.dataset.clear) {
            textarea.value = '';
            refresh();
            return;
        }
        if (btn.dataset.addRange) {
            handleAddRangeClick(e);
        }
    });

    textarea.addEventListener('input', refresh);
    refresh();
})();

(function(){
    const sel = document.querySelector("select[name=plantshop_shipping_week]");
    const target = document.querySelector(".plantshop-shipping-week-display");
    if(!sel || !target){return;}
    const upd = function(){ const opt = sel.options[sel.selectedIndex]; target.textContent = opt ? opt.text : ""; };
    sel.addEventListener("change", upd);
    document.addEventListener("wc-updated", upd);
})();
