
// ============================================================
// 서브경로 호스팅 — fetch wrapper
// 모든 /api/* 호출에 APP_BASE_PATH 를 prepend, 401 응답 시 dbx-main 로그인으로 이동.
// ============================================================
(function () {
    const APP_BASE_PATH = (window.APP_BASE_PATH || '').replace(/\/$/, '');
    const origFetch = window.fetch.bind(window);
    window.fetch = async function (input, init) {
        if (typeof input === 'string' && APP_BASE_PATH && input.startsWith('/api/')) {
            input = APP_BASE_PATH + input;
        }
        const response = await origFetch(input, init);
        if (response.status === 401) {
            // 세션 만료 — dbx-main 로그인으로 위임 (next 로 현재 위치 보존)
            const next = encodeURIComponent((APP_BASE_PATH || '') + window.location.pathname + window.location.search);
            window.location.href = (APP_BASE_PATH || '') + '/login?next=' + next;
        }
        return response;
    };
})();

function showToast(message) {
    const toast = document.createElement('div');
    toast.textContent = message;
    toast.style.position = 'fixed';
    toast.style.bottom = '20px';
    toast.style.left = '50%';
    toast.style.transform = 'translateX(-50%)';
    toast.style.background = 'rgba(0, 0, 0, 0.7)';
    toast.style.color = '#fff';
    toast.style.padding = '8px 16px';
    toast.style.borderRadius = '4px';
    toast.style.zIndex = '9999';
    toast.style.fontSize = '0.9rem';
    toast.style.transition = 'opacity 0.3s ease';
    document.body.appendChild(toast);
    setTimeout(() => {
        toast.style.opacity = '0';
        setTimeout(() => toast.remove(), 300);
    }, 1500);
}
function formatShortDate(dateStr) {
    if (!dateStr) return "";
    const d = new Date(dateStr);
    if (isNaN(d)) return dateStr;
    const days = ["일", "월", "화", "수", "목", "금", "토"];
    const m = String(d.getMonth() + 1).padStart(2, "0");
    const day = String(d.getDate()).padStart(2, "0");
    const dow = days[d.getDay()];
    return `${m}월 ${day}일(${dow})`;
}

