"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var ReceiptService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReceiptService = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const typeorm_2 = require("typeorm");
const receipt_entity_1 = require("../database/entities/receipt.entity");
const payment_entity_1 = require("../database/entities/payment.entity");
const business_entity_1 = require("../database/entities/business.entity");
const id_generator_util_1 = require("../common/utils/id-generator.util");
const PDFDocument = require("pdfkit");
const fs = require("fs");
const PDFDocumentClass = PDFDocument;
const pdfConstructor = typeof PDFDocumentClass === 'function' ? PDFDocumentClass : PDFDocumentClass.default || PDFDocumentClass;
let ReceiptService = ReceiptService_1 = class ReceiptService {
    constructor(receiptRepo, paymentRepo, businessRepo) {
        this.receiptRepo = receiptRepo;
        this.paymentRepo = paymentRepo;
        this.businessRepo = businessRepo;
        this.logger = new common_1.Logger(ReceiptService_1.name);
    }
    async generateReceipt(paymentId) {
        const existingReceipt = await this.receiptRepo.findOne({
            where: { paymentId },
            relations: ['payment', 'payment.customer', 'payment.package', 'business'],
        });
        if (existingReceipt) {
            const pdfBuffer = await this.buildReceiptPdf(existingReceipt);
            return {
                receiptNumber: existingReceipt.receiptNumber,
                pdfBuffer,
            };
        }
        const payment = await this.paymentRepo.findOne({
            where: { id: paymentId },
            relations: ['customer', 'package', 'business'],
        });
        if (!payment) {
            throw new common_1.NotFoundException('Payment not found');
        }
        if (payment.status !== payment_entity_1.PaymentStatus.SUCCESSFUL) {
            throw new common_1.NotFoundException('Receipt can only be generated for successful payments');
        }
        const business = await this.businessRepo.findOne({
            where: { id: payment.businessId },
        });
        const receiptNumber = (0, id_generator_util_1.generateReceiptNumber)();
        const receipt = this.receiptRepo.create({
            businessId: payment.businessId,
            paymentId: payment.id,
            customerId: payment.customerId,
            receiptNumber,
            amount: payment.amount,
            paymentMethod: 'MPESA',
            mpesaReceipt: payment.mpesaReceipt,
            taxDetails: {
                subtotal: Number(payment.amount),
                taxAmount: 0,
                total: Number(payment.amount),
            },
        });
        const savedReceipt = await this.receiptRepo.save(receipt);
        savedReceipt.payment = payment;
        savedReceipt.business = business;
        if (payment.customer) {
            savedReceipt.customer = payment.customer;
        }
        const pdfBuffer = await this.buildReceiptPdf(savedReceipt);
        this.logger.log(`Receipt generated: ${receiptNumber} for payment ${paymentId}`);
        return { receiptNumber, pdfBuffer };
    }
    async buildReceiptPdf(receipt) {
        return new Promise((resolve, reject) => {
            const chunks = [];
            const doc = new pdfConstructor({
                size: 'A5',
                margin: 40,
                info: {
                    Title: `Receipt ${receipt.receiptNumber}`,
                    Author: receipt.business?.name || 'HBS WiFi',
                },
            });
            doc.on('data', (chunk) => chunks.push(chunk));
            doc.on('end', () => resolve(Buffer.concat(chunks)));
            doc.on('error', reject);
            this.renderReceiptContent(doc, receipt);
        });
    }
    renderReceiptContent(doc, receipt) {
        const business = receipt.business;
        const payment = receipt.payment;
        const customer = receipt.customer;
        if (business?.logo) {
            try {
                const logoPath = business.logo;
                if (fs.existsSync(logoPath)) {
                    doc.image(logoPath, { width: 80, align: 'center' });
                }
            }
            catch {
                this.logger.warn('Could not load business logo');
            }
        }
        if (business?.name) {
            doc.fontSize(16).font('Helvetica-Bold').text(business.name, { align: 'center' });
        }
        doc.fontSize(10).font('Helvetica').fillColor('#666666');
        if (business?.address) {
            doc.text(business.address, { align: 'center' });
        }
        if (business?.phone) {
            doc.text(`Tel: ${business.phone}`, { align: 'center' });
        }
        if (business?.email) {
            doc.text(`Email: ${business.email}`, { align: 'center' });
        }
        if (business?.taxId) {
            doc.text(`PIN: ${business.taxId}`, { align: 'center' });
        }
        doc.moveDown(1);
        doc
            .moveTo(40, doc.y)
            .lineTo(doc.page.width - 40, doc.y)
            .stroke('#cccccc');
        doc.moveDown(0.5);
        doc.fontSize(14).font('Helvetica-Bold').fillColor('#000000').text('PAYMENT RECEIPT', { align: 'center' });
        doc.moveDown(0.5);
        doc
            .moveTo(40, doc.y)
            .lineTo(doc.page.width - 40, doc.y)
            .stroke('#cccccc');
        doc.moveDown(0.5);
        const leftX = 40;
        const rightX = doc.page.width - 40;
        const col1X = leftX;
        const col2X = leftX + 120;
        doc.fontSize(8).font('Helvetica');
        const addRow = (label, value, y = null) => {
            if (y)
                doc.y = y;
            doc.font('Helvetica-Bold').text(label, col1X, doc.y, { continued: true, width: 110 });
            doc.font('Helvetica').text(value, col2X);
        };
        addRow('Receipt No:', receipt.receiptNumber);
        if (receipt.mpesaReceipt) {
            addRow('M-Pesa Receipt:', receipt.mpesaReceipt);
        }
        addRow('Date:', receipt.createdAt ? new Date(receipt.createdAt).toLocaleString('en-KE', { timeZone: 'Africa/Nairobi' }) : new Date().toLocaleString('en-KE'));
        if (customer) {
            doc.moveDown(0.3);
            if (customer.firstName || customer.lastName) {
                addRow('Customer:', `${customer.firstName || ''} ${customer.lastName || ''}`.trim());
            }
            if (customer.phoneNumber) {
                addRow('Phone:', customer.phoneNumber);
            }
        }
        if (payment?.package) {
            doc.moveDown(0.3);
            addRow('Package:', payment.package.name);
        }
        doc.moveDown(0.5);
        doc
            .moveTo(40, doc.y)
            .lineTo(doc.page.width - 40, doc.y)
            .stroke('#cccccc');
        doc.moveDown(0.5);
        doc.fontSize(10).font('Helvetica-Bold');
        doc.text('Amount Breakdown', { align: 'left' });
        doc.fontSize(8).font('Helvetica');
        doc.moveDown(0.3);
        const taxDetails = receipt.taxDetails;
        const subtotal = taxDetails?.subtotal ? Number(taxDetails.subtotal) : Number(receipt.amount);
        const taxAmount = taxDetails?.taxAmount ? Number(taxDetails.taxAmount) : 0;
        addRow('Subtotal:', `KES ${subtotal.toFixed(2)}`);
        addRow('Tax (16%):', `KES ${taxAmount.toFixed(2)}`);
        doc.moveDown(0.3);
        doc
            .moveTo(40, doc.y)
            .lineTo(doc.page.width - 40, doc.y)
            .stroke('#cccccc');
        doc.moveDown(0.3);
        doc.fontSize(11).font('Helvetica-Bold');
        doc.text(`Total: KES ${Number(receipt.amount).toFixed(2)}`, { align: 'right' });
        doc.moveDown(1.5);
        doc.fontSize(7).font('Helvetica').fillColor('#999999');
        doc.text('This is a computer-generated receipt and does not require a signature.', { align: 'center' });
        doc.text(`Generated on ${new Date().toISOString()}`, { align: 'center' });
        doc.end();
    }
};
exports.ReceiptService = ReceiptService;
exports.ReceiptService = ReceiptService = ReceiptService_1 = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, typeorm_1.InjectRepository)(receipt_entity_1.Receipt)),
    __param(1, (0, typeorm_1.InjectRepository)(payment_entity_1.Payment)),
    __param(2, (0, typeorm_1.InjectRepository)(business_entity_1.Business)),
    __metadata("design:paramtypes", [typeorm_2.Repository,
        typeorm_2.Repository,
        typeorm_2.Repository])
], ReceiptService);
