const { BankAccount, BankTransaction } = require('../models/banking');
const { sequelize } = require('../config/db');

exports.createBankAccount = async (data) => {
    const transaction = await sequelize.transaction();
    try {
        // If this is set as default, unset others
        if (data.isDefault === true || data.isDefault === 'true') {
            await BankAccount.update({ isDefault: false }, { where: {}, transaction });
        } else {
            // If no default exists, make this the default
            const defaultExists = await BankAccount.findOne({ where: { isDefault: true } });
            if (!defaultExists) data.isDefault = true;
        }

        const account = await BankAccount.create({
            ...data,
            currentBalance: data.openingBalance || 0
        }, { transaction });

        // Record opening balance transaction if > 0
        if (parseFloat(data.openingBalance) > 0) {
            await BankTransaction.create({
                bankAccountId: account.id,
                type: 'Credit',
                amount: data.openingBalance,
                description: 'Opening Balance',
                module: 'Banking',
                balanceAfter: data.openingBalance,
                transactionDate: new Date()
            }, { transaction });
        }

        await transaction.commit();
        return account;
    } catch (err) {
        await transaction.rollback();
        throw err;
    }
};

exports.getBankAccounts = async () => {
    return await BankAccount.findAll({
        where: { isActive: true },
        order: [['isDefault', 'DESC'], ['bankName', 'ASC']]
    });
};

exports.getAccountTransactions = async (bankAccountId) => {
    return await BankTransaction.findAll({
        where: { bankAccountId },
        order: [['transactionDate', 'DESC']]
    });
};

exports.getDefaultBankAccount = async () => {
    return await BankAccount.findOne({ where: { isDefault: true, isActive: true } });
};

exports.recordTransaction = async ({ bankAccountId, type, amount, description, reference, module, referenceId }, t) => {
    const account = await BankAccount.findByPk(bankAccountId, { transaction: t });
    if (!account) {
        console.warn('Bank account not found for transaction recording');
        return null;
    }

    const numAmount = Math.abs(parseFloat(amount));
    let newBalance = parseFloat(account.currentBalance);

    if (type === 'Credit') {
        newBalance += numAmount;
    } else {
        newBalance -= numAmount;
    }

    const bankTx = await BankTransaction.create({
        bankAccountId: account.id,
        type,
        amount: numAmount,
        description,
        reference,
        module,
        referenceId,
        balanceAfter: newBalance,
        transactionDate: new Date()
    }, { transaction: t });

    await account.update({ currentBalance: newBalance }, { transaction: t });
    return bankTx;
};

// Helper for recording to default bank
exports.recordToDefaultBank = async (params, t) => {
    const defaultAccount = await exports.getDefaultBankAccount();
    if (!defaultAccount) {
        console.warn('No default bank account found');
        return null;
    }
    return await exports.recordTransaction({ ...params, bankAccountId: defaultAccount.id }, t);
};

exports.setAsDefault = async (id) => {
    const transaction = await sequelize.transaction();
    try {
        await BankAccount.update({ isDefault: false }, { where: {}, transaction });
        await BankAccount.update({ isDefault: true }, { where: { id }, transaction });
        await transaction.commit();
    } catch (err) {
        await transaction.rollback();
        throw err;
    }
};
