// file: report.js

function generateCashierReport(jualData, pesaniData, posSettings, userData, options, cartData) {
    const width = 42;
    let report = [];

    // Fungsi helper (tidak ada perubahan)
    function centerText(text) {
        const padding = Math.max(0, width - text.length);
        const left = Math.floor(padding / 2);
        const right = padding - left;
        return ' '.repeat(left) + text + ' '.repeat(right);
    }
    function padRight(text, len) {
        text = String(text);
        return text + ' '.repeat(Math.max(0, len - text.length));
    }
    function padLeft(text, len) {
        text = String(text);
        return ' '.repeat(Math.max(0, len - text.length)) + text;
    }
    function formatCurrency(amount) {
        return Math.round(Number(amount)).toLocaleString('id-ID');
    }

    // --- HEADER ---
    report.push(centerText(posSettings.alamat_resto || 'Alamat Resto'));
    report.push('');
    report.push(centerText('REPORT KASIR HARIAN'));
    report.push('');
    report.push(`tanggal: ${options.startDate} sd ${options.endDate}`);
    report.push(`Kasir   : ${options.kasir}`);
    report.push('');

    // --- Filter valid jual ---
    const validJual = jualData.filter(j => !['1', 1, 'true', true].includes(j.batal));
    if (validJual.length === 0) {
        report.push('TIDAK ADA TRANSAKSI');
        return report.join('\n');
    }
    const validNomorSet = new Set(validJual.map(j => j.nomor));
    const validPesani = pesaniData.filter(p => validNomorSet.has(p.nomor));

    // --- 1. Sales By Tipe ---
    report.push('Sales Type :');
    report.push('-'.repeat(width));
    const tipeMap = { '1': 'Dine IN', '2': 'Take Away', '3': 'Delivery', '4': 'Online' };
    const salesByTipe = {};
    validJual.forEach(j => {
        const tipe = tipeMap[j.tipe] || `Tipe ${j.tipe}`;
        salesByTipe[tipe] = (salesByTipe[tipe] || 0) + parseFloat(j.jumlah || 0);
    });
    let totalSalesByType = 0;
    for (const [tipe, amount] of Object.entries(salesByTipe)) {
        report.push(padRight(tipe, 20) + padLeft(formatCurrency(amount), 22));
        totalSalesByType += amount;
    }
    report.push('-'.repeat(width));
    report.push(padRight('Jumlah', 20) + padLeft(formatCurrency(totalSalesByType), 22));
    report.push('');

    // --- 2. Total & Revenue (LOGIKA DIPERBAIKI) ---
    const totalStruk = validJual.length;
    const totalSales = validJual.reduce((sum, j) => sum + parseFloat(j.ttot || 0), 0);
    
    // PERBAIKAN: Hitung diskon item dari tabel pesani
    const menuItems = validPesani.filter(p => p.sub === '0' && (p.payment == null || p.payment === ''));
    const totalItemDiscount = menuItems.reduce((sum, p) => {
        const harga = parseFloat(p.harga || 0);
        const qty = parseFloat(p.quantity || 1);
        const discp = parseFloat(p.discp || 0);
        const discr = parseFloat(p.discr || 0);
        return sum + ((harga * qty * (discp / 100))) + (discr * qty);
    }, 0);
    
    // PERBAIKAN: Hitung diskon faktur dari tabel jual
    const totalBillDiscount = pesaniData
    .filter(p => p.payment === '06')
    .reduce((sum, p) => sum - parseFloat(p.harga || 0), 0); // Gunakan minus (-) karena harga diskon bernilai negatif ### Penjelasan Perbaikan
    const totalDiscount = totalItemDiscount + totalBillDiscount;

    const netSales = totalSales - totalDiscount;
    const totalService = validJual.reduce((sum, j) => sum + parseFloat(j.tserv || 0), 0);
    const totalPajak = validJual.reduce((sum, j) => sum + parseFloat(j.ttax || 0), 0);
    
    // PERBAIKAN: Hitung ulang total revenue agar konsisten
    const totalRevenue = netSales + totalService + totalPajak;
    
    report.push(`${padRight('TOTAL SALES', 15)}:${padLeft(totalStruk, 4)} ${padLeft(formatCurrency(totalSales), 21)}`);
    // PERBAIKAN: Tampilkan kedua jenis diskon
    report.push(`${padRight('DISC ITEM', 15)}:${padLeft('', 4)} ${padLeft(formatCurrency(totalItemDiscount), 21)}`);
    report.push(`${padRight('DISC FAKTUR', 15)}:${padLeft('', 4)} ${padLeft(formatCurrency(totalBillDiscount), 21)}`);
    report.push(padLeft('--------------------', width));
    report.push(`${padRight('NET SALES', 15)}:${padLeft('', 4)} ${padLeft(formatCurrency(netSales), 21)}`);
    report.push(`${padRight('SERVICE', 15)}:${padLeft('', 4)} ${padLeft(formatCurrency(totalService), 21)}`);
    report.push(`${padRight('PAJAK REST', 15)}:${padLeft('', 4)} ${padLeft(formatCurrency(totalPajak), 21)}`);
    report.push(padLeft('--------------------', width));
    report.push(`${padRight('TOTAL REVENUE', 15)}:${padLeft('', 4)} ${padLeft(formatCurrency(totalRevenue), 21)}`);
    report.push('');

    // --- 3. Cash Collection ---
    // (Tidak ada perubahan, sudah benar)
    report.push('CASH COLLECTION');

// Filter semua item pembayaran dari pesani
const allPaymentItems = validPesani.filter(p => p.payment && p.payment !== '06');

const paymentMap = {};
let totalNonCashAmount = 0;

// Proses semua pembayaran NON-TUNAI terlebih dahulu untuk mendapatkan rinciannya
allPaymentItems.forEach(p => {
    if (p.payment !== '10') { // Hanya proses kartu, voucher, dll.
        const method = p.edc ? p.edc.toUpperCase() : (p.name ? p.name.toUpperCase() : 'OTHER');
        if (!paymentMap[method]) {
            paymentMap[method] = { count: 0, amount: 0 };
        }
        const paymentAmount = parseFloat(p.harga || 0);
        paymentMap[method].count++;
        paymentMap[method].amount += paymentAmount;
        totalNonCashAmount += paymentAmount;
    }
});

// Hitung total revenue yang benar (sudah dihitung di atas)
const correctTotalRevenue = totalRevenue; 

// Hitung total pembayaran tunai bersih sebagai selisihnya
const totalCashAmount = correctTotalRevenue - totalNonCashAmount;
const cashTransactions = new Set(allPaymentItems.filter(p => p.payment === '10').map(p => p.nomor));
paymentMap['CASH'] = {
    count: cashTransactions.size,
    amount: totalCashAmount
};

// --- Sekarang, tampilkan hasilnya ---
let totalPaymentAmount = 0;
let totalPaymentCount = 0;
let totalCardAmount = 0;
let totalCardCount = 0;

// Urutkan untuk menampilkan CASH paling atas (jika ada)
const displayOrder = ['CASH', ...Object.keys(paymentMap).filter(k => k !== 'CASH').sort()];

for (const method of displayOrder) {
    const data = paymentMap[method];
    if (data && data.count > 0) {
        report.push(`${padRight(method, 18)} ${padLeft(data.count, 3)} ${padLeft(formatCurrency(data.amount), 19)}`);
        totalPaymentAmount += data.amount;
        totalPaymentCount += data.count;

        if (method !== 'CASH') {
            totalCardAmount += data.amount;
            totalCardCount += data.count;
        }
    }
}

report.push(padLeft('------------------', width));
report.push(`${padRight('TOTAL CARD', 18)} ${padLeft(totalCardCount, 3)} ${padLeft(formatCurrency(totalCardAmount), 19)}`);
report.push('');
// Total payment sekarang akan selalu sama dengan Total Revenue
report.push(`${padRight('TOTAL PAYMENT', 12)}:${padLeft(totalPaymentCount, 3)} ${padLeft(formatCurrency(totalPaymentAmount), 24)}`);
report.push('');

    // --- 4. ITEM & BILL DISCOUNT (LOGIKA DIPERBAIKI) ---
    report.push('RINCIAN DISCOUNT :');
    report.push('-'.repeat(width));
    // Rincian Item Discount
    const itemDiscountsByName = {};
    const discountedItems = menuItems.filter(p => p.dname && p.dname.trim() !== '');
    discountedItems.forEach(p => {
        const discName = `(I) ${p.dname.toUpperCase()}`;
        if (!itemDiscountsByName[discName]) itemDiscountsByName[discName] = { amount: 0 };
        const harga = parseFloat(p.harga || 0);
        const qty = parseFloat(p.quantity || 1);
        const discp = parseFloat(p.discp || 0);
        const discr = parseFloat(p.discr || 0);
        itemDiscountsByName[discName].amount += ((harga * qty * (discp / 100))) + (discr * qty);
    });
    for (const [name, data] of Object.entries(itemDiscountsByName)) {
        report.push(`${padRight(name, 26)} ${padLeft(formatCurrency(data.amount), 15)}`);
    }
    // Rincian Bill/Faktur Discount
    const billDiscountsByName = {};
    const discountedBills = pesaniData.filter(p => p.payment === '06');
    discountedBills.forEach(p => {
        const discName = `(F) ${p.name.toUpperCase()}`;
        if (!billDiscountsByName[discName]) billDiscountsByName[discName] = { amount: 0 };
        billDiscountsByName[discName].amount += -parseFloat(p.harga || 0);
    });
     for (const [name, data] of Object.entries(billDiscountsByName)) {
        // HANYA TAMPILKAN JIKA NILAI DISKON LEBIH DARI 0
        if (data.amount > 0) {
            report.push(`${padRight(name, 26)} ${padLeft(formatCurrency(data.amount), 15)}`);
        }
    }
    report.push(padLeft('------------------', width));
    report.push(`${padRight('Total Disc.', 26)} ${padLeft(formatCurrency(totalDiscount), 15)}`);
    report.push('');

    // --- 5. Sales By Kategory (LOGIKA DIPERBAIKI) ---
    report.push('Sales By Kategory');
    report.push('-'.repeat(width));
    const catMap = {};
    menuItems.forEach(p => {
        const cat = (p.group_name || 'Uncategorized').toUpperCase();
        const itemTotal = parseFloat(p.harga || 0) * parseFloat(p.quantity || 1);
        if (!catMap[cat]) catMap[cat] = { qty: 0, amount: 0 };
        catMap[cat].qty += parseInt(p.quantity) || 1;
        catMap[cat].amount += itemTotal;
    });
    let totalCatQty = 0, totalCatAmount = 0;
    for (const [cat, data] of Object.entries(catMap)) {
        totalCatQty += data.qty;
        totalCatAmount += data.amount;
        report.push(`${padRight(cat, 15)} ${padLeft(data.qty, 5)} ${padLeft(formatCurrency(data.amount), 20)}`);
    }
    report.push('-'.repeat(width));
    report.push(`${padRight('  Jumlah', 15)} ${padLeft(totalCatQty, 5)} ${padLeft(formatCurrency(totalCatAmount), 20)}`);
    report.push('');

    // --- 6. Sales By Time ---
    report.push('Sales By Time');
    report.push('-'.repeat(width));
    const timeMap = {};
    validJual.forEach(j => {
        const date = new Date(j.jamm);
        if (isNaN(date)) return; // Lewati jika tanggal tidak valid
        const hour = date.getHours();
        const slot = `${String(hour).padStart(2, '0')}:00-${String(hour).padStart(2, '0')}:59`;
        timeMap[slot] = (timeMap[slot] || 0) + parseFloat(j.jumlah || 0);
    });
    let totalTimeCount = 0, totalTimeAmount = 0;
    Object.keys(timeMap).sort().forEach(slot => {
        const amount = timeMap[slot];
        const count = validJual.filter(j => {
             const d = new Date(j.jamm);
             return !isNaN(d) && d.getHours() === parseInt(slot.split(':')[0]);
        }).length;
        totalTimeCount += count;
        totalTimeAmount += amount;
        report.push(`${padRight(slot, 15)} ${padLeft(count, 5)} ${padLeft(formatCurrency(amount), 20)}`);
    });
    report.push('-'.repeat(width));
    report.push(`${padRight('  Jumlah', 15)} ${padLeft(totalTimeCount, 5)} ${padLeft(formatCurrency(totalTimeAmount), 20)}`);
    report.push('');

    // Sisa laporan (tidak ada perubahan)
    const totalGuest = validJual.reduce((sum, j) => sum + (parseInt(j.cover) || 0), 0) || 1;
    const avgCover = Math.round(totalSales / totalGuest);
    const avgCheck = Math.round(totalSales / totalStruk);
    report.push(`${padRight('Average Cover', 15)} ${padLeft(totalGuest, 5)} ${padLeft(formatCurrency(avgCover), 20)}`);
    report.push(`${padRight('Average Check', 15)} ${padLeft(totalStruk, 5)} ${padLeft(formatCurrency(avgCheck), 20)}`);
    report.push('');

    report.push('VOID TRANCACTION');
    report.push('-'.repeat(width));
    report.push(`${padRight(' JUMLAH', 15)} ${padLeft(0, 5)} ${padLeft(formatCurrency(0), 20)}`);
    report.push('');
    report.push('-'.repeat(width));
    
    let outstandingCount = 0;
    let outstandingAmount = 0;
    if (cartData && cartData.length > 0) {
        cartData.forEach(c => {
            if (c.cart && c.cart.trim() !== '[]') {
                try {
                    const items = JSON.parse(c.cart);
                    if (items.length > 0) {
                        outstandingCount++;
                        const tableTotal = items.reduce((sum, item) => {
                            if (!item.payment) {
                                return sum + (parseFloat(item.harga || 0) * parseFloat(item.quantity || 1));
                            }
                            return sum;
                        }, 0);
                        outstandingAmount += tableTotal;
                    }
                } catch (e) { console.error('Gagal parse JSON dari cart:', c.cart); }
            }
        });
    }

    report.push(`${padRight('OUT STANDING :', 15)} ${padLeft(outstandingCount, 5)} ${padLeft(formatCurrency(outstandingAmount), 20)}`);
    report.push('-'.repeat(width));
    report.push('');

    const now = new Date();
    const printTime = `${String(now.getDate()).padStart(2, '0')}-${String(now.getMonth() + 1).padStart(2, '0')}-${now.getFullYear()} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`;
    report.push(`Print at: ${printTime}`);
    report.push(`By      : ${options.kasir}`);

    return report.join('\n');
}