const { PayrollRun, Payslip } = require('../models/payroll');
const { Staff } = require('../models/staff');
const { Expense, ExpenseCategory } = require('../models/expense');
const { logAction } = require('../utils/logger');
const { sequelize } = require('../config/db');
const { recordToDefaultBank } = require('./bankService');

exports.getEmployees = async () => Staff.findAll({ where: { staffType: 'Permanent' } });



exports.createRun = async (month, processorId) => {
    // Check existing
    const existing = await PayrollRun.findOne({ where: { month } });
    if (existing) throw new Error(`Payroll for ${month} already exists`);

    const transaction = await sequelize.transaction();
    try {
        const run = await PayrollRun.create({
            month,
            status: 'Draft',
            processedBy: processorId
        }, { transaction });

        // Generate Payslips for PERMANENT staff only
        const employees = await Staff.findAll({
            where: {
                isActive: true,
                staffType: 'Permanent'
            }
        });

        let total = 0;

        const slips = employees.map(emp => {
            const basic = Number(emp.monthlySalary) || 0;
            const allowance = Number(emp.allowance) || 0;
            const net = basic + allowance;

            total += net;
            return {
                payrollRunId: run.id,
                staffId: emp.id,
                basic: basic,
                allowances: allowance,
                netPay: net,
                status: 'Pending'
            };
        });

        await Payslip.bulkCreate(slips, { transaction });
        run.totalPaid = total;
        await run.save({ transaction });

        await transaction.commit();
        await logAction(processorId, 'CREATE_RUN', 'PAYROLL', { id: run.id, month }, null);

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

exports.getRuns = async () => {
    return await PayrollRun.findAll({
        order: [['month', 'DESC']],
        include: [{ model: Payslip, include: [Staff] }]
    });
};

exports.markPaid = async (runId, userId) => {
    const run = await PayrollRun.findByPk(runId);
    if (!run) throw new Error('Run not found');
    if (run.status === 'Paid') throw new Error('Already paid');

    const transaction = await sequelize.transaction();
    try {
        run.status = 'Paid';
        await run.save({ transaction });

        await Payslip.update({ status: 'Paid' }, { where: { payrollRunId: run.id }, transaction });

        // Create Expense record in finance module
        let category = await ExpenseCategory.findOne({ where: { name: 'Payroll & Salaries' } });
        if (!category) {
            category = await ExpenseCategory.create({ name: 'Payroll & Salaries' }, { transaction });
        }

        const expense = await Expense.create({
            amount: run.totalPaid,
            expenseCategoryId: category.id,
            description: `Payroll Run ${run.month}`,
            paymentMethod: 'Bank Transfer',
            expenseDate: new Date(),
            reference: `PAY-${run.month}`,
            notes: `Auto-generated payroll expense for permanent staff.`,
            createdBy: userId
        }, { transaction });

        // Record to Banking (Debit)
        await recordToDefaultBank({
            type: 'Debit',
            amount: run.totalPaid,
            description: `Payroll Payout: ${run.month}`,
            reference: `PAY-${run.month}`,
            module: 'Payroll',
            referenceId: run.id
        }, transaction);

        await transaction.commit();
        await logAction(userId, 'PAY_RUN', 'PAYROLL', { id: run.id }, null);
        return run;
    } catch (err) {
        await transaction.rollback();
        throw err;
    }
};