document.addEventListener('DOMContentLoaded', () => {
    // Tab switching logic
    const navLinks = document.querySelectorAll('.nav-links li');
    const tabContents = document.querySelectorAll('.tab-content');

    navLinks.forEach(link => {
        link.addEventListener('click', () => {
            navLinks.forEach(l => l.classList.remove('active'));
            tabContents.forEach(c => c.classList.remove('active'));

            link.classList.add('active');
            const target = link.getAttribute('data-tab');
            document.getElementById(target).classList.add('active');

            if (target === 'order-tab') {
                const estExtra = document.getElementById('setting-ship-extra');
                const lblObj = document.getElementById('lbl-ship-extra');
                if (estExtra && lblObj) {
                    let valStr = estExtra.value.replace(/,/g, '');
                    let val = valStr ? parseInt(valStr, 10) : 0;
                    if (!isNaN(val)) {
                        lblObj.textContent = '추가배송비 ' + val.toLocaleString() + '원';
                    }
                }
            } else if (target === 'code-tab') {
                if (typeof window.reRenderSetItemsForWrap === 'function') {
                    window.reRenderSetItemsForWrap();
                }
            }
        });
    });

    // Auto format phone number
    document.getElementById('cust-phone').addEventListener('input', function (e) {
        let val = this.value.replace(/[^0-9]/g, '');
        if (val.length > 0 && val[0] !== '0') {
            val = '010' + val;
        }
        let res = '';
        if (val.startsWith('02')) {
            if (val.length < 3) res = val;
            else if (val.length < 6) res = val.replace(/(\d{2})(\d+)/, '$1-$2');
            else if (val.length < 10) res = val.replace(/(\d{2})(\d{3})(\d+)/, '$1-$2-$3');
            else res = val.replace(/(\d{2})(\d{4})(\d{4})/, '$1-$2-$3');
        } else {
            if (val.length < 4) res = val;
            else if (val.length < 7) res = val.replace(/(\d{3})(\d+)/, '$1-$2');
            else if (val.length < 11) res = val.replace(/(\d{3})(\d{3})(\d+)/, '$1-$2-$3');
            else res = val.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3');
        }
        this.value = res;
    });

    async function handleClipboardPaste(targetField) {
        try {
            if (!navigator.clipboard || !navigator.clipboard.readText) {
                alert("현재 환경에서는 클립보드 연동 보안 정책으로 인해 자동 입력이 지원되지 않습니다.\\nHTTPS 상태일 때 동작합니다.\\n직접 붙여넣기(Ctrl+V)를 사용해주세요.");
                return;
            }
            const text = await navigator.clipboard.readText();
            const trimmed = text.trim();
            const digits = text.replace(/[^0-9]/g, '');
            const hasPhone = digits.length >= 9 && digits.length <= 12;
            
            // 이름은 한글 2~5글자를 인식하도록 완화
            const nameMatch = trimmed.match(/^[가-힣]{2,5}/);
            
            if (targetField === 'phone') {
                const phoneInput = document.getElementById('cust-phone');
                if (hasPhone) {
                    phoneInput.value = digits;
                    phoneInput.dispatchEvent(new Event('input'));
                }
            } else if (targetField === 'name') {
                const nameInput = document.getElementById('cust-name');
                if (nameMatch) {
                    nameInput.value = nameMatch[0];
                }
            }
        } catch (err) {
            console.error("Clipboard read error:", err);
            alert("클립보드 접근 권한이 없거나 읽어오지 못했습니다. 브라우저 주소창의 권한을 확인해주세요.");
        }
    }

    document.getElementById('cust-phone').addEventListener('click', function (e) {
        if (!this.value) handleClipboardPaste('phone');
    });

    document.getElementById('cust-name').addEventListener('click', function (e) {
        if (!this.value) handleClipboardPaste('name');
    });

    const pointInput = document.getElementById('sms-point-deduction');
    if (pointInput) {
        pointInput.addEventListener('input', function(e) {
            let val = this.value.replace(/[^0-9]/g, '');
            this.value = val ? parseInt(val, 10).toLocaleString() : '';
        });
    }

    // Global Data
    let configData = {};

    // Fetch configuration
    fetch('/api/config')
        .then(res => res.json())
        .then(data => {
            configData = data;

            if (data.APP_SETTINGS && data.APP_SETTINGS.font) {
                document.body.style.fontFamily = `"${data.APP_SETTINGS.font}", 'Inter', 'Malgun Gothic', sans-serif`;
            } else {
                document.body.style.fontFamily = '';
            }

            buildOrderTab(data);
            buildGiftTab(data);
            if (typeof buildProductTab === 'function') {
                buildProductTab(data);
            }
            loadSmsHistory();
            if (typeof loadManualHistory === 'function') {
                loadManualHistory();
            }
        })
        .catch(err => console.error("Error loading config:", err));



    // Fetch local fonts using hybrid approach (Browser API first, Backend API fallback)
    async function initLocalFonts() {
        const fontSelect = document.getElementById('app-font-select');
        if (!fontSelect) return;

        let fontNames = [];

        try {
            // Attempt to fetch via native browser API (works on HTTPS/localhost for all PC fonts)
            if ('queryLocalFonts' in window && window.isSecureContext) {
                const localFonts = await window.queryLocalFonts();
                fontNames = [...new Set(localFonts.map(f => f.family))].sort();
            } else {
                throw new Error("Local font API not available or context not secure");
            }
        } catch (e) {
            console.warn("내 컴퓨터 폰트 직접 읽기 실패, 서버 폰트로 대체:", e);
            try {
                // Fallback to server registry (works locally without HTTPS but fails to get windows fonts on Linux cloud)
                const res = await fetch('/api/fonts');
                fontNames = await res.json();
            } catch (err) {
                console.error("서버 폰트 불러오기 실패:", err);
            }
        }

        fontSelect.innerHTML = '<option value="">기본 폰트 (선택 없음)</option>';

        if (fontNames && fontNames.length > 0) {
            // 명시적으로 호스팅된 폰트 추가
            const customFonts = ['NanumSquareNeo', 'Pretendard-Regular'];
            customFonts.forEach(f => {
                if (!fontNames.includes(f)) fontNames.unshift(f);
            });
            // 중복 제거 및 정렬
            fontNames = [...new Set(fontNames)].sort((a, b) => {
                const aIsCustom = customFonts.includes(a);
                const bIsCustom = customFonts.includes(b);
                if (aIsCustom && bIsCustom) return customFonts.indexOf(a) - customFonts.indexOf(b);
                if (aIsCustom) return -1;
                if (bIsCustom) return 1;
                return a.localeCompare(b);
            });

            fontNames.forEach(f => {
                const opt = document.createElement('option');
                opt.value = f;

                // Truncate display text to prevent native dropdowns from becoming excessively wide
                let displayText = f;
                if (displayText.length > 35) {
                    displayText = displayText.substring(0, 35) + '...';
                }
                opt.textContent = displayText;

                // Set the font family so users can preview the font in the dropdown
                opt.style.fontFamily = `"${f}", sans-serif`;
                fontSelect.appendChild(opt);
            });

            if (configData.APP_SETTINGS && configData.APP_SETTINGS.font) {
                fontSelect.value = configData.APP_SETTINGS.font;
            }
        } else {
            fontSelect.innerHTML = '<option value="">폰트를 불러오지 못했습니다</option>';
        }
    }

    const btnFontDefault = document.getElementById('btn-font-default');
    if (btnFontDefault) {
        btnFontDefault.addEventListener('click', () => {
            const fontSelect = document.getElementById('app-font-select');
            if (fontSelect) fontSelect.value = '';
            document.getElementById('btn-gift-save').style.backgroundColor = '#e53e3e';
        });
    }

    // Initialize fonts
    initLocalFonts();

    // ============================================
    // BUILD ORDER TAB
    // ============================================
    
    document.getElementById('order-items-container').addEventListener('change', function(e) {
        if (e.target.classList.contains('qty-order') && e.target.tagName === 'SELECT' && e.target.value === 'manual') {
            const input = document.createElement('input');
            input.type = 'number';
            input.min = '1';
            input.value = '1';
            input.className = 'qty-order';
            
            e.target.replaceWith(input);
            input.focus();
            input.select();
        }
    });

    document.getElementById('order-items-container').addEventListener('blur', function(e) {
        if (e.target.classList.contains('qty-order') && e.target.tagName === 'INPUT') {
            if (!e.target.value) {
                const select = document.createElement('select');
                select.className = 'qty-order';
                const qtyOpts = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 20, 30, 40, 50];
                const optHtml = qtyOpts.map(q => `<option value="${q}">${q}</option>`).join('');
                const manualOpt = `<option value="manual" style="background-color: black; color: white;">직접입력</option>`;
                select.innerHTML = manualOpt + optHtml;
                select.value = '1';
                e.target.replaceWith(select);
            } else if (parseInt(e.target.value) < 1) {
                e.target.value = '1';
            }
        }
    }, true);
    function buildOrderTab(data) {
        const container = document.getElementById('order-items-container');
        let sections = [];
        if (data.GROUP_NAMES) {

            const order_gn = data.GROUP_NAMES.__order || Object.keys(data.GROUP_NAMES).filter(k => k !== '__order');
            for (const key of order_gn) {
                if (key === '__order') continue;
                const title = data.GROUP_NAMES[key];

                sections.push({
                    key: key, title: title

                });
            }
        } else {
            // Fallback for older config files without GROUP_NAMES
            sections = [
                { key: 'ORDER_SINGLE_1', title: '단품 아이템 (1)' },
                { key: 'ORDER_SINGLE_2', title: '단품 아이템 (2)' },
                { key: 'ORDER_SET_1', title: '세트 아이템 (1)' },
                { key: 'ORDER_SET_2', title: '세트 아이템 (2)' },
                { key: 'ORDER_EVENT_1', title: '이벤트 (1)' },
                { key: 'ORDER_EVENT_2', title: '이벤트 (2)' },
                { key: 'ORDER_GIFT', title: '사은품' }
            ];
        }


        sections.forEach(sec => {
            if (!data[sec.key]) return;
            const card = document.createElement('div');
            card.className = 'glass-card item-group-card';

            const title = document.createElement('h3');
            title.textContent = sec.title;
            card.appendChild(title);

            const grid = document.createElement('div');
            grid.className = 'item-list';

            const order_1 = data[sec.key]?.__order || Object.keys(data[sec.key]).filter(k => k !== '__order');
            order_1.forEach(rawLabel => {
                if (rawLabel === '__order') return;
                const value = data[sec.key][rawLabel];
                let label = rawLabel.trim();

                if (label.startsWith('---')) {
                    const hr = document.createElement('hr');
                    hr.style.gridColumn = "1 / -1";
                    hr.style.border = "none";
                    hr.style.borderTop = "1.5px dashed black";
                    hr.style.margin = "8px 0";
                    grid.appendChild(hr);
                    return;
                }

                let colorStyle = '';
                const match = label.match(/_([ORBGP])$/i);
                if (match) {
                    label = label.slice(0, -2).trim();
                    const colorMap = { 'O': '#ed8936', 'R': '#e53e3e', 'B': '#3182ce', 'G': '#1D6F42', 'P': '#d53f8c' };
                    colorStyle = `color: ${colorMap[match[1].toUpperCase()]}; font-weight: 700;`;
                }

                const safeValue = value || "";
                const parts = safeValue.split('|').map(s => s.trim());
                let code = parts[0] || "NONE";

                let multiplier = 1;
                const matchCode = code.match(/_(\d+)$/);
                if (matchCode) {
                    multiplier = parseInt(matchCode[1], 10) || 1;
                    code = code.replace(/_\d+$/, '');
                }

                const isFree = label.startsWith('*');
                if (isFree) {
                    label = label.replace(/^\*/, '').trim();
                }

                let name = label;
                if (parts.length > 1 && parts[1] !== "") {
                    name = parts[1];
                }

                let cost = 0;
                let dcost = "null";
                if (parts.length > 2 && parts[2] !== "") {
                    cost = parseInt(parts[2].replace(/,/g, '')) || 0;
                    dcost = parts.length > 3 && parts[3] !== "" ? parseInt(parts[3].replace(/,/g, '')) : "null";
                }

                const row = document.createElement('div');
                row.className = 'item-row';

                let itemType = sec.key;

                const qtyOpts = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 20, 30, 40, 50];
                const optHtml = qtyOpts.map(q => `<option value="${q}"${q === 1 ? ' selected' : ''}>${q}</option>`).join('');
                const manualOpt = `<option value="manual" style="background-color: black; color: white;">직접입력</option>`;

                row.innerHTML = `
                    <label style="${colorStyle}" title="${label}">
                        <input type="checkbox" class="chk-order" data-code="${code}" data-name="${name}" data-label="${label}" data-type="${itemType}" data-cost="${cost}" data-dcost="${dcost}" data-is-free="${isFree}" data-multiplier="${multiplier}">
                        ${label}
                    </label>
                    <select class="qty-order">${manualOpt}${optHtml}</select>
                `;
                grid.appendChild(row);

                row.querySelector('input[type="checkbox"]').addEventListener('change', updateOrderNoLidState);


            });

            card.appendChild(grid);
            container.appendChild(card);


        });

        // Event listeners for config checks
        document.getElementById('sms-discount').addEventListener('change', e => {
            if (e.target.checked) document.getElementById('sms-june-promo').checked = false;
            if (e.target.checked) {
                document.getElementById('sms-coupon').disabled = true;
            } else {
                document.getElementById('sms-coupon').disabled = false;
            }
        });
        document.getElementById('sms-coupon').addEventListener('change', e => {
            if (e.target.checked) {
                document.getElementById('sms-discount').disabled = true;
            } else {
                document.getElementById('sms-discount').disabled = false;
            }
        });
        document.getElementById('sms-june-promo').addEventListener('change', e => {
            if (e.target.checked) document.getElementById('sms-discount').checked = false;
        });
        document.getElementById('sms-ship-free').addEventListener('change', e => {
            // No need to handle old static shipping checkboxes
        });
    }

    function updateOrderNoLidState() {
        const checked = Array.from(document.querySelectorAll('.chk-order:checked'));
        const noLidChk = document.getElementById('chk-no-lid');
        if (checked.length === 0) {
            noLidChk.disabled = true;
            noLidChk.checked = false;
            return;
        }

        const canEnable = checked.every(chk => chk.dataset.type === 'ORDER_SINGLE');
        noLidChk.disabled = !canEnable;
        if (!canEnable) noLidChk.checked = false;
    }


    // ============================================
    // ORDER ACTIONS
    // ============================================
    function getCouponDiscount(amount) {
        if (amount >= 220000) return 25000;
        if (amount >= 150000) return 15000;
        if (amount >= 100000) return 10000;
        if (amount >= 70000) return 5000;
        if (amount >= 50000) return 3000;
        if (amount >= 30000) return 2000;
        return 0;
    }
    function getOrderPayload(excludedIndices = []) {
        const items = [];
        let totalCost = 0;
        let hasMarkedFreeShipping = false;

        document.querySelectorAll('.chk-order:checked').forEach((chk, idx) => {
            const row = chk.closest('.item-row');
            const qty = parseInt(row.querySelector('.qty-order').value) || 1;
            const multiplier = parseInt(chk.dataset.multiplier) || 1;
            const orderLabel = chk.dataset.label;

            items.push({
                code: chk.dataset.code,
                name: chk.dataset.name,
                label: orderLabel,
                item_type: chk.dataset.type,
                quantity: qty * multiplier


            });

            const cost = parseInt(chk.dataset.cost) || 0;
            const dcost = chk.dataset.dcost === "null" ? null : (parseInt(chk.dataset.dcost) || null);

            let itemTotal = 0;
            if (dcost !== null && qty >= 3) {
                itemTotal = Math.floor(qty / 3) * dcost * 2 + (qty % 3) * cost;
            } else {
                itemTotal = cost * qty;
            }
            
            const orderType = document.querySelector('input[name="order-type"]:checked').value;
            const noLidChecked = document.getElementById('chk-no-lid').checked;
            if (orderType === 'noolak' || orderType === 'pason' || orderType === 'bullyang' || noLidChecked) {
                itemTotal = 0;
            }
            
            if (!excludedIndices.includes(idx)) {
                totalCost += itemTotal;
                if (chk.dataset.isFree === "true") hasMarkedFreeShipping = true;
            }


        });

        // 🟢 금액별 추가 상품 체킹 시 사은품 자동 탑재
        if (document.getElementById('sms-june-promo').checked && configData['SMS_GIFT_RULES']) {
            let seen = new Set();
            for (let i = 1; i <= 4; i++) {
                const sMin = configData['SMS_GIFT_RULES'][`condition${i}_min`];
                const sMax = configData['SMS_GIFT_RULES'][`condition${i}_max`];
                const sGiftStr = configData['SMS_GIFT_RULES'][`condition${i}_gift`];
                if (!sGiftStr) continue;

                const minV = sMin ? parseInt(sMin) : 0;
                const maxV = sMax ? parseInt(sMax) : null;

                if (totalCost >= minV && (maxV === null || totalCost < maxV)) {
                    if (!seen.has(sGiftStr)) {
                        seen.add(sGiftStr);

                        let foundCode = 'ZZ-0000';
                        let foundName = sGiftStr;
                        let cleanLabel = sGiftStr.trim();
                        if (cleanLabel.match(/_([ORBGP])$/i)) cleanLabel = cleanLabel.slice(0, -2).trim();

                        for (const secKey of Object.keys(configData)) {
                            if (secKey === 'SMS_PRICING' || secKey === 'SMS_GIFT_RULES' || secKey === 'GROUP_NAMES') continue;
                            if (configData[secKey][sGiftStr]) {
                                const parts = configData[secKey][sGiftStr].split('|').map(s => s.trim());
                                foundCode = parts[0];
                                foundName = parts.length > 1 ? parts[1] : cleanLabel;
                                break;
                            }
                        }

                        items.push({
                            code: foundCode,
                            name: foundName,
                            label: cleanLabel,
                            item_type: 'event',
                            quantity: 1


                        });
                    }
                }
            }
        }

        let baseShippingVal = parseInt((configData.APP_SETTINGS && configData.APP_SETTINGS.shipping_fee) ? configData.APP_SETTINGS.shipping_fee : 3500);
        let extraShippingVal = parseInt((configData.APP_SETTINGS && configData.APP_SETTINGS.extra_shipping_fee) ? configData.APP_SETTINGS.extra_shipping_fee : 3000);
        
        let pointDeduction = parseInt(document.getElementById('sms-point-deduction').value.replace(/,/g, '')) || 0;

        let totalAfterDiscount = totalCost;
        let discount5Amount = 0;
        let couponAmount = 0;
        if (document.getElementById('sms-coupon').checked) {
            couponAmount = getCouponDiscount(totalCost);
        }
        if (document.getElementById('sms-discount').checked) {
            totalAfterDiscount = Math.floor((totalCost * 0.95) / 10) * 10;
            discount5Amount = totalCost - totalAfterDiscount;
        }
        if (couponAmount > 0) {
            totalAfterDiscount = Math.max(0, totalAfterDiscount - couponAmount);
        }
        if (pointDeduction > 0) {
            totalAfterDiscount = Math.max(0, totalAfterDiscount - pointDeduction);
        }

        let isAutoFree = totalAfterDiscount >= 50000;
        let isManualFree = document.getElementById('sms-ship-free').checked;
        let isFreeShip = hasMarkedFreeShipping || isAutoFree || isManualFree;

        let shippingCost = 0;
        let freeReason = "";
        if (!isFreeShip) {
            shippingCost = baseShippingVal;
        } else {
            if (isAutoFree) freeReason = "5만원 이상";
            else if (isManualFree) freeReason = "수동배송무료";
            else if (hasMarkedFreeShipping) freeReason = "무료배송상품";
            else freeReason = "무료";
        }
        
        let extraShippingCost = 0;
        if (document.getElementById('sms-ship-extra').checked) {
            extraShippingCost = extraShippingVal;
            if (isFreeShip) freeReason += " / 도서산간 추가";
        }
        
        const currentOrderType = document.querySelector('input[name="order-type"]:checked').value;
        if (currentOrderType === 'noolak' || currentOrderType === 'pason' || currentOrderType === 'bullyang') {
            shippingCost = 0;
            extraShippingCost = 0;
        }

        let finalPayable = totalAfterDiscount + shippingCost + extraShippingCost;

        return {
            customer_name: document.getElementById('cust-name').value.trim(),
            address: document.getElementById('cust-address').value.trim(),
            phone: document.getElementById('cust-phone').value.trim(),
            comment: "",
            order_type: document.querySelector('input[name="order-type"]:checked').value,
            no_lid: document.getElementById('chk-no-lid').checked,
            items: items,
            total_amount: finalPayable,
            raw_total: totalCost,
            discount_amount: discount5Amount + couponAmount,
            discount_5_amount: discount5Amount,
            coupon_amount: couponAmount,
            point_deduction: pointDeduction,
            shipping_cost: shippingCost,
            extra_shipping_cost: extraShippingCost,
            free_reason: freeReason
        };
    }

    let currentSubmitContext = null;

    function submitOrder(url, isEllen = false) {
        const tempPayload = getOrderPayload();
        tempPayload.is_ellen = isEllen;

        if (tempPayload.items.length === 0) {
            alert("발주 아이템을 선택해주세요."); return;
        }

        if (url.includes('submit')) {
            if (!tempPayload.customer_name) {
                alert("이름 항목이 누락되었습니다. 입력해주세요.");
                return;
            }
            if (!tempPayload.phone) {
                alert("연락처 항목이 누락되었습니다. 입력해주세요.");
                return;
            }
            if (!tempPayload.address) {
                alert("주소 항목이 누락되었습니다. 입력해주세요.");
                return;
            }
        }

        // Setup modal
        const listContainer = document.getElementById('exclude-items-list');
        listContainer.innerHTML = '';
        
        const updateTotalDisplay = () => {
            const excludedIndices = Array.from(document.querySelectorAll('.exclude-chk:checked')).map(c => parseInt(c.dataset.idx));
            const livePayload = getOrderPayload(excludedIndices);
            
            let displayTotal = livePayload.total_amount;
            const chkSampleSend = document.getElementById('chk-sample-send');
            if (chkSampleSend && chkSampleSend.checked) {
                displayTotal = 0;
            }
            
            document.getElementById('exclude-modal-totalAmount').innerText = displayTotal.toLocaleString();
            
            let extraDiv = document.getElementById('exclude-extra-items');
            if(!extraDiv) {
                extraDiv = document.createElement('div');
                extraDiv.id = 'exclude-extra-items';
            }
            
            let extraHTML = '';
            if (livePayload.discount_5_amount > 0) {
                extraHTML += `
                <div style="display:flex; align-items:center; gap:8px; padding:8px; background:#fff; border:1px solid #cbd5e0; border-radius:4px;">
                    <span style="flex:1; font-weight:600; color:#2d3748; font-size: 0.95rem; margin-left:36px;">5% 할인</span>
                    <span style="color:#3182ce; font-weight:bold; font-size: 0.95rem;">- ${livePayload.discount_5_amount.toLocaleString()}원</span>
                </div>`;
            }
            if (livePayload.coupon_amount > 0) {
                extraHTML += `
                <div style="display:flex; align-items:center; gap:8px; padding:8px; background:#fff; border:1px solid #cbd5e0; border-radius:4px;">
                    <span style="flex:1; font-weight:600; color:#2d3748; font-size: 0.95rem; margin-left:36px;">쿠폰 할인</span>
                    <span style="color:#3182ce; font-weight:bold; font-size: 0.95rem;">- ${livePayload.coupon_amount.toLocaleString()}원</span>
                </div>`;
            }
            if (livePayload.point_deduction > 0) {
                extraHTML += `
                <div style="display:flex; align-items:center; gap:8px; padding:8px; background:#fff; border:1px solid #cbd5e0; border-radius:4px;">
                    <span style="flex:1; font-weight:600; color:#e53e3e; font-size: 0.95rem; margin-left:36px;">적립금 차감</span>
                    <span style="color:#e53e3e; font-weight:bold; font-size: 0.95rem;">- ${livePayload.point_deduction.toLocaleString()}원</span>
                </div>`;
            }
            if (livePayload.shipping_cost > 0) {
                 extraHTML += `
                <div style="display:flex; align-items:center; gap:8px; padding:8px; background:#fff; border:1px solid #cbd5e0; border-radius:4px;">
                    <span style="flex:1; font-weight:600; color:#2d3748; font-size: 0.95rem; margin-left:36px;">배송비</span>
                    <span style="color:#2d3748; font-weight:bold; font-size: 0.95rem;">+ ${livePayload.shipping_cost.toLocaleString()}원</span>
                </div>`;
            } else {
                 if(!livePayload.free_reason) livePayload.free_reason = "기본";
                 extraHTML += `
                <div style="display:flex; align-items:center; gap:8px; padding:8px; background:#fff; border:1px solid #cbd5e0; border-radius:4px;">
                    <span style="flex:1; font-weight:600; color:#2d3748; font-size: 0.95rem; margin-left:36px;">배송비 (무료 - ${livePayload.free_reason})</span>
                    <span style="color:#2d3748; font-weight:bold; font-size: 0.95rem;">0원</span>
                </div>`;
            }
            if (livePayload.extra_shipping_cost > 0) {
                 extraHTML += `
                <div style="display:flex; align-items:center; gap:8px; padding:8px; background:#fff; border:1px solid #cbd5e0; border-radius:4px;">
                    <span style="flex:1; font-weight:600; color:#2d3748; font-size: 0.95rem; margin-left:36px;">추가 배송비</span>
                    <span style="color:#2d3748; font-weight:bold; font-size: 0.95rem;">+ ${livePayload.extra_shipping_cost.toLocaleString()}원</span>
                </div>`;
            }
            extraDiv.innerHTML = extraHTML;
            listContainer.appendChild(extraDiv);

            document.querySelectorAll('.exclude-chk').forEach(c => {
                const priceSpan = c.closest('label').querySelector('.exclude-price-span');
                if (priceSpan) {
                    if (c.checked) {
                        priceSpan.style.textDecoration = 'line-through';
                        priceSpan.style.textDecorationColor = 'red';
                        priceSpan.style.opacity = '0.5';
                    } else {
                        priceSpan.style.textDecoration = 'none';
                        priceSpan.style.opacity = '1';
                    }
                }
            });
        };

        document.querySelectorAll('.chk-order:checked').forEach((chk, idx) => {
            const row = chk.closest('.item-row');
            const qty = parseInt(row.querySelector('.qty-order').value) || 1;
            const multiplier = parseInt(chk.dataset.multiplier) || 1;
            const finalQty = qty * multiplier;
            
            const cost = parseInt(chk.dataset.cost) || 0;
            const dcost = chk.dataset.dcost === "null" ? null : (parseInt(chk.dataset.dcost) || null);
            let itemTotal = 0;
            if (dcost !== null && qty >= 3) {
                itemTotal = Math.floor(qty / 3) * dcost * 2 + (qty % 3) * cost;
            } else {
                itemTotal = cost * qty;
            }
            
            const orderType = document.querySelector('input[name="order-type"]:checked').value;
            const noLidChecked = document.getElementById('chk-no-lid').checked;
            if (orderType === 'noolak' || orderType === 'pason' || orderType === 'bullyang' || noLidChecked) {
                itemTotal = 0;
            }
            
            let badges = [];
            if (orderType === 'noolak') badges.push('누락');
            else if (orderType === 'pason') badges.push('파손');
            else if (orderType === 'bullyang') badges.push('불량');
            if (noLidChecked && chk.dataset.type === 'ORDER_SINGLE') badges.push('뚜껑(X)통(O)');
            
            let reasonBadge = badges.length > 0 ? `<span style="font-size:0.75rem; background:#feebc8; color:#dd6b20; padding:2px 5px; border-radius:4px; margin-left:6px; font-weight:bold;">${badges.join(', ')}</span>` : '';

            const div = document.createElement('div');
            div.style.display = 'flex';
            div.style.alignItems = 'center';
            div.style.gap = '8px';
            div.style.padding = '8px';
            div.style.background = '#fff';
            div.style.border = '1px solid #cbd5e0';
            div.style.borderRadius = '4px';
            
            div.innerHTML = `
                <label style="cursor:pointer; display:flex; align-items:center; gap:8px; width:100%; margin: 0;">
                    <input type="checkbox" class="exclude-chk" data-idx="${idx}" style="transform: scale(1.2); cursor: pointer;">
                    <span style="flex:1; font-weight:600; color:#2d3748; font-size: 0.95rem;">${chk.dataset.label} (${finalQty}개)${reasonBadge}</span>
                    <span class="exclude-price-span" style="color:#e53e3e; font-weight:bold; font-size: 0.95rem; transition: opacity 0.2s;">${itemTotal.toLocaleString()}원</span>
                </label>
            `;
            
            const checkbox = div.querySelector('.exclude-chk');
            checkbox.addEventListener('change', updateTotalDisplay);
            
            listContainer.appendChild(div);
        });

        currentSubmitContext = { url, isEllen };
        
        const chkSampleSend = document.getElementById('chk-sample-send');
        if (chkSampleSend) {
            chkSampleSend.checked = false;
            chkSampleSend.onchange = (e) => {
                const isChecked = e.target.checked;
                document.querySelectorAll('.exclude-chk').forEach(c => c.checked = isChecked);
                updateTotalDisplay();
            };
        }
        
        updateTotalDisplay();
        document.getElementById('exclude-modal').style.display = 'flex';
    }

    document.getElementById('btn-exclude-cancel').addEventListener('click', () => {
        document.getElementById('exclude-modal').style.display = 'none';
        currentSubmitContext = null;
    });

    document.getElementById('btn-exclude-submit').addEventListener('click', () => {
        if (!currentSubmitContext) return;
        const excludedIndices = Array.from(document.querySelectorAll('.exclude-chk:checked')).map(c => parseInt(c.dataset.idx));
        document.getElementById('exclude-modal').style.display = 'none';
        doSubmitOrder(currentSubmitContext.url, currentSubmitContext.isEllen, excludedIndices);
        currentSubmitContext = null;
    });

    function doSubmitOrder(url, isEllen = false, excludedIndices = []) {
        const payload = getOrderPayload(excludedIndices);
        payload.is_ellen = isEllen;

        const isSpecialType = (payload.order_type === 'noolak' || payload.order_type === 'pason' || payload.order_type === 'bullyang');
        const typeLabelMap = { 'noolak': '누락', 'pason': '파손', 'bullyang': '불량', 'normal': '수동발주', 'ellen': '엘렌' };
        
        let finalPayloadAmount = payload.total_amount;
        if (isSpecialType) finalPayloadAmount = 0;
        
        const chkSampleSend = document.getElementById('chk-sample-send');
        if (chkSampleSend && chkSampleSend.checked) {
            finalPayloadAmount = 0;
        }

        const submitPayload = { ...payload, total_amount: finalPayloadAmount };

        if (url.includes('submit')) {
            const manualTabLink = document.querySelector('li[data-tab="manual-tab"]');
            if (manualTabLink) manualTabLink.click();
            const loader = document.getElementById('sheet-loader');
            if (loader) loader.style.display = 'flex';
        }

        fetch(url, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(submitPayload)
        }).then(res => res.json()).then(data => {
            if (url.includes('submit')) {
                const loader = document.getElementById('sheet-loader');
                if (loader) loader.style.display = 'none';
            }
            if (data.status === 'success') {
                if (!url.includes('submit')) {
                    alert(data.message);
                } else if (data.timestamp) {
                    const histData = {
                        timestamp: data.timestamp,
                        customer_name: submitPayload.customer_name,
                        total_amount: isSpecialType ? typeLabelMap[submitPayload.order_type] : submitPayload.total_amount
                    };
                    fetch('/api/manual/history', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify(histData)
                    }).then(() => {
                        if (typeof loadManualHistory === 'function') {
                            loadManualHistory();
                        }
                    });
                }

                // Invoke browser-native clipboard copy protocol with the newly prepared text
                if (data.clipboard_text) {
                    navigator.clipboard.writeText(data.clipboard_text).catch(err => {
                        console.error('Clipboard copy failed:', err);
                        alert("클립보드 접근 권한이 없어 복사하지 못했습니다. (HTTPS 환경 필요)");


                    });
                }

                document.getElementById('btn-reset').click();
                if (url.includes('submit')) {
                    const iframe = document.querySelector('#manual-tab iframe');
                    if (iframe) iframe.src = iframe.src;
                }
            } else {
                alert("Error: " + data.detail);
            }
        }).catch(err => {
            if (url.includes('submit')) {
                const loader = document.getElementById('sheet-loader');
                if (loader) loader.style.display = 'none';
            }
            alert("요청 중 오류 발생: " + err);


        });
    }

    document.getElementById('btn-submit-normal').addEventListener('click', () => submitOrder('/api/order/submit', false));
    document.getElementById('btn-submit-ellen').addEventListener('click', () => submitOrder('/api/order/submit', true));

    document.getElementById('btn-download-sheet').addEventListener('click', () => {
        if (!confirm("수동발주로 입력한 자료는 엑셀 파일로 저장되며, 입력된 수동발주 내용은 사라집니다.\n진행하시겠습니까?")) return;

        const btn = document.getElementById('btn-download-sheet');
        btn.innerText = '저장 중...';
        btn.disabled = true;

        const progressContainer = document.getElementById('download-progress-container');
        const progressBar = document.getElementById('download-progress-bar');
        const progressText = document.getElementById('download-progress-text');

        progressContainer.style.display = 'block';
        progressBar.style.width = '0%';
        progressText.innerText = '0%';

        let progress = 0;
        const interval = setInterval(() => {
            if (progress < 90) {
                progress += Math.floor(Math.random() * 8) + 4;
                if (progress > 90) progress = 90;
                progressBar.style.width = progress + '%';
                progressText.innerText = progress + '%';
            }
        }, 500);

        fetch('/api/sheet/download_and_clear', { method: 'POST' })
            .then(res => {
                if (!res.ok) throw new Error("서버에서 오류가 발생했습니다.");
                return res.blob();
            })
            .then(blob => {
                // Determine save filename client-side
                const now = new Date();
                const weekdays = ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"];
                const dayStr = weekdays[now.getDay()];
                const mm = String(now.getMonth() + 1).padStart(2, '0');
                const dd = String(now.getDate()).padStart(2, '0');
                const fileName = `${mm}월 ${dd}일 (${dayStr}) 5 수동발주.xlsx`;

                // Spawn a temporary web link to fetch the constructed Blob and trigger "Save as"
                const downloadUrl = window.URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.style.display = 'none';
                a.href = downloadUrl;
                a.download = fileName;
                document.body.appendChild(a);
                a.click();

                // Cleanup Blob immediately
                window.URL.revokeObjectURL(downloadUrl);
                document.body.removeChild(a);

                clearInterval(interval);
                progressBar.style.width = '100%';
                progressText.innerText = '100%';

                setTimeout(() => {
                    alert("구글 엑셀 파일이 성공적으로 다운로드되고 시트가 초기화되었습니다.");
                    progressContainer.style.display = 'none';
                    btn.innerText = '엑셀로 저장';
                    btn.disabled = false;

                    const iframe = document.querySelector('#manual-tab iframe');
                    if (iframe) iframe.src = iframe.src;
                }, 400);
            })
            .catch(err => {
                clearInterval(interval);
                alert("네트워크 오류/파일 저장 실패: " + err);
                progressContainer.style.display = 'none';
                btn.innerText = '엑셀로 저장';
                btn.disabled = false;


            });


    });

    document.getElementById('btn-reset').addEventListener('click', () => {
        document.querySelectorAll('.chk-order').forEach(c => {
            c.checked = false;
            const row = c.closest('.item-row');
            if (row) row.style.backgroundColor = '';
        });
        document.querySelectorAll('.qty-order').forEach(i => i.value = "1");
        document.getElementById('cust-name').value = '';
        document.getElementById('cust-phone').value = '';
        document.getElementById('cust-address').value = '';
        document.getElementById('chk-no-lid').checked = false;
        document.getElementById('chk-no-lid').disabled = true;
        document.querySelector('input[name="order-type"][value="normal"]').checked = true;

        // sms reset as well
        document.getElementById('sms-discount').checked = false;
        document.getElementById('sms-discount').disabled = false;
        document.getElementById('sms-coupon').checked = false;
        document.getElementById('sms-coupon').disabled = false;
        document.getElementById('sms-june-promo').checked = false;
        document.getElementById('sms-ship-free').checked = false;
        document.getElementById('sms-ship-extra').checked = false;
        const ptInput = document.getElementById('sms-point-deduction');
        if (ptInput) ptInput.value = '';
        document.getElementById('sms-preview').innerHTML = '';


    });

    // ============================================
    // SMS CALCULATE WITH MATCHED PRICING
    // ============================================
    function getAmountGiftText(orderAmount) {
        if (!configData['SMS_GIFT_RULES']) return "";
        let matched = [];
        let rules = [];
        for (let i = 1; i <= 4; i++) {
            const sMin = configData['SMS_GIFT_RULES'][`condition${i}_min`];
            const sMax = configData['SMS_GIFT_RULES'][`condition${i}_max`];
            const sGift = configData['SMS_GIFT_RULES'][`condition${i}_gift`];
            if (!sGift) continue;

            const minV = sMin ? parseInt(sMin) : 0;
            const maxV = sMax ? parseInt(sMax) : null;
            rules.push({
                min: minV, max: maxV, gift: sGift

            });
        }

        let seen = new Set();
        rules.forEach(r => {
            if (orderAmount < r.min) return;
            if (r.max !== null && orderAmount >= r.max) return;
            if (!seen.has(r.gift)) {
                seen.add(r.gift);
                matched.push(r.gift);
            }


        });

        if (matched.length === 0) return "";
        return "\n(금액별 사은품 증정)\n" + matched.join("\n") + "\n";
    }

    document.getElementById('btn-sms-calc').addEventListener('click', () => {
        let totalCost = 0;
        let orderListStr = "";
        let hasMarkedFreeShipping = false;

        const checkedItems = document.querySelectorAll('.chk-order:checked');
        if (checkedItems.length === 0) { alert("선택된 상품이 없습니다."); return; }

        checkedItems.forEach(chk => {
            const row = chk.closest('.item-row');
            const qty = parseInt(row.querySelector('.qty-order').value) || 1;
            const orderLabel = chk.dataset.label;

            const cost = parseInt(chk.dataset.cost) || 0;
            const dcost = chk.dataset.dcost === "null" ? null : (parseInt(chk.dataset.dcost) || null);
            const isFree = chk.dataset.isFree === "true";

            if (isFree) hasMarkedFreeShipping = true;

            let itemTotal = 0;
            if (dcost !== null && qty >= 3) {
                itemTotal = Math.floor(qty / 3) * dcost * 2 + (qty % 3) * cost;
            } else {
                itemTotal = cost * qty;
            }
            
            const orderType = document.querySelector('input[name="order-type"]:checked').value;
            const noLidChecked = document.getElementById('chk-no-lid').checked;
            if (orderType === 'noolak' || orderType === 'pason' || orderType === 'bullyang' || noLidChecked) {
                itemTotal = 0;
            }

            const cleanLabel = orderLabel.replace(/^\*/, '').trim();
            let dispName = cleanLabel.replace("오리 ", "");
            let smsQty = qty;

            const matchName = dispName.match(/_(\d+)개$/);
            if (matchName) {
                smsQty = qty * parseInt(matchName[1], 10);
                dispName = dispName.replace(/_\d+개$/, '').trim();
            }

            if (cost === 0) {
                orderListStr += `<span style="color:red; font-weight:bold;">${dispName} (가격미입력)</span>\n`;
            } else {
                orderListStr += `${dispName} ${smsQty}개 ${itemTotal.toLocaleString()}원\n`;
            }
            totalCost += itemTotal;


        });

        let baseShippingVal = parseInt((configData.APP_SETTINGS && configData.APP_SETTINGS.shipping_fee) ? configData.APP_SETTINGS.shipping_fee : 3500);
        let extraShippingVal = parseInt((configData.APP_SETTINGS && configData.APP_SETTINGS.extra_shipping_fee) ? configData.APP_SETTINGS.extra_shipping_fee : 3000);
        let pointDeduction = parseInt(document.getElementById('sms-point-deduction').value.replace(/,/g, '')) || 0;

        let totalAfterDiscount = totalCost;
        let discount5Amount = 0;
        let couponAmount = 0;
        if (document.getElementById('sms-coupon').checked) {
            couponAmount = getCouponDiscount(totalCost);
        }
        if (document.getElementById('sms-discount').checked) {
            totalAfterDiscount = Math.floor((totalCost * 0.95) / 10) * 10;
            discount5Amount = totalCost - totalAfterDiscount;
        }
        if (couponAmount > 0) {
            totalAfterDiscount = Math.max(0, totalAfterDiscount - couponAmount);
        }
        if (pointDeduction > 0) {
            totalAfterDiscount = Math.max(0, totalAfterDiscount - pointDeduction);
        }

        let junePromoText = "";
        if (document.getElementById('sms-june-promo').checked) {
            junePromoText = getAmountGiftText(totalCost);
        }

        let isAutoFree = totalAfterDiscount >= 50000;
        let isManualFree = document.getElementById('sms-ship-free').checked;
        let isFreeShip = hasMarkedFreeShipping || isAutoFree || isManualFree;

        let shippingCost = 0;
        if (!isFreeShip) {
            shippingCost = baseShippingVal;
        }
        
        let extraShippingCost = 0;
        if (document.getElementById('sms-ship-extra').checked) {
            extraShippingCost = extraShippingVal;
        }
        
        const currentOrderType = document.querySelector('input[name="order-type"]:checked').value;
        const noLidChecked = document.getElementById('chk-no-lid').checked;
        if (currentOrderType === 'noolak' || currentOrderType === 'pason' || currentOrderType === 'bullyang' || noLidChecked) {
            shippingCost = 0;
            extraShippingCost = 0;
        }

        let finalPayable = totalAfterDiscount + shippingCost + extraShippingCost;

        let depositVal = `${finalPayable.toLocaleString()}원`;
        if (hasMarkedFreeShipping) {
            if (extraShippingCost > 0) depositVal += "(무료배송, 추가배송비만 적용)";
            else depositVal += "(무료배송 상품 포함)";
        }
        else if (isFreeShip) depositVal += "(무료배송)";
        let depositLine = `입금 금액: ${depositVal}`;

        const defaultHeader = "안녕하세요, 미라네 주방입니다! 😊 \n주문내용 확인 부탁드립니다.";
        const defaultFooter = "1. 아래 계좌로 입금해 주세요.\n\n▶입금 금액: {최종금액} \n▶입금 계좌 (농협): 317-0025-1542-51\n▶예금주: (주)더블엑스 코퍼레이션\n\n2. 입금 후 [성함/주소/연락처]를 남겨주세요.\n\n[배송 안내]\n■오후 1시 이전 입금 건은 당일 발송됩니다.\n★이벤트 상품 주문시 1~2일 정도 늦어질 수 있으니 너그러운 양해 부탁드립니다.";
        const rules = configData['SMS_GIFT_RULES'] || {};

        let headerText = rules['header_text'] ? rules['header_text'].replace(/\\n/g, '\n') : defaultHeader;
        let footerText = rules['footer_text'] ? rules['footer_text'].replace(/\\n/g, '\n') : defaultFooter;

        footerText = footerText.replace(/{최종금액}/g, depositVal);

        let msg = `${headerText}\n\n*****주문 내용*****\n${orderListStr}${junePromoText}\n주문 금액: ${totalCost.toLocaleString()}원\n`;
        if (discount5Amount > 0) msg += `할인 금액: -${discount5Amount.toLocaleString()}원(5%)\n`;
        if (couponAmount > 0) msg += `쿠폰 할인: -${couponAmount.toLocaleString()}원\n`;
        if (pointDeduction > 0) msg += `적립금 차감: -${pointDeduction.toLocaleString()}원\n`;
        if (shippingCost > 0) msg += `   택배비: ${shippingCost.toLocaleString()}원\n`;
        if (extraShippingCost > 0) msg += `추가배송비: ${extraShippingCost.toLocaleString()}원\n`;

        msg += `==========================\n${depositLine}\n\n${footerText}`;

        const previewDiv = document.getElementById('sms-preview');
        previewDiv.innerHTML = msg;
        navigator.clipboard.writeText(previewDiv.innerText).catch(err => {
            console.error('Clipboard copy failed:', err);
        });


        // Save History
        const now = new Date();
        const stamp = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')} ${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;

        const savedItems = [];
        checkedItems.forEach(chk => {
            const row = chk.closest('.item-row');
            const qty = parseInt(row.querySelector('.qty-order').value) || 1;
            savedItems.push({
                code: chk.dataset.code,
                label: chk.dataset.label,
                qty: qty


            });


        });

        const custName = document.getElementById('cust-name').value.trim();
        const custPhone = document.getElementById('cust-phone').value.trim();
        const custAddress = document.getElementById('cust-address').value.trim();

        const histData = {
            timestamp: stamp,
            deposit_amount_str: finalPayable.toLocaleString() + "원",
            custName: custName,
            custPhone: custPhone,
            custAddress: custAddress,
            customer_name: custName,
            phone: custPhone,
            address: custAddress,
            orderType: document.querySelector('input[name="order-type"]:checked').value,
            noLid: document.getElementById('chk-no-lid').checked,
            items: savedItems,
            smsOpts: {
                discount: document.getElementById('sms-discount').checked,
                junePromo: document.getElementById('sms-june-promo').checked,
                shipExtra: document.getElementById('sms-ship-extra').checked,
                shipFree: document.getElementById('sms-ship-free').checked,
                pointDeduction: pointDeduction
            },
            previewText: msg
        };

        fetch('/api/sms/history', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(histData)
        }).then(() => {
            writeSmsCustomerCache(stamp, {
                custName: custName,
                custPhone: custPhone,
                custAddress: custAddress
            });
            loadSmsHistory();
        });


    });

    // ============================================
    // SMS HISTORY
    // ============================================
    const SMS_CUSTOMER_CACHE_KEY = 'smsCustomerHistoryByTimestamp';

    function readSmsCustomerCache() {
        try {
            return JSON.parse(localStorage.getItem(SMS_CUSTOMER_CACHE_KEY) || '{}');
        } catch (e) {
            return {};
        }
    }

    function writeSmsCustomerCache(timestamp, customer) {
        if (!timestamp) return;
        const cache = readSmsCustomerCache();
        cache[timestamp] = customer;
        localStorage.setItem(SMS_CUSTOMER_CACHE_KEY, JSON.stringify(cache));
    }

    function firstNonEmpty(...values) {
        for (const value of values) {
            if (value !== undefined && value !== null && String(value).trim() !== '') {
                return value;
            }
        }
        return '';
    }

    function loadSmsHistory() {
        const u = document.getElementById('sms-history-list');
        u.innerHTML = '';
        fetch('/api/sms/history').then(r => r.json()).then(data => {
            data.slice().reverse().forEach((d, idx) => {
                const actualIdx = data.length - 1 - idx;
                const li = document.createElement('li');
                li.style.cursor = 'pointer';
                li.style.padding = '4px 0';
                li.style.borderBottom = '1px solid #eee';
                li.onclick = () => window.loadHistoryItem(actualIdx);

                const spanDate = document.createElement('span');
                spanDate.textContent = `${d.timestamp} | ${d.deposit_amount_str}`;
                li.appendChild(spanDate);

                const spanDel = document.createElement('span');
                spanDel.className = 'action-text ms-2';
                spanDel.style.marginLeft = '8px';
                spanDel.title = '삭제';
                spanDel.textContent = '❌';
                spanDel.onclick = (e) => window.deleteHistory(actualIdx, e);
                li.appendChild(spanDel);

                u.appendChild(li);


            });


        });
    }

    window.loadManualHistory = function () {
        const u = document.getElementById('manual-history-list');
        if (!u) return;
        u.innerHTML = '';
        fetch('/api/manual/history').then(r => r.json()).then(data => {
            let totalCount = data.length;
            let totalAmount = 0;
            data.forEach((d) => {
                if (typeof d.total_amount === 'number') totalAmount += d.total_amount;
                else if (typeof d.total_amount === 'string' && !isNaN(parseInt(d.total_amount))) totalAmount += parseInt(d.total_amount);
            });

            let txtCount = document.getElementById('manual-total-count');
            let txtAmount = document.getElementById('manual-total-amount');
            if (txtCount) txtCount.textContent = totalCount;
            if (txtAmount) txtAmount.textContent = totalAmount.toLocaleString();

            data.slice().reverse().forEach((d) => {
                const li = document.createElement('li');
                li.style.padding = '4px 0';
                li.style.borderBottom = '1px solid #eee';
                li.style.display = 'flex';
                li.style.justifyContent = 'space-between';
                li.style.alignItems = 'center';
                li.style.fontSize = '0.9rem';

                const spanInfo = document.createElement('span');
                const timeStr = d.timestamp.split(' ')[1] || d.timestamp;
                let amtDisplay = (typeof d.total_amount === 'number' || (typeof d.total_amount === 'string' && !isNaN(parseInt(d.total_amount)))) 
                                 ? parseInt(d.total_amount).toLocaleString() + '원' 
                                 : d.total_amount;
                spanInfo.textContent = `${timeStr} | ${d.customer_name} | ${amtDisplay}`;
                li.appendChild(spanInfo);

                const spanDel = document.createElement('span');
                spanDel.className = 'action-text ms-2';
                spanDel.style.marginLeft = '8px';
                spanDel.style.cursor = 'pointer';
                spanDel.title = '삭제';
                spanDel.textContent = '❌';
                spanDel.onclick = (e) => {
                    e.stopPropagation();
                    if (confirm("🚨 [경고] 이 수동발주 기록을 삭제하시겠습니까?\n\n(구글 시트에서도 함께 삭제됩니다!)")) {
                        const btn = e.target;
                        btn.textContent = '⏳';
                        btn.style.pointerEvents = 'none';
                        fetch(`/api/manual/history/${encodeURIComponent(d.timestamp)}`, { method: 'DELETE' })
                            .then(() => {
                                window.loadManualHistory();
                                const iframe = document.querySelector('#manual-tab iframe');
                                if (iframe) iframe.src = iframe.src;
                            })
                            .catch(() => {
                                alert("삭제 중 오류가 발생했습니다.");
                                btn.textContent = '❌';
                                btn.style.pointerEvents = 'auto';
                            });
                    }
                };
                li.appendChild(spanDel);

                u.appendChild(li);
            });
        }).catch(err => console.error("Error loading manual history", err));
    }

    window.loadHistoryItem = function (idx) {
        fetch('/api/sms/history').then(r => r.json()).then(data => {
            if (idx < 0 || idx >= data.length) return;
            const d = data[idx];

            document.getElementById('btn-reset').click();

            const cachedCustomer = readSmsCustomerCache()[d.timestamp] || {};
            const savedCustName = firstNonEmpty(d.custName, d.customer_name, cachedCustomer.custName, cachedCustomer.customer_name);
            const savedCustPhone = firstNonEmpty(d.custPhone, d.phone, cachedCustomer.custPhone, cachedCustomer.phone);
            const savedCustAddress = firstNonEmpty(d.custAddress, d.address, cachedCustomer.custAddress, cachedCustomer.address);
            document.getElementById('cust-name').value = savedCustName;
            document.getElementById('cust-phone').value = savedCustPhone;
            document.getElementById('cust-address').value = savedCustAddress;
            if (d.orderType !== undefined) {
                const rb = document.querySelector(`input[name="order-type"][value="${d.orderType}"]`);
                if (rb) rb.checked = true;
            }

            // Fallback for Google Sheets history where items array is missing but items_str exists
            if ((!d.items || !Array.isArray(d.items)) && d.items_str) {
                d.items = [];
                const parts = d.items_str.split(',');
                parts.forEach(part => {
                    const match = part.trim().match(/^(.*)[\[\(](.*?)[\]\)]\s*(\d+)개$/);
                    if (match) {
                        d.items.push({
                            label: match[1].trim(),
                            code: match[2].trim(),
                            qty: parseInt(match[3])
                        });
                    }
                });
            }

            if (d.items && Array.isArray(d.items)) {
                d.items.forEach(item => {
                    let chk = Array.from(document.querySelectorAll('.chk-order:not(:checked)')).find(c => c.dataset.code === item.code && c.dataset.label === item.label);
                    if (!chk) {
                        chk = Array.from(document.querySelectorAll('.chk-order:not(:checked)')).find(c => c.dataset.code === item.code || c.dataset.label === item.label);
                    }
                    if (chk) {
                        chk.checked = true;
                        const row = chk.closest('.item-row');
                        if (row) {
                            const sel = row.querySelector('.qty-order');
                            if (sel) {
                                if (sel.tagName === 'SELECT') {
                                    const optionExists = Array.from(sel.options).some(opt => opt.value == item.qty);
                                    if (!optionExists) {
                                        const input = document.createElement('input');
                                        input.type = 'number';
                                        input.min = '1';
                                        input.value = item.qty;
                                        input.className = 'qty-order';
                                        sel.replaceWith(input);
                                    } else {
                                        sel.value = item.qty;
                                    }
                                } else {
                                    sel.value = item.qty;
                                }
                            }
                        }
                    }


                });

                const anyChk = document.querySelector('.chk-order');
                if (anyChk) {
                    anyChk.dispatchEvent(new Event('change'));
                }

                if (d.noLid !== undefined) document.getElementById('chk-no-lid').checked = d.noLid;
            }

            if (d.smsOpts) {
                document.getElementById('sms-discount').checked = !!d.smsOpts.discount;
                document.getElementById('sms-june-promo').checked = !!d.smsOpts.junePromo;
                document.getElementById('sms-ship-extra').checked = !!d.smsOpts.shipExtra;
                document.getElementById('sms-ship-free').checked = !!d.smsOpts.shipFree;
                if (d.smsOpts.pointDeduction) {
                    const ptInput = document.getElementById('sms-point-deduction');
                    if(ptInput) ptInput.value = parseInt(d.smsOpts.pointDeduction).toLocaleString();
                } else {
                    const ptInput = document.getElementById('sms-point-deduction');
                    if(ptInput) ptInput.value = '';
                }
            }

            if (d.previewText !== undefined) {
                document.getElementById('sms-preview').innerHTML = d.previewText;
            }


        });
    }

    window.deleteHistory = function (idx, e) {
        e.stopPropagation();
        if (confirm("이 기록을 삭제하시겠습니까?")) {
            fetch(`/api/sms/history/${idx}`, { method: 'DELETE' }).then(() => loadSmsHistory());
        }
    }

    document.getElementById('btn-sms-clear-all').addEventListener('click', () => {
        if (confirm("정말로 모든 기록을 삭제하시겠습니까?")) {
            fetch('/api/sms/history', { method: 'DELETE' }).then(() => loadSmsHistory());
        }


    });

    // ============================================
    // GIFT TAB
    // ============================================
    function buildGiftTab(data) {
        const container = document.getElementById('gift-rules-container');
        container.innerHTML = ''; // 중복 방지를 위해 기존 내용 완전히 비우기
        const giftsRaw = data['ORDER_GIFT'] ? (data['ORDER_GIFT'].__order || Object.keys(data['ORDER_GIFT'])) : [];
        const gifts = giftsRaw.filter(k => k !== '__order');
        const rules = data['SMS_GIFT_RULES'] || {};

        for (let i = 1; i <= 4; i++) {
            const card = document.createElement('div');
            card.className = 'glass-card gift-rule-card';

            const title = document.createElement('h3');
            title.textContent = `조건 ${i}`;

            const minV = rules[`condition${i}_min`] || '';
            const maxV = rules[`condition${i}_max`] || '';
            const selGift = rules[`condition${i}_gift`] || '';

            const fmt = (v) => {
                if (!v) return '';
                let n = parseInt(String(v).replace(/,/g, ''), 10);
                return isNaN(n) ? '' : n.toLocaleString();
            };
            const inputs = document.createElement('div');
            inputs.className = 'rule-inputs';
            inputs.innerHTML = `
                <input type="text" id="rule${i}-min" placeholder="최소금액" value="${fmt(minV)}">이상
                <input type="text" id="rule${i}-max" placeholder="최대금액" value="${fmt(maxV)}">미만
                <button class="btn btn-secondary btn-clear-rule" data-idx="${i}">조건 삭제</button>
            `;

            const radioList = document.createElement('div');
            radioList.className = 'gift-radio-list';

            // None option
            radioList.innerHTML += `<label><input type="radio" name="rule${i}-gift" value="" ${!selGift ? 'checked' : ''}> 선택 없음</label>`;

            gifts.forEach(g => {
                radioList.innerHTML += `<label><input type="radio" name="rule${i}-gift" value="${g}" ${selGift === g ? 'checked' : ''}> ${g}</label>`;


            });

            card.appendChild(title);
            card.appendChild(inputs);
            card.appendChild(radioList);
            container.appendChild(card);
        }

        document.querySelectorAll('.btn-clear-rule').forEach(btn => {
            btn.addEventListener('click', e => {
                const i = e.target.dataset.idx;
                document.getElementById(`rule${i}-min`).value = '';
                document.getElementById(`rule${i}-max`).value = '';
                document.querySelector(`input[name="rule${i}-gift"][value=""]`).checked = true;


            });


        });

        const defaultHeader = "안녕하세요, 미라네 주방입니다! 😊 \n주문내용 확인 부탁드립니다.";
        const defaultFooter = "1. 아래 계좌로 입금해 주세요.\n\n▶입금 금액: {최종금액} \n▶입금 계좌 (농협): 317-0025-1542-51\n▶예금주: (주)더블엑스 코퍼레이션\n\n2. 입금 후 [성함/주소/연락처]를 남겨주세요.\n\n[배송 안내]\n■오후 1시 이전 입금 건은 당일 발송됩니다.\n★이벤트 상품 주문시 1~2일 정도 늦어질 수 있으니 너그러운 양해 부탁드립니다.";

        let hText = rules['header_text'] ? rules['header_text'].replace(/\\n/g, '\n') : defaultHeader;
        let fText = rules['footer_text'] ? rules['footer_text'].replace(/\\n/g, '\n') : defaultFooter;

        document.getElementById('sms-header-text').value = hText;
        document.getElementById('sms-footer-text').value = fText;

        let appFont = data['APP_SETTINGS'] ? data['APP_SETTINGS']['font'] : '';
        const fontSelect = document.getElementById('app-font-select');
        if (fontSelect && appFont) {
            fontSelect.value = appFont;
        }

        let baseShippingVal = data['APP_SETTINGS'] && data['APP_SETTINGS']['shipping_fee'] ? data['APP_SETTINGS']['shipping_fee'] : '3500';
        let extraShippingVal = data['APP_SETTINGS'] && data['APP_SETTINGS']['extra_shipping_fee'] ? data['APP_SETTINGS']['extra_shipping_fee'] : '3000';
        
        document.getElementById('setting-ship-base').value = parseInt(baseShippingVal).toLocaleString();
        document.getElementById('setting-ship-extra').value = parseInt(extraShippingVal).toLocaleString();
        
        const lblShipExtra = document.getElementById('lbl-ship-extra');
        if (lblShipExtra) {
            lblShipExtra.textContent = '추가배송비 ' + parseInt(extraShippingVal).toLocaleString() + '원';
        }

        const btnGiftSave = document.getElementById('btn-gift-save');
        // Reset color in case it was red
        btnGiftSave.style.backgroundColor = '';

        const markUnsaved = () => {
            btnGiftSave.style.backgroundColor = '#e53e3e';
        };

        // Format money fields on input
        document.querySelectorAll('input[id^="rule"][id$="-min"], input[id^="rule"][id$="-max"], #setting-ship-base, #setting-ship-extra').forEach(el => {
            el.addEventListener('input', e => {
                let val = e.target.value.replace(/[^0-9]/g, '');
                e.target.value = val ? parseInt(val, 10).toLocaleString() : '';


            });


        });

        // Inputs within gift tab
        document.querySelectorAll('#gift-tab input, #gift-tab textarea, #gift-tab select').forEach(el => {
            el.removeEventListener('input', markUnsaved);
            el.removeEventListener('change', markUnsaved);
            el.addEventListener('input', markUnsaved);
            el.addEventListener('change', markUnsaved);


        });

        document.querySelectorAll('.btn-clear-rule').forEach(btn => {
            btn.addEventListener('click', markUnsaved);


        });
    }

    const btnGiftSave = document.getElementById('btn-gift-save');
    if (btnGiftSave) {
        btnGiftSave.addEventListener('click', async () => {
            const payload = {
                rules: {},
                app_settings: {
                    shipping_fee: document.getElementById('setting-ship-base').value.replace(/[^0-9]/g, ''),
                    extra_shipping_fee: document.getElementById('setting-ship-extra').value.replace(/[^0-9]/g, '')
                }
            };
            for (let i = 1; i <= 10; i++) {
                const minEl = document.getElementById(`rule${i}-min`);
                const maxEl = document.getElementById(`rule${i}-max`);
                const itemEl = document.getElementById(`rule${i}-item`);
                if (minEl && maxEl && itemEl) {
                    payload.rules[`rule${i}_min`] = minEl.value.replace(/[^0-9]/g, '');
                    payload.rules[`rule${i}_max`] = maxEl.value.replace(/[^0-9]/g, '');
                    payload.rules[`rule${i}_item`] = itemEl.value;
                }
            }

            const hText = document.getElementById('sms-header-text');
            if (hText) payload.rules['header_text'] = hText.value;
            const fText = document.getElementById('sms-footer-text');
            if (fText) payload.rules['footer_text'] = fText.value;
            const fontSel = document.getElementById('app-font-select');
            if (fontSel) payload.app_settings.font = fontSel.value;
            
            try {
                const res = await fetch('/api/gift/settings', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify(payload)
                });
                if (res.ok) {
                    alert('저장되었습니다.');
                    btnGiftSave.style.backgroundColor = '';
                    fetch('/api/config').then(r => r.json()).then(d => {
                        configData = d;
                        const oc = document.getElementById('order-items-container');
                        if (oc) oc.innerHTML = '';
                        buildOrderTab(configData);
                        buildGiftTab(configData);
                        buildProductTab(configData);
                    });
                } else {
                    alert('저장 실패');
                }
            } catch (e) {
                alert('오류 발생');
            }
        });
    }

    const formRec = document.getElementById('form-return-receive');
    if (formRec) {
        formRec.addEventListener('submit', async (e) => {
            e.preventDefault();
            const payload = {
                receive_date: document.getElementById('rec-date').value,
                tracking_no: document.getElementById('rec-tracking-no').value,
                mall: document.getElementById('rec-mall').value,
                receiver_name: document.getElementById('rec-name').value,
                phone: document.getElementById('rec-phone').value,
                address: document.getElementById('rec-address').value,
                remarks: document.getElementById('rec-remarks').value,
                receive_status: document.getElementById('rec-status').value
            };
            const recId = document.getElementById('rec-id');
            if (recId && recId.value) {
                payload.id = parseInt(recId.value, 10);
            }
            try {
                const res = await fetch('/api/return/receive', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify(payload)
                });
                if(res.ok) {
                    formRec.reset();
                    document.getElementById('rec-date').value = new Date(new Date().getTime() - new Date().getTimezoneOffset() * 60000).toISOString().split('T')[0];
                    if(recId) recId.value = '';
                    if (typeof loadReturnReceivings === 'function') {
                        loadReturnReceivings();
                    }
                    if (typeof loadReturnRequests === 'function') {
                        loadReturnRequests();
                    }
                } else {
                    alert('등록 실패');
                }
            } catch(e) { alert('오류 발생'); }
        });
    }

    // Bulk receive logic
    const btnBulkReceive = document.getElementById('btn-bulk-receive');
    const bulkReceiveModal = document.getElementById('bulk-receive-modal');
    const btnBulkCancel = document.getElementById('btn-bulk-cancel');
    const btnBulkSubmit = document.getElementById('btn-bulk-submit');
    const bulkTrackingNumbers = document.getElementById('bulk-tracking-numbers');
    const bulkPrefixInput = document.getElementById('bulk-prefix-input');
    const btnBulkPrefixSave = document.getElementById('btn-bulk-prefix-save');

    if (btnBulkReceive && bulkReceiveModal) {
        btnBulkReceive.addEventListener('click', () => {
            bulkReceiveModal.style.display = 'flex';
            if (bulkPrefixInput) {
                bulkPrefixInput.value = localStorage.getItem('bulkTrackingPrefix') || '';
            }
        });

        if (btnBulkPrefixSave && bulkPrefixInput) {
            bulkPrefixInput.addEventListener('input', () => {
                btnBulkPrefixSave.style.backgroundColor = '#e53e3e';
            });

            btnBulkPrefixSave.addEventListener('click', () => {
                const prefix = bulkPrefixInput.value.trim();
                localStorage.setItem('bulkTrackingPrefix', prefix);
                btnBulkPrefixSave.style.backgroundColor = '#4a5568';
                alert('저장되었습니다.');
            });
        }

        btnBulkCancel.addEventListener('click', () => {
            bulkReceiveModal.style.display = 'none';
            bulkTrackingNumbers.value = '';
        });

        if (bulkTrackingNumbers) {
            bulkTrackingNumbers.addEventListener('keydown', (e) => {
                if (e.ctrlKey && e.key === 'Enter') {
                    e.preventDefault();
                    if (btnBulkSubmit) btnBulkSubmit.click();
                }
            });
        }

        btnBulkSubmit.addEventListener('click', async () => {
            const lines = bulkTrackingNumbers.value.split('\n');
            const savedPrefix = localStorage.getItem('bulkTrackingPrefix') || '';
            
            const trackingNumbers = lines.map(l => {
                let val = l.trim();
                if (val && savedPrefix && val.length === 8) {
                    return savedPrefix + val;
                }
                return val;
            }).filter(l => l);
            
            if (trackingNumbers.length === 0) {
                alert('송장번호를 입력해주세요.');
                return;
            }

            btnBulkSubmit.disabled = true;
            btnBulkSubmit.textContent = '처리 중...';

            try {
                const res = await fetch('/api/return/receive/bulk', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({ tracking_numbers: trackingNumbers })
                });

                if (res.ok) {
                    const data = await res.json();
                    bulkReceiveModal.style.display = 'none';
                    bulkTrackingNumbers.value = '';
                    if (typeof loadReturnReceivings === 'function') {
                        loadReturnReceivings();
                    }
                    if (typeof loadReturnRequests === 'function') {
                        loadReturnRequests();
                    }
                } else {
                    alert('일괄 등록 실패');
                }
            } catch (e) {
                alert('오류 발생');
            } finally {
                btnBulkSubmit.disabled = false;
                btnBulkSubmit.textContent = '일괄 등록';
            }
        });
    }

    // Load Lists
    async function loadReturnRequests() {
        const tbody = document.getElementById('tbody-return-requests');
        if(!tbody) return;
        try {
            const res = await fetch('/api/return/request');
            const recRes = await fetch('/api/return/receive');
            if(res.ok && recRes.ok) {
                const data = await res.json();
                const recData = await recRes.json();
                const receivedTrackingNos = new Set((recData.data || []).map(r => r.tracking_no).filter(t => t));

                tbody.innerHTML = '';
                if(data.data) {
                    
                    const excludeReceived = document.getElementById('chk-exclude-received')?.checked;
                    let displayData = data.data;
                    if (excludeReceived) {
                        displayData = displayData.filter(i => !(i.tracking_no && receivedTrackingNos.has(i.tracking_no)));
                    }
                    displayData.forEach(item => {
                        const isReceived = item.tracking_no && receivedTrackingNos.has(item.tracking_no);
                        const tr = document.createElement('tr');
                        tr.style.cursor = 'pointer';
                        let displayRemarks = item.remarks || '';
                        if (isReceived) {
                            tr.style.textDecoration = 'line-through';
                            tr.style.color = '#a0aec0';
                            displayRemarks += ' <span style="color: #e53e3e; font-size: 0.7rem; font-weight: bold;">[입고완료]</span>';
                        }
                        tr.addEventListener('click', () => {
                            document.getElementById('req-date').value = item.request_date || '';
                            document.getElementById('req-type').value = item.request_type || '';
                            document.getElementById('req-name').value = item.receiver_name || '';
                            document.getElementById('req-address').value = item.address || '';
                            document.getElementById('req-phone').value = item.phone || '';
                            document.getElementById('req-tracking-no').value = item.tracking_no || '';
                            document.getElementById('req-mall').value = item.mall || '';
                            document.getElementById('req-remarks').value = item.remarks || '';
                            const reqId = document.getElementById('req-id');
                            if(reqId) reqId.value = item.id;
                        });
                        const todayStr = new Date(new Date().getTime() - new Date().getTimezoneOffset() * 60000).toISOString().split('T')[0];
                        if (item.request_date && !item.request_date.startsWith(todayStr)) {
                            tr.style.backgroundColor = '#cbd5e0';
                        }
                        const rowDataJson = JSON.stringify(item).replace(/'/g, "&apos;").replace(/"/g, "&quot;");
                        tr.innerHTML = `
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: center; width: 30px;" onclick="event.stopPropagation();">
                                <input type="checkbox" class="chk-req-row" data-item="${rowDataJson}" ${isReceived ? 'disabled' : ''}>
                            </td>
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: center; white-space: nowrap; width: 100px;">${formatShortDate(item.request_date)}</td>
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: center; cursor: pointer; white-space: nowrap; width: 90px;" onclick="navigator.clipboard.writeText(this.innerText); showToast('이름이 복사되었습니다.');" title="클릭하여 복사">${item.receiver_name}</td>
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: left; cursor: pointer; white-space: nowrap; width: 130px;" onclick="navigator.clipboard.writeText(this.innerText); showToast('연락처가 복사되었습니다.');" title="클릭하여 복사">${item.phone}</td>
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: left; cursor: pointer; white-space: nowrap; width: 110px;" onclick="navigator.clipboard.writeText(this.innerText); showToast('송장번호가 복사되었습니다.');" title="클릭하여 복사">${item.tracking_no}</td>
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: center; white-space: nowrap; width: 65px;">${item.request_type}</td>
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: left; width: 215px;">${displayRemarks}</td>
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: center; width: 40px;" onclick="event.stopPropagation();">
                                <button class="btn-delete-req" data-id="${item.id}" style="background:none; border:none; color:red; cursor:pointer;">✕</button>
                            </td>
                        `;
                        tbody.appendChild(tr);
                    });
                    
                    
                    const chkAll = document.getElementById('chk-all-req');
                    if (chkAll) {
                        chkAll.checked = false;
                        chkAll.onchange = (e) => {
                            document.querySelectorAll('.chk-req-row').forEach(cb => cb.checked = e.target.checked);
                        };
                    }
                    
                    document.querySelectorAll('.btn-delete-req').forEach(btn => {
                        btn.addEventListener('click', async (e) => {
                            e.stopPropagation();
                            if(confirm('정말로 삭제하시겠습니까?')) {
                                try {
                                    const delRes = await fetch(`/api/return/request/${e.target.dataset.id}`, {method: 'DELETE'});
                                    if(delRes.ok) {
                                        if (typeof loadReturnRequests === 'function') loadReturnRequests();
                                        if (typeof loadReturnReceivings === 'function') loadReturnReceivings();
                                    }
                                } catch(err) { alert('삭제 실패'); }
                            }
                        });
                    });
                }
            }
        } catch(e) {}
    }

    async function loadReturnReceivings() {
        const tbody = document.getElementById('tbody-return-receivings');
        if(!tbody) return;
        try {
            const res = await fetch('/api/return/receive');
            if(res.ok) {
                const data = await res.json();
                tbody.innerHTML = '';
                if(data.data) {
                    
                    const excludeCompleted = document.getElementById('chk-exclude-completed')?.checked;
                    let displayData = data.data;
                    if (excludeCompleted) {
                        displayData = displayData.filter(i => i.receive_status !== '환불완료' && i.receive_status !== '교환완료');
                    }
                    displayData.forEach(item => {
                        const tr = document.createElement('tr');
                        tr.style.cursor = 'pointer';
                        tr.addEventListener('click', () => {
                            document.getElementById('rec-date').value = item.receive_date || '';
                            document.getElementById('rec-tracking-no').value = item.tracking_no || '';
                            document.getElementById('rec-mall').value = item.mall || '';
                            document.getElementById('rec-name').value = item.receiver_name || '';
                            document.getElementById('rec-phone').value = item.phone || '';
                            document.getElementById('rec-address').value = item.address || '';
            document.getElementById('rec-remarks').value = item.remarks || '';
                            const recStatus = document.getElementById('rec-status');
                            if (recStatus) recStatus.value = item.receive_status || '환불 대기';
                            const recId = document.getElementById('rec-id');
                            if (recId) recId.value = item.id;
                        });
                        const todayStr = new Date(new Date().getTime() - new Date().getTimezoneOffset() * 60000).toISOString().split('T')[0];
                        if (item.receive_date && !item.receive_date.startsWith(todayStr)) {
                            tr.style.backgroundColor = '#cbd5e0';
                        }
                        const isCompleted = (item.receive_status === '환불완료' || item.receive_status === '교환완료');
                        const statusStyle = isCompleted ? 'color: #e53e3e; font-weight: bold;' : '';
                        tr.innerHTML = `
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: center; white-space: nowrap; width: 100px;">${formatShortDate(item.receive_date)}</td>
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: center; cursor: pointer; white-space: nowrap; width: 90px;" onclick="navigator.clipboard.writeText(this.innerText); showToast('이름이 복사되었습니다.');" title="클릭하여 복사">${item.receiver_name}</td>
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: left; cursor: pointer; white-space: nowrap; width: 130px;" onclick="navigator.clipboard.writeText(this.innerText); showToast('연락처가 복사되었습니다.');" title="클릭하여 복사">${item.phone}</td>
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: left; cursor: pointer; white-space: nowrap; width: 110px;" onclick="navigator.clipboard.writeText(this.innerText); showToast('송장번호가 복사되었습니다.');" title="클릭하여 복사">${item.tracking_no}</td>
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: center; white-space: nowrap; width: 85px;">${item.mall || ''}</td>
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: center; white-space: nowrap; width: 65px; ${statusStyle}">${item.receive_status}</td>
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: left; width: 160px;">${(item.remarks || '').replace(/맞교환/g, `<span style=\"color: red;\">맞교환</span>`)}</td>
                            <td style="padding: 8px; border-bottom: 1px solid #e2e8f0; text-align: center; width: 40px;" onclick="event.stopPropagation();">
                                <button class="btn-delete-rec" data-id="${item.id}" style="background:none; border:none; color:red; cursor:pointer;">✕</button>
                            </td>
                        `;
                        tbody.appendChild(tr);
                    });
                    
                    document.querySelectorAll('.btn-delete-rec').forEach(btn => {
                        btn.addEventListener('click', async (e) => {
                            e.stopPropagation();
                            if(confirm('정말로 삭제하시겠습니까?')) {
                                try {
                                    const delRes = await fetch(`/api/return/receive/${e.target.dataset.id}`, {method: 'DELETE'});
                                    if(delRes.ok) {
                                        if (typeof loadReturnReceivings === 'function') loadReturnReceivings();
                                        if (typeof loadReturnRequests === 'function') loadReturnRequests();
                                    }
                                } catch(err) { alert('삭제 실패'); }
                            }
                        });
                    });
                }
            }
        } catch(e) {}
    }

    // Initial load
    const returnTabMenu = document.querySelector('[data-tab="return-tab"]');
    
    const chkExcludeCompleted = document.getElementById('chk-exclude-completed');
    if (chkExcludeCompleted) {
        chkExcludeCompleted.addEventListener('change', () => {
            loadReturnReceivings();
        });
    }

    const chkExcludeReceived = document.getElementById('chk-exclude-received');
    if (chkExcludeReceived) {
        chkExcludeReceived.addEventListener('change', () => {
            loadReturnRequests();
        });
    }
    
    if(returnTabMenu) {
        returnTabMenu.addEventListener('click', () => {
            loadReturnRequests();
            loadReturnReceivings();
        });
        
        // Load immediately on page load
        setTimeout(() => {
            loadReturnRequests();
            loadReturnReceivings();
        }, 500);
    }
    const reqTrackingNo = document.getElementById('req-tracking-no');
    const recTrackingNo = document.getElementById('rec-tracking-no');
    
    // Auto-paste 12-digit tracking number on click
    async function handleTrackingClick(e) {
        try {
            const text = await navigator.clipboard.readText();
            if (!text) return;
            const cleanText = text.replace(/[-\s]/g, '');
            // Check if exactly 12 digits as requested
            if (/^\d{12}$/.test(cleanText)) {
                e.target.value = cleanText;
                e.target.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
            }
        } catch(err) {
            console.log('Clipboard read failed: ', err);
        }
    }
    
    if (reqTrackingNo) reqTrackingNo.addEventListener('click', handleTrackingClick);
    if (recTrackingNo) recTrackingNo.addEventListener('click', handleTrackingClick);

    
    // Default dates to today
    const reqDate = document.getElementById('req-date');
    if (reqDate) reqDate.value = new Date(new Date().getTime() - new Date().getTimezoneOffset() * 60000).toISOString().split('T')[0];
    const recDate = document.getElementById('rec-date');
    if (recDate) recDate.value = new Date(new Date().getTime() - new Date().getTimezoneOffset() * 60000).toISOString().split('T')[0];

    // Search on Return Request tab
    if(reqTrackingNo) {
        reqTrackingNo.addEventListener('keydown', async (e) => {
            if (e.key === 'Enter') {
                e.preventDefault();
                const no = reqTrackingNo.value.trim();
                if(!no) return;
                try {
                    const res = await fetch('/api/return/lookup?tracking_no=' + encodeURIComponent(no));
                    if(res.ok) {
                        const data = await res.json();
                        if(data.success && data.data) {
                            document.getElementById('req-mall').value = data.data.vendor || '';
                            document.getElementById('req-name').value = data.data.recipient_name || '';
                            document.getElementById('req-phone').value = data.data.recipient_phone || data.data.recipient_mobile || '';
                            document.getElementById('req-address').value = data.data.address || '';
                        }
                    }
                } catch(e) { console.error('Lookup failed', e); }
            }
        });
    }

    // Search on Return Receive tab
    if(recTrackingNo) {
        recTrackingNo.addEventListener('keydown', async (e) => {
            if (e.key === 'Enter') {
                e.preventDefault();
                const no = recTrackingNo.value.trim();
                if(!no) return;
                try {
                    // First try to find in return requests
                    const res1 = await fetch('/api/return/request?tracking_no=' + encodeURIComponent(no));
                    let foundInReq = false;
                    if(res1.ok) {
                        const data1 = await res1.json();
                        if(data1.success && data1.data && data1.data.length > 0) {
                            const item = data1.data[0];
                            document.getElementById('rec-mall').value = item.mall || '';
                            document.getElementById('rec-name').value = item.receiver_name || '';
                            document.getElementById('rec-phone').value = item.phone || '';
                            const reqType = item.request_type || '';
                            const reqRemarks = item.remarks || '';
                            const autoRemark = reqRemarks ? `${reqType}/${reqRemarks}` : reqType;
                            document.getElementById('rec-remarks').value = autoRemark;
                            if (item.address) document.getElementById('rec-address').value = item.address;
                            foundInReq = true;
                        }
                    }
                    
                    // If not found in requests, fallback to orderlist_db
                    if(!foundInReq) {
                        const res2 = await fetch('/api/return/lookup?tracking_no=' + encodeURIComponent(no));
                        if(res2.ok) {
                            const data2 = await res2.json();
                            if(data2.success && data2.data) {
                                document.getElementById('rec-mall').value = data2.data.vendor || '';
                                document.getElementById('rec-name').value = data2.data.recipient_name || '';
                                document.getElementById('rec-phone').value = data2.data.recipient_phone || data2.data.recipient_mobile || '';
                                document.getElementById('rec-address').value = data2.data.address || '';
                            }
                        }
                    }
                } catch(e) { console.error('Receive lookup failed', e); }
            }
        });
    }

    // Submit Return Request
    const formReq = document.getElementById('form-return-request');
    if(formReq) {
        formReq.addEventListener('submit', async (e) => {
            e.preventDefault();
            const payload = {
                request_date: document.getElementById('req-date').value,
                request_type: document.getElementById('req-type').value,
                receiver_name: document.getElementById('req-name').value,
                address: document.getElementById('req-address').value,
                phone: document.getElementById('req-phone').value,
                tracking_no: document.getElementById('req-tracking-no').value,
                mall: document.getElementById('req-mall').value,
                remarks: document.getElementById('req-remarks').value
            };
            const reqId = document.getElementById('req-id');
            if (reqId && reqId.value) {
                payload.id = parseInt(reqId.value, 10);
            }
            try {
                const res = await fetch('/api/return/request', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify(payload)
                });
                if(res.ok) {
                    formReq.reset();
                    document.getElementById('req-date').value = new Date(new Date().getTime() - new Date().getTimezoneOffset() * 60000).toISOString().split('T')[0];
                    if(reqId) reqId.value = '';
                    if (typeof loadReturnRequests === 'function') {
                        loadReturnRequests();
                    }
                    if (typeof loadReturnReceivings === 'function') {
                        loadReturnReceivings();
                    }
                } else {
                    alert('등록 실패');
                }
            } catch(e) { alert('오류 발생'); }
        });
    }
    // ============================================
    // PRODUCT SETTINGS TAB
    // ============================================
    window.productRulesGroupData = {};
    window.productRulesListData = {};

    function buildProductTab(data) {
        const container = document.getElementById('product-groups-container');
        if (!container) return;
        container.innerHTML = '';

        const groupNames = data['GROUP_NAMES'] || {};
        window.productRulesGroupData = {};
        window.productRulesListData = {};

        let groupIdCounter = 0;


        const order_group = groupNames.__order || Object.keys(groupNames).filter(k => k !== '__order');
        for (const gKey of order_group) {
            if (gKey === '__order') continue;
            const gName = groupNames[gKey];

            groupIdCounter++;
            const gId = `pgroup-${groupIdCounter}`;
            window.productRulesGroupData[gId] = { old_code: gKey, new_code: gKey, name: gName };

            const pList = data[gKey] || {};
            window.productRulesListData[gId] = [];

            const order_3 = pList.__order || Object.keys(pList).filter(k => k !== '__order');
            for (const pKey of order_3) {
                if (pKey === '__order') continue;
                const pVal = pList[pKey];

                if (pKey.startsWith('---separator_')) {
                    window.productRulesListData[gId].push({ is_separator: true });
                } else {
                    let is_free = pKey.startsWith('*');
                    let cleanKey = is_free ? pKey.substring(1) : pKey;

                    let color = '';
                    if (cleanKey.endsWith('_O')) { color = '_O'; cleanKey = cleanKey.slice(0, -2); }
                    else if (cleanKey.endsWith('_R')) { color = '_R'; cleanKey = cleanKey.slice(0, -2); }
                    else if (cleanKey.endsWith('_B')) { color = '_B'; cleanKey = cleanKey.slice(0, -2); }
                    else if (cleanKey.endsWith('_G')) { color = '_G'; cleanKey = cleanKey.slice(0, -2); }
                    else if (cleanKey.endsWith('_P')) { color = '_P'; cleanKey = cleanKey.slice(0, -2); }

                    let label = cleanKey;
                    let parts = pVal.split('|').map(s => s.trim());
                    let code = parts[0] || '';
                    let name = parts[1] || '';
                    let price = parts.length > 2 ? parseInt(parts[2], 10) : 0;
                    let dprice = parts.length > 3 ? parseInt(parts[3], 10) : 0;

                    window.productRulesListData[gId].push({
                        is_separator: false,
                        code, name, label, price, dprice, color, is_free
                    });
                }
            }

            renderProductGroup(gId, container);
        }

        const btnProductSave = document.getElementById('btn-product-save');
        if (btnProductSave) btnProductSave.style.backgroundColor = '';

        const markProductUnsaved = () => {
            if (btnProductSave) btnProductSave.style.backgroundColor = '#e53e3e';
        };

        container.addEventListener('input', markProductUnsaved);
        container.addEventListener('change', markProductUnsaved);
        container.addEventListener('click', (e) => {
            if (e.target.tagName === 'BUTTON') markProductUnsaved();
        });
    }

    function renderProductGroup(gId, parentContainer) {
        let card = document.getElementById(gId);
        if (!card) {
            card = document.createElement('div');
            card.id = gId;
            card.className = 'glass-card';
            card.style.padding = '10px 15px';
            card.style.marginBottom = '10px';
            card.style.width = 'max-content'; // 박스 전체 폭을 콘텐츠에 맞게 축소
            parentContainer.appendChild(card);
        }

        const gData = window.productRulesGroupData[gId];
        const items = window.productRulesListData[gId];
        const fmt = (v) => v ? parseInt(String(v).replace(/,/g, ''), 10).toLocaleString() : '';

        let html = `
            <div style="display: flex; justify-content: space-between; align-items: center; border-bottom: 2px solid #3182ce; padding-bottom: 5px; margin-bottom: 10px;">
                <div style="display: flex; gap: 10px; align-items: center;">
                    <span style="font-size: 1.5rem; font-weight: 800; color: #2c5282; margin: 0; padding-bottom: 4px;">${gData.name}</span>
                </div>
            </div>
            <div class="product-items-list" style="display: flex; flex-direction: column; gap: 0; min-height: 20px; border: 1px solid #cbd5e0; border-radius: 4px; overflow: hidden;">
        `;

        items.forEach((item, idx) => {
            if (item.is_separator) {
                html += `
                    <div class="item-row" data-idx="${idx}" style="background: #e2e8f0; display: flex; align-items: center; padding: 5px 8px; border-bottom: 1px solid #cbd5e0;">
                        <span class="drag-handle" style="margin-right: 15px; color: #718096; font-size: 1.2rem; cursor: grab;">☰</span>
                        <span style="color: #4a5568; font-size: 0.75rem; font-weight: bold; flex: 1;">--- 구분선 ---</span>
                        <button class="btn btn-danger btn-sm p-del" data-idx="${idx}" style="padding: 1px 4px; font-size: 0.7rem;">❌ 삭제</button>
                    </div>
                `;
            } else {
                html += `
                    <div class="item-row" data-idx="${idx}" style="background: #fff; padding: 5px 8px; display: flex; align-items: center; gap: 5px; border-bottom: 1px solid #e2e8f0;">
                        <span class="drag-handle" style="margin-right: 10px; color: #a0aec0; font-size: 1.1rem; cursor: grab;">☰</span>
                        <input type="text" class="p-label" value="${item.label}" placeholder="표기명(예: 오리)" style="width: 200px; padding: 2px 4px; font-size: 0.75rem;">
                        <input type="text" class="p-code" value="${item.code}" placeholder="코드" style="width: 90px; padding: 2px 4px; font-size: 0.75rem;">
                        <input type="text" class="p-name" value="${item.name}" placeholder="정식옵션명" style="width: 200px; padding: 2px 4px; font-size: 0.75rem;">
                        <input type="text" class="p-price" value="${fmt(item.price)}" placeholder="가격" style="width: 60px; padding: 2px 4px; font-size: 0.75rem; text-align: right;">
                        <input type="text" class="p-dprice" value="${fmt(item.dprice)}" placeholder="2+1가격" style="width: 60px; padding: 2px 4px; font-size: 0.75rem; text-align: right;">
                        
                        <div class="color-options" style="display: flex; gap: 8px; align-items: center; border: 1px solid #cbd5e0; padding: 2px 8px; border-radius: 4px; font-size: 0.7rem; background:#f7fafc;">
                            <label style="cursor:pointer;"><input type="radio" name="color-${gId}-${idx}" value="" ${item.color === '' ? 'checked' : ''}> 기본</label>
                            <label style="color:#dd6b20; cursor:pointer;"><input type="radio" name="color-${gId}-${idx}" value="_O" ${item.color === '_O' ? 'checked' : ''}> 주황</label>
                            <label style="color:#e53e3e; cursor:pointer;"><input type="radio" name="color-${gId}-${idx}" value="_R" ${item.color === '_R' ? 'checked' : ''}> 빨강</label>
                            <label style="color:#3182ce; cursor:pointer;"><input type="radio" name="color-${gId}-${idx}" value="_B" ${item.color === '_B' ? 'checked' : ''}> 파랑</label>
                            <label style="color:#38a169; cursor:pointer;"><input type="radio" name="color-${gId}-${idx}" value="_G" ${item.color === '_G' ? 'checked' : ''}> 초록</label>
                            <label style="color:#d53f8c; cursor:pointer;"><input type="radio" name="color-${gId}-${idx}" value="_P" ${item.color === '_P' ? 'checked' : ''}> 핑크</label>
                        </div>
                        
                        <label style="font-size: 0.75rem; display: inline-flex; align-items: center; gap: 3px; cursor: pointer; white-space: nowrap; margin-left: 10px;">
                            <input type="checkbox" class="p-free" ${item.is_free ? 'checked' : ''}> 🚚무료배송
                        </label>
                        <button class="btn btn-danger btn-sm p-del" data-idx="${idx}" style="padding: 1px 4px; font-size: 0.7rem; margin-left: 5px;">❌ 삭제</button>
                        
                        <div style="flex: 1; min-width: 0;"></div>
                    </div>
                `;
            }
        });

        html += `
            </div>
            <div style="display: flex; gap: 10px; margin-top: 8px;">
                <button class="btn btn-primary btn-sm btn-add-item" style="font-size: 0.75rem;">+ 상품 추가</button>
                <button class="btn btn-secondary btn-sm btn-add-sep" style="font-size: 0.75rem;">+ 구분선 추가</button>
            </div>
        `;

        card.innerHTML = html;

        const rows = card.querySelectorAll('.product-items-list > .item-row');
        rows.forEach((row, i) => {
            if (!items[i].is_separator) {
                row.querySelector('.p-label').addEventListener('input', e => items[i].label = e.target.value);
                row.querySelector('.p-code').addEventListener('input', e => items[i].code = e.target.value);
                row.querySelector('.p-name').addEventListener('input', e => items[i].name = e.target.value);

                ['.p-price', '.p-dprice'].forEach(sel => {
                    row.querySelector(sel).addEventListener('input', e => {
                        let val = e.target.value.replace(/[^0-9]/g, '');
                        if (sel === '.p-price') items[i].price = parseInt(val, 10) || 0;
                        else items[i].dprice = parseInt(val, 10) || 0;
                        e.target.value = val ? parseInt(val, 10).toLocaleString() : '';
                    });
                });

                row.querySelectorAll(`input[name="color-${gId}-${i}"]`).forEach(radio => {
                    radio.addEventListener('change', e => { if (e.target.checked) items[i].color = e.target.value; });
                });

                row.querySelector('.p-free').addEventListener('change', e => items[i].is_free = e.target.checked);
            }
        });

        // SortableJS for bulletproof drag & drop
        new Sortable(card.querySelector('.product-items-list'), {
            handle: '.drag-handle',
            animation: 150,
            onEnd: function (evt) {
                if (evt.oldIndex !== evt.newIndex) {
                    const movedItem = items.splice(evt.oldIndex, 1)[0];
                    items.splice(evt.newIndex, 0, movedItem);
                    const btnSave = document.getElementById('btn-product-save');
                    if (btnSave) btnSave.style.backgroundColor = '#e53e3e';
                    // Optional: renderProductGroup() if we need to sync data-idx, but items array is already updated in sync with DOM!
                    // It's safer to re-render to attach listeners based on new indices though:
                    renderProductGroup(gId, parentContainer);
                }
            }
        });

        card.querySelectorAll('.p-del').forEach(b => {
            b.addEventListener('click', e => {
                const parent = document.getElementById('product-groups-container');
                const y = parent ? parent.scrollTop : 0;
                const i = parseInt(e.target.dataset.idx, 10);
                items.splice(i, 1);
                renderProductGroup(gId, parentContainer);
                if (parent) requestAnimationFrame(() => parent.scrollTo(0, y));
            });
        });
        card.querySelector('.btn-add-item').addEventListener('click', (e) => {
            e.preventDefault();
            const parent = document.getElementById('product-groups-container');
            const y = parent ? parent.scrollTop : 0;
            items.push({ is_separator: false, code: '', name: '', label: '', price: 0, dprice: 0, color: '', is_free: false });
            renderProductGroup(gId, parentContainer);
            if (parent) requestAnimationFrame(() => parent.scrollTo(0, y));
        });
        card.querySelector('.btn-add-sep').addEventListener('click', (e) => {
            e.preventDefault();
            const parent = document.getElementById('product-groups-container');
            const y = parent ? parent.scrollTop : 0;
            items.push({ is_separator: true });
            renderProductGroup(gId, parentContainer);
            if (parent) requestAnimationFrame(() => parent.scrollTo(0, y));
        });
    }

    const _btnProdSave = document.getElementById('btn-product-save');
    if (_btnProdSave) {
        _btnProdSave.addEventListener('click', () => {
            const payload = { groups: [], products: {} };
            // window.productRulesGroupData
            for (const gId in window.productRulesGroupData) {
                const gData = window.productRulesGroupData[gId];
                if (gData.new_code && gData.name) {
                    payload.groups.push(gData);
                    payload.products[gData.new_code] = window.productRulesListData[gId];
                }
            }

            document.getElementById('btn-product-save').innerText = '저장 중...';

            fetch('/api/products/settings', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(payload)
            }).then(r => {
                if (!r.ok) throw new Error("Network response was not ok (status " + r.status + ")");
                return r.json();
            }).then(res => {
                alert("상품 설정이 저장되었습니다.");
                document.getElementById('btn-product-save').innerText = '상품 설정 저장';
                fetch('/api/config').then(r => r.json()).then(d => {
                    configData = d;
                    document.getElementById('btn-product-save').style.backgroundColor = '';

                    // Clear all UI and rebuild
                    const oc = document.getElementById('order-items-container');
                    if (oc) oc.innerHTML = '';

                    buildOrderTab(configData);
                    buildGiftTab(configData);
                    buildProductTab(configData);
                });
            }).catch(err => {
                console.error(err);
                alert("저장 실패!");
                document.getElementById('btn-product-save').innerText = '상품 설정 저장';
            });
        });
    }

    const btnCopyManual = document.getElementById('btn-copy-manual-total');
    if (btnCopyManual) {
        btnCopyManual.addEventListener('click', () => {
            const count = document.getElementById('manual-total-count').textContent;
            const amount = document.getElementById('manual-total-amount').textContent;
            const textToCopy = `수기 주문: ${count}건 / ${amount}원`;

            navigator.clipboard.writeText(textToCopy).then(() => {
                const toast = document.getElementById('toast-notification');
                if (toast) {
                    toast.style.opacity = '1';
                    setTimeout(() => {
                        toast.style.opacity = '0';
                    }, 1500);
                }
            }).catch(err => {
                console.error('Failed to copy', err);
            });
        });
    }
    
    // ============================================
    // CODE TAB (Master Data Mgmt)
    // ============================================
    function initCodeTab() {
        const btnAddSin = document.getElementById('btn-add-single');
        const btnAddSet = document.getElementById('btn-add-set');
        if (!btnAddSin) return;

        let editingSingleCode = null;
        let editingSetCode = null;
        let singleItemsList = [];
        let setItemsList = [];
        let singleSort = { key: 'item_code', asc: true };
        let setSort = { key: 'item_code', asc: true };

        // Render Single Items
        const renderSingleItems = () => {
            const tbody = document.getElementById('single-items-tbody');
            tbody.innerHTML = '';
            
            singleItemsList.sort((a,b) => {
                let valA = a[singleSort.key] || '';
                let valB = b[singleSort.key] || '';
                if(valA < valB) return singleSort.asc ? -1 : 1;
                if(valA > valB) return singleSort.asc ? 1 : -1;
                return 0;
            });

            singleItemsList.forEach(item => {
                const tr = document.createElement('tr');
                tr.className = 'hover-row';
                tr.style.height = '27px';
                tr.style.borderBottom = '1px solid #e2e8f0';
                tr.innerHTML = `
                    <td style="padding: 0 10px; font-size: 0.85rem;">${item.item_code}</td>
                    <td style="padding: 0 5px; font-size: 0.75rem; color: #718096;">${item.sabangnet_code}</td>
                    <td style="padding: 0 10px; font-size: 0.85rem;">${item.name}</td>
                    <td style="padding: 0 5px; text-align: right; vertical-align: middle;">
                        <div style="display: flex; gap: 8px; justify-content: flex-end; align-items: center; height: 100%;">
                            <button class="btn btn-sm btn-edit-sin" style="padding:2px; display:flex; align-items:center; background:transparent; color:#4a5568; box-shadow:none; border:none; cursor:pointer;" data-code="${item.item_code}" title="수정">
                                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>
                            </button>
                            <button class="btn btn-sm btn-del-sin" style="padding:2px; display:flex; align-items:center; background:transparent; color:#e53e3e; box-shadow:none; border:none; cursor:pointer;" data-code="${item.item_code}" title="삭제">
                                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>
                            </button>
                        </div>
                    </td>
                `;
                tbody.appendChild(tr);
            });
            
            document.querySelectorAll('.th-sortable[data-list="single"]').forEach(th => {
                const icon = th.querySelector('.sort-icon');
                if(!icon) return;
                if(th.dataset.key === singleSort.key) {
                    icon.innerText = singleSort.asc ? '▲' : '▼';
                    icon.style.color = '#3182ce';
                } else {
                    icon.innerText = '↕';
                    icon.style.color = '#e2e8f0';
                }
            });
        };

        // Load data
        const loadSingleItems = () => {
            return fetch('/api/codes/single').then(r=>r.json()).then(res => {
                singleItemsList = res.data;
                renderSingleItems();
            });
        };
        const renderSetItems = () => {
            const tbody = document.getElementById('set-items-tbody');
            tbody.innerHTML = '';
            
            let tooltip = document.getElementById('set-comp-tooltip');
            if (!tooltip) {
                tooltip = document.createElement('div');
                tooltip.id = 'set-comp-tooltip';
                tooltip.style.position = 'fixed';
                tooltip.style.background = '#fff';
                tooltip.style.border = '1px solid #cbd5e0';
                tooltip.style.padding = '8px';
                tooltip.style.borderRadius = '5px';
                tooltip.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)';
                tooltip.style.display = 'none';
                tooltip.style.zIndex = '9999';
                tooltip.style.pointerEvents = 'none';
                tooltip.style.flexDirection = 'column';
                tooltip.style.gap = '2px';
                document.body.appendChild(tooltip);
            }
            
            const mapCompInfo = c => {
                const sInfo = singleItemsList.find(s => s.item_code === c.single_code);
                let displayName = sInfo ? sInfo.name : c.single_code;
                displayName = displayName.replace(/미라클 통 /g, '').trim();
                const isHwangto = displayName.includes('황토');
                const bg = isHwangto ? 'background:#feebc8;' : 'background:#edf2f7;';
                const border = isHwangto ? 'border:1px solid #fbd38d;' : 'border:1px solid #cbd5e0;';
                const qtyColor = isHwangto ? '#dd6b20' : '#3182ce';
                const textColor = isHwangto ? 'color:#c05621;' : '';
                return `<span class="comp-span" style="display:inline-block; ${bg} ${border} padding:1px 4px; border-radius:3px; font-size:0.75rem; margin:1px; ${textColor}">${displayName} <b style="color:${qtyColor};">${c.quantity}</b></span>`;
            };
            
            setItemsList.sort((a,b) => {
                let valA = a[setSort.key] || '';
                let valB = b[setSort.key] || '';
                if(valA < valB) return setSort.asc ? -1 : 1;
                if(valA > valB) return setSort.asc ? 1 : -1;
                return 0;
            });

            setItemsList.forEach(item => {
                const tr = document.createElement('tr');
                tr.className = 'hover-row';
                tr.style.height = '27px';
                tr.style.borderBottom = '1px solid #e2e8f0';
                
                const compsHtml = item.components.map(mapCompInfo).join('');
                
                tr.innerHTML = `
                    <td style="padding: 0 10px; font-weight:bold; font-size: 0.85rem;">${item.item_code}</td>
                    <td style="padding: 0 10px; font-size: 0.85rem; white-space: nowrap;">${item.name || ''}</td>
                    <td class="comps-cell" style="padding: 4px 10px; line-height: 1.2; width: 100%; max-width: 1px;">
                        <div class="comps-wrapper" style="white-space: nowrap; overflow: hidden; position: relative; padding-right: 48px;">
                            ${compsHtml}
                            <span class="more-indicator" style="display:none; color:#e53e3e; font-weight:bold; font-size:0.8rem; cursor:default; position: absolute; right: 0; background: transparent; padding-left: 2px;"></span>
                        </div>
                    </td>
                    <td style="padding: 0 5px; text-align: right; vertical-align: middle;">
                        <div style="display: flex; gap: 8px; justify-content: flex-end; align-items: center; height: 100%;">
                            <button class="btn btn-sm btn-edit-set" style="padding:2px; display:flex; align-items:center; background:transparent; color:#4a5568; box-shadow:none; border:none; cursor:pointer;" data-code="${item.item_code}" title="수정">
                                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>
                            </button>
                            <button class="btn btn-sm btn-del-set" style="padding:2px; display:flex; align-items:center; background:transparent; color:#e53e3e; box-shadow:none; border:none; cursor:pointer;" data-code="${item.item_code}" title="삭제">
                                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>
                            </button>
                        </div>
                    </td>
                `;
                tr._itemComps = item.components;
                tbody.appendChild(tr);
            });
            
            // 모든 행이 그려진 후 브라우저가 그리드를 계산할 여유를 주기 위해 지연실행
            setTimeout(() => {
                const rows = tbody.querySelectorAll('tr');
                rows.forEach(tr => {
                    const wrapper = tr.querySelector('.comps-wrapper');
                    if (!wrapper) return;
                    const spans = wrapper.querySelectorAll('.comp-span');
                    const indicator = wrapper.querySelector('.more-indicator');

                    if (spans.length > 0) {
                        let hiddenCount = 0;
                        let lastVisibleIndex = spans.length - 1;
                        
                        // X좌표를 기준으로 컨테이너를 벗어나는 아이템 탐색
                        const maxLimit = wrapper.offsetWidth - 48; // 오른쪽 48px는 '외 N개' 표기를 위해 예약
                        for (let i = 0; i < spans.length; i++) {
                            if (spans[i].offsetLeft + spans[i].offsetWidth > maxLimit) {
                                lastVisibleIndex = i - 1;
                                break;
                            }
                        }

                        if (lastVisibleIndex < spans.length - 1 && lastVisibleIndex >= 0) {
                            hiddenCount = spans.length - 1 - lastVisibleIndex;
                            
                            for (let i = lastVisibleIndex + 1; i < spans.length; i++) {
                                spans[i].style.display = 'none';
                            }
                            
                            indicator.innerText = `외 ${hiddenCount}개`;
                            indicator.style.display = 'inline-block';
                        } else if (lastVisibleIndex < 0 && spans.length > 1) {
                            // 매우 좁은 공간일 경우 적어도 1개는 숨기고 처리
                            hiddenCount = spans.length - 1;
                            for (let i = 1; i < spans.length; i++) {
                                spans[i].style.display = 'none';
                            }
                            indicator.innerText = `외 ${hiddenCount}개`;
                            indicator.style.display = 'inline-block';
                        }
                        
                        if (hiddenCount > 0 && tr._itemComps) {
                            const compsCell = tr.querySelector('.comps-cell');
                            compsCell.addEventListener('mouseenter', (e) => {
                                compsCell._hoverTimeout = setTimeout(() => {
                                    tooltip.innerHTML = tr._itemComps.map(mapCompInfo).map(html => `<div>${html}</div>`).join('');
                                    tooltip.style.display = 'flex';
                                    tooltip.style.left = (e.clientX + 40) + 'px';
                                    tooltip.style.top = (e.clientY - 10) + 'px';
                                }, 1000);
                            });
                            compsCell.addEventListener('mousemove', (e) => {
                                if (tooltip.style.display === 'flex') {
                                    tooltip.style.left = (e.clientX + 40) + 'px';
                                    tooltip.style.top = (e.clientY - 10) + 'px';
                                }
                            });
                            compsCell.addEventListener('mouseleave', () => {
                                clearTimeout(compsCell._hoverTimeout);
                                tooltip.style.display = 'none';
                            });
                        }
                    }
                });
            }, 50);
            
            document.querySelectorAll('.th-sortable[data-list="set"]').forEach(th => {
                const icon = th.querySelector('.sort-icon');
                if(!icon) return;
                if(th.dataset.key === setSort.key) {
                    icon.innerText = setSort.asc ? '▲' : '▼';
                    icon.style.color = '#3182ce';
                } else {
                    icon.innerText = '↕';
                    icon.style.color = '#e2e8f0';
                }
            });
        };

        const loadSetItems = () => {
            return fetch('/api/codes/set').then(r=>r.json()).then(res => {
                setItemsList = res.data;
                renderSetItems();
            });
        };

        const loadSingleItemsAndSetItems = () => {
             loadSingleItems().then(() => loadSetItems());
        };

        window.reRenderSetItemsForWrap = () => {
            if (setItemsList && setItemsList.length > 0) renderSetItems();
        };

        window.addEventListener('resize', () => {
            if(document.getElementById('code-tab').classList.contains('active')) {
                clearTimeout(window._setItemsResizeTimer);
                window._setItemsResizeTimer = setTimeout(() => {
                    if (setItemsList && setItemsList.length > 0) renderSetItems();
                }, 100);
            }
        });

        loadSingleItemsAndSetItems();

        // Sorting events
        document.querySelectorAll('.th-sortable').forEach(th => {
            th.addEventListener('click', (e) => {
                const listType = th.dataset.list;
                const key = th.dataset.key;
                if(listType === 'single') {
                    if(singleSort.key === key) singleSort.asc = !singleSort.asc;
                    else { singleSort.key = key; singleSort.asc = true; }
                    renderSingleItems();
                } else if(listType === 'set') {
                    if(setSort.key === key) setSort.asc = !setSort.asc;
                    else { setSort.key = key; setSort.asc = true; }
                    renderSetItems();
                }
            });
        });

        document.getElementById('code-tab').addEventListener('click', (e) => {
            if(e.target.parentElement && e.target.parentElement.classList.contains('btn-del-sin')) return; // ignore if click is inside not button
            const btnDelSin = e.target.closest('.btn-del-sin');
            if(btnDelSin) {
                if(confirm('단품 항목을 삭제하시겠습니까? (연결된 세트 구성품도 삭제될 수 있습니다)')) {
                    fetch('/api/codes/single/' + btnDelSin.dataset.code, {method: 'DELETE'}).then(()=> loadSingleItemsAndSetItems());
                }
                return;
            }
            
            const btnDelSet = e.target.closest('.btn-del-set');
            if(btnDelSet) {
                if(confirm('세트 항목을 삭제하시겠습니까?')) {
                    fetch('/api/codes/set/' + btnDelSet.dataset.code, {method: 'DELETE'}).then(()=> { setItemsList = []; loadSetItems(); });
                }
                return;
            }
            
            const btnEditSin = e.target.closest('.btn-edit-sin');
            if(btnEditSin) {
                const code = btnEditSin.dataset.code;
                fetch('/api/codes/single').then(r=>r.json()).then(res => {
                    const item = res.data.find(d => d.item_code === code);
                    if(item) {
                        editingSingleCode = code;
                        document.getElementById('modal-single-title').innerText = '📦 단품 수정';
                        document.getElementById('sin-item-code').value = item.item_code;
                        document.getElementById('sin-item-code').disabled = true;
                        document.getElementById('sin-sabangnet-code').value = item.sabangnet_code;
                        document.getElementById('sin-name').value = item.name;
                        document.getElementById('single-item-modal').style.display = 'flex';
                    }
                });
            }
            const btnEditSet = e.target.closest('.btn-edit-set');
            if(btnEditSet) {
                const code = btnEditSet.dataset.code;
                fetch('/api/codes/set').then(r=>r.json()).then(res => {
                    const item = res.data.find(d => d.item_code === code);
                    if(item) {
                        editingSetCode = code;
                        document.getElementById('modal-set-title').innerText = '🍱 세트 수정';
                        document.getElementById('set-item-code').value = item.item_code;
                        document.getElementById('set-item-code').disabled = true;
                        document.getElementById('set-name').value = item.name;
                        const wrapper = document.getElementById('set-components-wrapper');
                        wrapper.innerHTML = '';
                        item.components.forEach(c => addSetComponentRow(c.single_code, c.quantity));
                        document.getElementById('set-item-modal').style.display = 'flex';
                    }
                });
            }
        });

        // Single Modal
        const sinItemCodeInput = document.getElementById('sin-item-code');
        const sinItemWarn = document.getElementById('sin-item-warn');
        
        sinItemCodeInput.addEventListener('input', (e) => {
            let val = e.target.value.toUpperCase();
            e.target.value = val;
            if (val.length > 0 && !/^[A-Z]/.test(val)) {
                sinItemWarn.textContent = '⚠️ 아이템 코드 첫 글자는 영문이어야 합니다.';
                sinItemWarn.style.display = 'block';
            } else if(!editingSingleCode && val && singleItemsList.some(s => s.item_code === val)) {
                sinItemWarn.textContent = '⚠️ 이미 존재하는 단품 코드입니다!';
                sinItemWarn.style.display = 'block';
            } else {
                sinItemWarn.style.display = 'none';
            }
        });

        btnAddSin.addEventListener('click', () => {
            editingSingleCode = null;
            document.getElementById('modal-single-title').innerText = '📦 새 단품 추가';
            sinItemCodeInput.value = '';
            sinItemCodeInput.disabled = false;
            if(sinItemWarn) sinItemWarn.style.display = 'none';
            document.getElementById('sin-sabangnet-code').value = '';
            document.getElementById('sin-name').value = '';
            document.getElementById('single-item-modal').style.display = 'flex';
        });
        document.getElementById('btn-sin-cancel').addEventListener('click', () => {
            document.getElementById('single-item-modal').style.display = 'none';
        });
        document.getElementById('btn-sin-save').addEventListener('click', () => {
            const itemCode = document.getElementById('sin-item-code').value.trim();
            let sabangnet = document.getElementById('sin-sabangnet-code').value.trim();
            const name = document.getElementById('sin-name').value.trim();
            if(!itemCode || !sabangnet || !name) { alert('모든 항목을 입력해주세요.'); return; }
            
            if (itemCode.length > 0 && !/^[A-Z]/.test(itemCode)) {
                alert('아이템 코드의 첫 글자는 반드시 영문이어야 합니다!');
                return;
            }

            if(!editingSingleCode && singleItemsList.some(s => s.item_code === itemCode)) {
                alert('이미 존재하는 단품 아이템 코드입니다!');
                return;
            }
            if(!sabangnet.endsWith('-0001')) sabangnet += '-0001';
            
            const payload = {item_code: itemCode, sabangnet_code: sabangnet, name: name};
            const method = editingSingleCode ? 'PUT' : 'POST';
            const url = editingSingleCode ? '/api/codes/single/' + encodeURIComponent(editingSingleCode) : '/api/codes/single';
            
            fetch(url, {
                method: method, headers: {'Content-Type': 'application/json'}, body: JSON.stringify(payload)
            }).then(r => r.json()).then(res => {
                if(res.detail) { alert(res.detail); }
                else {
                    document.getElementById('single-item-modal').style.display = 'none';
                    loadSingleItems();
                }
            });
        });
        
        // Single sabangnet auto append -0001 on blur
        document.getElementById('sin-sabangnet-code').addEventListener('blur', (e) => {
             let val = e.target.value.trim();
             if(val && !val.endsWith('-0001') && !val.includes('-')) {
                  e.target.value = val + '-0001';
             }
        });

        // Set Modal
        const setItemCodeInput = document.getElementById('set-item-code');
        const setItemWarn = document.getElementById('set-item-warn');
        
        setItemCodeInput.addEventListener('input', (e) => {
            let val = e.target.value.toUpperCase();
            e.target.value = val;
            if (val.length > 0 && !/^[A-Z]/.test(val)) {
                setItemWarn.textContent = '⚠️ 아이템 코드 첫 글자는 영문이어야 합니다.';
                setItemWarn.style.display = 'block';
            } else if(!editingSetCode && val && setItemsList.some(s => s.item_code === val)) {
                setItemWarn.textContent = '⚠️ 이미 존재하는 세트 코드입니다!';
                setItemWarn.style.display = 'block';
            } else {
                setItemWarn.style.display = 'none';
            }
        });

        const addSetComponentRow = (sc = '', qt = 1) => {
             const div = document.createElement('div');
             div.style.display = 'flex';
             div.style.gap = '5px';
             
             let optionsHtml = '<option value="">단품코드 선택</option>';
             singleItemsList.forEach(s => {
                 const selected = (s.item_code === sc) ? 'selected' : '';
                 optionsHtml += `<option value="${s.item_code}" ${selected}>[${s.item_code}] ${s.name}</option>`;
             });

             div.innerHTML = `
                 <select class="comp-code" style="flex:1; padding: 4px; border: 1px solid #cbd5e0; border-radius: 4px;">
                     ${optionsHtml}
                 </select>
                 <input type="number" class="comp-qty" min="1" value="${qt}" style="width:60px; padding: 4px; border: 1px solid #cbd5e0; border-radius: 4px;">
                 <button class="btn btn-sm comp-del" style="background:#e53e3e; padding:4px 8px;" title="삭제">X</button>
             `;
             div.querySelector('.comp-del').addEventListener('click', () => div.remove());
             document.getElementById('set-components-wrapper').appendChild(div);
        };
        
        btnAddSet.addEventListener('click', () => {
            editingSetCode = null;
            document.getElementById('modal-set-title').innerText = '🍱 새 세트 추가';
            setItemCodeInput.value = '';
            setItemCodeInput.disabled = false;
            if(setItemWarn) setItemWarn.style.display = 'none';
            document.getElementById('set-name').value = '';
            document.getElementById('set-components-wrapper').innerHTML = '';
            addSetComponentRow(); 
            document.getElementById('set-item-modal').style.display = 'flex';
        });
        document.getElementById('btn-add-set-component').addEventListener('click', () => {
            addSetComponentRow();
        });
        document.getElementById('btn-set-cancel').addEventListener('click', () => {
            document.getElementById('set-item-modal').style.display = 'none';
        });
        document.getElementById('btn-set-save').addEventListener('click', () => {
            const itemCode = document.getElementById('set-item-code').value.trim();
            const name = document.getElementById('set-name').value.trim();
            if(!itemCode) { alert('세트 아이템 코드를 입력해주세요.'); return; }
            
            if (itemCode.length > 0 && !/^[A-Z]/.test(itemCode)) {
                alert('아이템 코드의 첫 글자는 반드시 영문이어야 합니다!');
                return;
            }
            
            if(!editingSetCode && setItemsList.some(s => s.item_code === itemCode)) {
                alert('이미 존재하는 세트 아이템 코드입니다!');
                return;
            }
            
            const components = [];
            const rows = document.getElementById('set-components-wrapper').querySelectorAll('div');
            rows.forEach(r => {
                const sc = r.querySelector('.comp-code').value.trim();
                const qt = parseInt(r.querySelector('.comp-qty').value, 10);
                if(sc && !isNaN(qt) && qt > 0) {
                    components.push({single_code: sc, quantity: qt});
                }
            });
            
            if(components.length === 0) { alert('유효한 단품 구성품을 최소 1개 이상 선택해주세요.'); return; }
            
            const payload = {item_code: itemCode, components: components, sabangnet_code: "", name: name};
            const method = editingSetCode ? 'PUT' : 'POST';
            const url = editingSetCode ? '/api/codes/set/' + encodeURIComponent(editingSetCode) : '/api/codes/set';
            
            fetch(url, {
                method: method, headers: {'Content-Type': 'application/json'}, body: JSON.stringify(payload)
            }).then(r => r.json()).then(res => {
                if(res.detail) { alert(res.detail); }
                else {
                    document.getElementById('set-item-modal').style.display = 'none';
                    loadSetItems();
                }
            });
        });
    }

    initCodeTab();
});

    const btnEmailReq = document.getElementById('btn-email-req');
    if (btnEmailReq) {
        btnEmailReq.addEventListener('click', async () => {
            const checkedBoxes = document.querySelectorAll('.chk-req-row:checked');
            if (checkedBoxes.length === 0) {
                alert('이메일로 보낼 반품 신청 항목을 선택해주세요.');
                return;
            }
            
            const d = new Date();
            const yyyy = d.getFullYear();
            const m = String(d.getMonth() + 1).padStart(2, '0');
            const dd = String(d.getDate()).padStart(2, '0');
            const days = ['일', '월', '화', '수', '목', '금', '토'];
            const dow = days[d.getDay()];
            const subject = `★ ${yyyy}년 ${m}월 ${dd}일(${dow}) 미라네주방 반품 신청`;
            
            let plainTextGreeting = "안녕하세요.\r\n오늘 반품 신청합니다.\r\n내용은 아래와 같습니다.\r\n감사합니다.\r\n\r\n";
            let ptIndex = 1;
            checkedBoxes.forEach(cb => {
                try {
                    const item = JSON.parse(cb.dataset.item);
                    let ptStatus = item.request_type || '';
                    if (ptStatus === '맞교환') {
                        ptStatus = '★맞교환★';
                    }
                    plainTextGreeting += `${ptIndex}. 이름: ${item.receiver_name || ''} / 연락처: ${item.phone || ''} / 송장번호: ${item.tracking_no || ''} / 상태: ${ptStatus}

`;
                    ptIndex++;
                } catch(e) {}
            });
            
            
            let htmlTable = `
            <table border="1" style="border-collapse: collapse; font-family: '맑은 고딕', sans-serif; font-size: 10pt; text-align: center;">
                <thead>
                    <tr style="background-color: #f2f2f2;">
                        <th style="padding: 8px;">번호</th>
                        <th style="padding: 8px;">이름</th>
                        <th style="padding: 8px;">전화번호</th>
                        <th style="padding: 8px;">송장번호</th>
                        <th style="padding: 8px;">상태</th>
                    </tr>
                </thead>
                <tbody>
            `;
            
            let index = 1;
            checkedBoxes.forEach(cb => {
                try {
                    const item = JSON.parse(cb.dataset.item);
                    let statusText = item.request_type || '';
                    let trStyle = '';
                    if (statusText === '맞교환') {
                        trStyle = ' style="font-weight: bold; color: red;"';
                    }
                    htmlTable += `
                    <tr${trStyle}>
                        <td style="padding: 8px;">${index++}</td>
                        <td style="padding: 8px;">${item.receiver_name || ''}</td>
                        <td style="padding: 8px; mso-number-format:'\@';">${item.phone || ''}</td>
                        <td style="padding: 8px; mso-number-format:'\@';">${item.tracking_no || ''}</td>
                        <td style="padding: 8px;">${statusText}</td>
                    </tr>
                    `;
                } catch(e) {}
            });
            htmlTable += `</tbody></table>`;
            
            try {
                const blobHtml = new Blob([htmlTable], { type: 'text/html' });
                const blobText = new Blob(["표가 클립보드에 복사되었습니다. 메일 본문에 붙여넣기 하세요."], { type: 'text/plain' });
                const data = new ClipboardItem({
                    'text/html': blobHtml,
                    'text/plain': blobText
                });
                navigator.clipboard.write([data]).then(() => {
                    showToast("표가 클립보드에 복사되었습니다! 아웃룩 본문에 '붙여넣기(Ctrl+V)' 하세요.");
                    setTimeout(() => {
                        const mailtoLink = `mailto:skylove6969@hanmail.net?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(plainTextGreeting)}`;
                        window.location.href = mailtoLink;
                    }, 1000);
                }).catch(err => {
                    alert('클립보드 복사에 실패했습니다.');
                    const mailtoLink = `mailto:skylove6969@hanmail.net?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(plainTextGreeting)}`;
                    window.location.href = mailtoLink;
                });
            } catch(e) {
                const mailtoLink = `mailto:skylove6969@hanmail.net?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(plainTextGreeting)}`;
                window.location.href = mailtoLink;
            }
        });
    }


// Clear form when clicking empty space around inputs
function handleFormEmptyClick(e, formId) {
    // If the click is on an input, select, button, label, or textarea, do nothing
    if (e.target.tagName === 'INPUT' || e.target.tagName === 'SELECT' || e.target.tagName === 'BUTTON' || e.target.tagName === 'LABEL' || e.target.tagName === 'TEXTAREA') return;
    if (e.target.closest('button')) return;
    
    // Otherwise it's an empty space click
    const form = document.getElementById(formId);
    if (form) {
        form.reset();
        // Reset hidden IDs and dates
        if (formId === 'form-return-request') {
            const reqId = document.getElementById('req-id');
            if (reqId) reqId.value = '';
            const reqDate = document.getElementById('req-date');
            if (reqDate) reqDate.value = new Date(new Date().getTime() - new Date().getTimezoneOffset() * 60000).toISOString().split('T')[0];
        } else if (formId === 'form-return-receive') {
            const recId = document.getElementById('rec-id');
            if (recId) recId.value = '';
            const recDate = document.getElementById('rec-date');
            if (recDate) recDate.value = new Date(new Date().getTime() - new Date().getTimezoneOffset() * 60000).toISOString().split('T')[0];
        }
    }
}

const reqFormContainer = document.getElementById('form-return-request');
if (reqFormContainer) {
    reqFormContainer.addEventListener('click', (e) => handleFormEmptyClick(e, 'form-return-request'));
}

const recFormContainer = document.getElementById('form-return-receive');
if (recFormContainer) {
    recFormContainer.addEventListener('click', (e) => handleFormEmptyClick(e, 'form-return-receive'));
}

// ============================================
// Version Update Notice
// ============================================
document.addEventListener('DOMContentLoaded', () => {
    let CURRENT_APP_VERSION = "8.54";
    const versionEl = document.getElementById('app-version-text');
    if (versionEl) {
        const text = versionEl.textContent.trim();
        const match = text.match(/Ver\s+([0-9.]+)/i);
        if (match) {
            CURRENT_APP_VERSION = match[1];
        }
    }
    const updateModal = document.getElementById('update-notice-modal');
    if (updateModal) {
        document.getElementById('update-notice-version').textContent = CURRENT_APP_VERSION;
        const storageKey = `hide_update_popup_${CURRENT_APP_VERSION}`;
        
        if (localStorage.getItem(storageKey) !== 'true') {
            updateModal.style.display = 'flex';
        }
        
        document.getElementById('btn-close-update-notice').addEventListener('click', () => {
            if (document.getElementById('chk-hide-update-notice').checked) {
                localStorage.setItem(storageKey, 'true');
            }
            updateModal.style.display = 'none';
            
            // Switch to Version History tab
            const historyTab = document.querySelector('[data-tab="version-history-tab"]');
            if (historyTab) {
                historyTab.click();
            }
        });
    }
});
