const { Income, IncomeCategory } = require('../models/income');
const { User } = require('../models/foundation');
const { logAction } = require('../utils/logger');
const { Op } = require('sequelize');
const { sequelize } = require('../config/db');
const { recordToDefaultBank } = require('./bankService');

exports.createIncome = async (data, userId) => {
    const transaction = await sequelize.transaction();
    try {
        const income = await Income.create({
            ...data,
            source: 'MANUAL',
            isReadOnly: false,
            createdBy: userId
        }, { transaction });

        // Record to Banking
        await recordToDefaultBank({
            type: 'Credit',
            amount: income.amount,
            description: `Income: ${income.notes || 'No description'}`,
            reference: income.reference,
            module: 'Income',
            referenceId: income.id
        }, transaction);

        await logAction(userId, 'CREATE', 'INCOME', { id: income.id, amount: income.amount }, null);
        await transaction.commit();
        return income;
    } catch (err) {
        await transaction.rollback();
        throw err;
    }
};

exports.getAllIncomes = async (filters = {}) => {
    const where = {};
    if (filters.category) where.incomeCategoryId = filters.category;
    if (filters.source) where.source = filters.source;
    if (filters.startDate && filters.endDate) {
        where.receivedDate = { [Op.between]: [filters.startDate, filters.endDate] };
    }

    return await Income.findAll({
        where,
        include: [
            { model: IncomeCategory, attributes: ['name'] },
            { model: User, as: 'creator', attributes: ['fullName'] }
        ],
        order: [['receivedDate', 'DESC'], ['createdAt', 'DESC']]
    });
};

exports.getIncomeById = async (id) => {
    return await Income.findByPk(id, {
        include: [IncomeCategory, { model: User, as: 'creator', attributes: ['fullName'] }]
    });
};

exports.updateIncome = async (id, data, userId) => {
    const transaction = await sequelize.transaction();
    try {
        const income = await Income.findByPk(id);
        if (!income) throw new Error('Income record not found');
        if (income.isReadOnly) throw new Error('CRM-imported income is read-only');

        const oldAmount = income.amount;
        await income.update(data, { transaction });

        // If amount changed, adjust bank balance
        if (parseFloat(data.amount) !== parseFloat(oldAmount)) {
            // Reverse old amount (Debit)
            await recordToDefaultBank({
                type: 'Debit',
                amount: oldAmount,
                description: `Correction: Reverse old income (ID: ${id})`,
                module: 'Income',
                referenceId: id
            }, transaction);

            // Record new amount (Credit)
            await recordToDefaultBank({
                type: 'Credit',
                amount: data.amount,
                description: `Correction: Record updated income (ID: ${id})`,
                module: 'Income',
                referenceId: id
            }, transaction);
        }

        await logAction(userId, 'UPDATE', 'INCOME', { id, ...data }, null);
        await transaction.commit();
        return income;
    } catch (err) {
        await transaction.rollback();
        throw err;
    }
};

exports.deleteIncome = async (id, userId) => {
    const transaction = await sequelize.transaction();
    try {
        const income = await Income.findByPk(id);
        if (!income) throw new Error('Income record not found');
        if (income.isReadOnly) throw new Error('CRM-imported income is read-only');

        // Reverse the income in banking (Debit)
        await recordToDefaultBank({
            type: 'Debit',
            amount: income.amount,
            description: `Reversal: Deleted income record (ID: ${id})`,
            module: 'Income',
            referenceId: id
        }, transaction);

        await income.destroy({ transaction });
        await logAction(userId, 'DELETE', 'INCOME', { id }, null);
        await transaction.commit();
    } catch (err) {
        await transaction.rollback();
        throw err;
    }
};

exports.getIncomeSummary = async () => {
    const total = await Income.sum('amount') || 0;

    // Last 5 entries
    const recent = await Income.findAll({
        limit: 5,
        order: [['createdAt', 'DESC']],
        include: [IncomeCategory]
    });

    return { total, recent };
};

// --- Category Logic ---
exports.getCategories = async () => {
    return await IncomeCategory.findAll({ where: { isActive: true } });
};

exports.createCategory = async (data) => {
    return await IncomeCategory.create(data);
};

exports.updateCategory = async (id, data) => {
    const cat = await IncomeCategory.findByPk(id);
    if (!cat) throw new Error('Category not found');
    return await cat.update(data);
};

exports.deleteCategory = async (id) => {
    const cat = await IncomeCategory.findByPk(id);
    if (!cat) throw new Error('Category not found');

    // Prevent deleting if linked to income records
    const usageCount = await Income.count({ where: { incomeCategoryId: id } });
    if (usageCount > 0) {
        throw new Error('Cannot delete category: It is already linked to income records.');
    }

    return await cat.destroy();
};
