const PDFDocument = require('pdfkit');
const path = require('path');
const fs = require('fs');
const { SystemSetting } = require('../models/settings');
const { BankAccount } = require('../models/banking');

const getCompanySettings = async () => {
    const settings = await SystemSetting.findAll();
    const map = {};
    settings.forEach(s => map[s.key] = s.value);
    return {
        name: map['COMPANY_NAME'] || 'DELIGHT SOLUTIONS LIMITED',
        address: map['COMPANY_ADDRESS'] || 'Ecobank-Head Office - 10th Floor\nNairobi Muindi Mbingu St, Nairobi Nairobi 00200\nKenya',
        phone: map['COMPANY_PHONE'],
        email: map['COMPANY_EMAIL'],
        logo: map['COMPANY_LOGO'],
        taxId: map['COMPANY_TAX_ID'],
        currency: map['DEFAULT_CURRENCY'] || 'KES',
        bankDetails: map['BANK_DETAILS'] // Leave empty if not set
    };
};

exports.generateBillingPDF = async (type, data, stream) => {
    const company = await getCompanySettings();
    const doc = new PDFDocument({ margin: 50, size: 'A4' });
    doc.pipe(stream);

    const primaryColor = '#333333';
    const secondaryColor = '#666666';
    const accentColor = '#2d2d2d'; // Dark header background

    // --- Header Section ---
    if (company.logo) {
        const logoRelativePath = company.logo.startsWith('/') ? company.logo.substring(1) : company.logo;
        const logoPath = path.join(__dirname, '..', logoRelativePath);
        if (fs.existsSync(logoPath)) {
            doc.image(logoPath, 50, 40, { height: 60 });
        }
    }

    // Company Info (Left)
    doc.fillColor(primaryColor)
        .font('Helvetica-Bold')
        .fontSize(14)
        .text(company.name.toUpperCase(), 50, 110)
        .font('Helvetica')
        .fontSize(10)
        .fillColor(secondaryColor)
        .text(company.address, 50, 130, { lineGap: 2 });

    // Document Title (Right)
    const docTitle = type === 'invoice' ? 'Invoice' : 'Estimate';
    const docNumber = type === 'invoice' ? data.invoiceNumber : data.quoteNumber;

    doc.fillColor(primaryColor)
        .font('Helvetica')
        .fontSize(36)
        .text(docTitle, 350, 40, { align: 'right' })
        .fontSize(12)
        .font('Helvetica-Bold')
        .text(`# ${docNumber}`, 350, 85, { align: 'right' });

    doc.moveDown(4);

    // --- Bill To & Meta Section ---
    const metaY = 220;
    doc.fillColor(secondaryColor)
        .font('Helvetica')
        .fontSize(10)
        .text('Bill To', 50, metaY);

    doc.fillColor(primaryColor)
        .font('Helvetica-Bold')
        .fontSize(12)
        .text(data.Client.name, 50, metaY + 15)
        .font('Helvetica')
        .fontSize(10)
        .fillColor(secondaryColor)
        .text(data.Client.billingAddress || '', 50, metaY + 32, { width: 250 });

    const dateLabel = type === 'invoice' ? 'Invoice Date :' : 'Estimate Date :';
    doc.text(dateLabel, 350, metaY + 32, { align: 'right', width: 100 });
    doc.fillColor(primaryColor)
        .text(data.issueDate, 460, metaY + 32, { align: 'right', width: 85 });

    // Subject & Scope
    if (data.subject || data.notes) {
        doc.moveDown(4);
        const subjectY = doc.y;
        doc.fillColor(secondaryColor).font('Helvetica').text('Subject :', 50, subjectY);
        doc.fillColor(primaryColor).font('Helvetica').text(data.subject || 'N/A', 110, subjectY, { width: 440 });

        // Scope/Description text if any
        if (data.notes && data.notes.length > 5) {
            doc.moveDown(0.5);
            doc.fillColor(secondaryColor).fontSize(9).text(data.notes, 50, doc.y, { width: 500 });
        }
    }

    doc.moveDown(2);

    // --- Table Section ---
    const tableTop = doc.y + 10;
    const colWidths = {
        num: 30,
        desc: 250,
        qty: 50,
        rate: 80,
        amt: 85
    };

    // Table Header Background
    doc.rect(50, tableTop, 500, 25).fill(accentColor);

    // Header Text
    doc.fillColor('#FFFFFF')
        .font('Helvetica-Bold')
        .fontSize(10)
        .text('#', 55, tableTop + 8)
        .text('Item & Description', 90, tableTop + 8)
        .text('Qty', 300, tableTop + 8, { width: 50, align: 'center' })
        .text('Rate', 360, tableTop + 8, { width: 80, align: 'right' })
        .text('Amount', 450, tableTop + 8, { width: 85, align: 'right' });

    let currentY = tableTop + 25;
    doc.fillColor(primaryColor).font('Helvetica');

    data.items.forEach((item, index) => {
        // Stripe or Border
        doc.moveTo(50, currentY).lineTo(550, currentY).stroke('#EEEEEE');

        const rowHeight = 25;
        doc.fontSize(10)
            .text(index + 1, 55, currentY + 8)
            .text(item.description, 90, currentY + 8, { width: 200 })
            .text(Number(item.quantity).toFixed(2), 300, currentY + 8, { width: 50, align: 'center' })
            .text(Number(item.unitPrice).toLocaleString(undefined, { minimumFractionDigits: 2 }), 360, currentY + 8, { width: 80, align: 'right' });

        const lineTotal = Number(item.quantity) * Number(item.unitPrice);
        doc.text(lineTotal.toLocaleString(undefined, { minimumFractionDigits: 2 }), 450, currentY + 8, { width: 85, align: 'right' });

        currentY += rowHeight;

        // Check page overflow
        if (currentY > 730) {
            doc.addPage();
            currentY = 50;
        }
    });

    doc.moveTo(50, currentY).lineTo(550, currentY).stroke('#EEEEEE');

    // --- Summary Section ---
    doc.moveDown(2);
    const summaryY = currentY + 20;

    const drawSummaryLine = (label, value, isBold = false, isBoxed = false) => {
        const y = doc.y;
        if (isBoxed) {
            doc.rect(330, y - 5, 220, 25).fill('#F9F9F9');
            doc.fillColor(primaryColor);
        }

        doc.font(isBold ? 'Helvetica-Bold' : 'Helvetica')
            .fontSize(10)
            .text(label, 350, y, { width: 100, align: 'right' })
            .text(value, 460, y, { width: 90, align: 'right' });

        doc.moveDown(1.5);
    };

    doc.y = summaryY;
    drawSummaryLine('Sub Total', Number(data.subtotal).toLocaleString(undefined, { minimumFractionDigits: 2 }));

    const taxTotal = data.items.reduce((sum, i) => sum + (Number(i.taxAmount) || 0), 0) + (data.tax || 0);
    drawSummaryLine('Zero Rate (0%)', taxTotal.toLocaleString(undefined, { minimumFractionDigits: 2 }));

    if (Number(data.discount) > 0) {
        drawSummaryLine('Discount', `-${Number(data.discount).toLocaleString()}`);
    }

    drawSummaryLine('Total', `${company.currency}${Number(data.total).toLocaleString(undefined, { minimumFractionDigits: 2 })}`, true, true);

    // Payment Instructions
    const defaultBank = await BankAccount.findOne({ where: { isDefault: true, isActive: true } });
    const bankInfo = company.bankDetails || (defaultBank ? `BANK: ${defaultBank.bankName}\nACCOUNT NAME: ${defaultBank.accountName}\nACCOUNT NUMBER: ${defaultBank.accountNumber}` : 'Please contact us for payment details.');

    doc.moveDown(2); // Ensure some space after summary
    doc.fontSize(12).font('Helvetica-Bold').fillColor('#0f172a').text('Payment Instructions', 50, doc.y);
    doc.fontSize(9).font('Helvetica').fillColor('#64748b').text(bankInfo, 50, doc.y + 5, { width: 500 });


    // --- Footer Section ---
    const footerY = 650;
    doc.fillColor(secondaryColor)
        .font('Helvetica-Bold')
        .fontSize(10)
        .text('Notes', 50, footerY);

    doc.font('Helvetica')
        .fontSize(9)
        .text('Looking forward for your business.', 50, footerY + 15);

    doc.end();
};

exports.generateBuffer = async (type, data) => {
    return new Promise(async (resolve, reject) => {
        try {
            const chunks = [];
            const { PassThrough } = require('stream');
            const stream = new PassThrough();
            stream.on('data', chunk => chunks.push(chunk));
            stream.on('end', () => resolve(Buffer.concat(chunks)));
            stream.on('error', err => reject(err));
            await exports.generateBillingPDF(type, data, stream);
        } catch (e) {
            reject(e);
        }
    });
};

exports.generateExpensePDF = async (expense, stream) => {
    // Keep expense PDF as is or slightly improve later
    const doc = new PDFDocument();
    doc.pipe(stream);
    doc.text('Expense Voucher');
    doc.text(`Description: ${expense.description}`);
    doc.text(`Amount: ${expense.amount}`);
    doc.end();
}
