const { Payment } = require('../models/payment');
const { Invoice } = require('../models/billing');
const { Income, IncomeCategory } = require('../models/income');
const { sequelize } = require('../config/db');
const { logAction } = require('../utils/logger');

const { recordToDefaultBank, recordTransaction, getDefaultBankAccount } = require('./bankService');

exports.recordPayment = async (data, userId) => {
    const transaction = await sequelize.transaction();
    try {
        const invoice = await Invoice.findByPk(data.invoiceId);
        if (!invoice) throw new Error('Invoice not found');

        // Determine Bank Account
        let bankAccountId = data.bankAccountId;
        if (!bankAccountId) {
            const defaultBank = await getDefaultBankAccount();
            if (!defaultBank) throw new Error('No default bank account configured. Please create one first.');
            bankAccountId = defaultBank.id;
        }

        const payment = await Payment.create({
            ...data,
            bankAccountId,
            clientId: invoice.clientId,
            status: 'Completed'
        }, { transaction });

        // Update Invoice Balance
        invoice.balanceDue = Number(invoice.balanceDue) - Number(data.amount);
        if (invoice.balanceDue <= 0) {
            invoice.status = 'Paid';
            invoice.balanceDue = 0;
        }
        await invoice.save({ transaction });

        // Post to Income Module
        let category = await IncomeCategory.findOne({ where: { name: 'Client Payments' } });
        if (!category) {
            category = await IncomeCategory.create({
                name: 'Client Payments',
                description: 'Revenue from client portal payments'
            }, { transaction });
        }

        await Income.create({
            amount: data.amount,
            incomeCategoryId: category.id,
            source: 'MANUAL',
            reference: `PAY-${payment.id.substring(0, 8)}`,
            paymentMethod: data.paymentMethod || 'MPesa',
            receivedDate: new Date(),
            notes: `Payment for Invoice ${invoice.invoiceNumber}. Method: ${data.paymentMethod}. Ref: ${data.transactionReference}`,
            createdBy: userId,
            isReadOnly: true
        }, { transaction });

        // Record to Banking Ledger
        await recordTransaction({
            bankAccountId,
            type: 'Credit',
            amount: data.amount,
            description: `Payment for Invoice ${invoice.invoiceNumber}`,
            reference: data.transactionReference,
            module: 'Billing',
            referenceId: payment.id
        }, transaction);

        await transaction.commit();
        await logAction(userId, 'RECORD_PAYMENT', 'BILLING', { invoiceId: invoice.id, amount: data.amount }, null);
        return payment;
    } catch (err) {
        await transaction.rollback();
        throw err;
    }
};

exports.getClientPayments = async (clientId) => {
    return await Payment.findAll({
        where: { clientId },
        include: [{ model: Invoice, attributes: ['invoiceNumber'] }],
        order: [['paymentDate', 'DESC']]
    });
};
