
import { getMonth, getYear, format, getDaysInMonth } from 'date-fns';
import type { Employee, StatementRow, JournalEntry, JournalEntryLine, ChartOfAccount } from './types';

export function getMonthlyAdjustments(employee: Employee, month: number, year: number): { total: number, records: { description: string, amount: number }[] } {
    let total = 0;
    const records: { description: string, amount: number }[] = [];

    employee.financialRecords.forEach(record => {
        record.installments.forEach(installment => {
            const installmentDate = new Date(installment.date);
            if (getMonth(installmentDate) === month && getYear(installmentDate) === year) {
                total += installment.amount;
                records.push({ description: record.description, amount: installment.amount });
            }
        });
    });

    return { total, records };
}


export function getMonthlyBonuses(employee: Employee, month: number, year: number) {
    const { records } = getMonthlyAdjustments(employee, month, year);
    const bonusRecords = records.filter(r => r.amount < 0);
    const total = bonusRecords.reduce((sum, rec) => sum + rec.amount, 0) * -1; // Make it a positive number
    return {
        total,
        records: bonusRecords.map(r => ({ ...r, amount: r.amount * -1 }))
    }
}

export function getMonthlyDeductions(employee: Employee, month: number, year: number) {
     const { records } = getMonthlyAdjustments(employee, month, year);
    const deductionRecords = records.filter(r => r.amount > 0);
    const total = deductionRecords.reduce((sum, rec) => sum + rec.amount, 0);
     return {
        total,
        records: deductionRecords
    }
}


export function getNetSalary(employee: Employee, month: number, year: number) {
    const { total: totalDeductions } = getMonthlyDeductions(employee, month, year);
    const { total: totalBonuses } = getMonthlyBonuses(employee, month, year);

    let grossSalary = 0;
    if (employee.status !== 'temporary') {
        const attendedDays = employee.attendance.filter(att => {
            const attDate = new Date(att.checkIn);
            return getMonth(attDate) === month && getYear(attDate) === year && att.checkOut !== null;
        }).length;

        if (employee.salaryType === 'monthly') {
            grossSalary = employee.salary;
        } else {
            grossSalary = attendedDays * employee.salary;
        }
    }
    
    return grossSalary + totalBonuses - totalDeductions;
}

export function getEmployeeStatement(employee: Employee): StatementRow[] {
    const allRelevantMonths = new Set<string>();

    // 1. Get all months from attendance records
    employee.attendance.forEach(att => {
        const d = new Date(att.checkIn);
        allRelevantMonths.add(`${getYear(d)}-${getMonth(d)}`);
    });

    // 2. Get all months from financial records
    employee.financialRecords.forEach(rec => {
        rec.installments.forEach(inst => {
            const d = new Date(inst.date);
            allRelevantMonths.add(`${getYear(d)}-${getMonth(d)}`);
        });
    });

    if (allRelevantMonths.size === 0) {
        return [];
    }

    // Create statement rows for each unique month
    const statementRows: StatementRow[] = Array.from(allRelevantMonths).map(monthStr => {
        const [year, month] = monthStr.split('-').map(Number);
        
        const attendedDays = employee.attendance.filter(att => {
            const attDate = new Date(att.checkIn);
            return getYear(attDate) === year && getMonth(attDate) === month && att.checkOut !== null;
        }).length;

        let grossSalary = 0;
        if (employee.status !== 'temporary') {
            if (employee.salaryType === 'monthly') {
                grossSalary = employee.salary;
            } else {
                grossSalary = attendedDays * employee.salary;
            }
        }
        
        const { total: deductions } = getMonthlyDeductions(employee, month, year);
        const { total: bonuses } = getMonthlyBonuses(employee, month, year);
        
        const netSalary = grossSalary + bonuses - deductions;

        return {
            month: format(new Date(year, month), 'MMMM yyyy'),
            grossSalary,
            deductions,
            bonuses,
            netSalary,
            isPaid: false, // Placeholder for payment status
        };
    });

    // Sort by date descending
    return statementRows.sort((a, b) => new Date(b.month).getTime() - new Date(a.month).getTime());
}

export function getShiftForEmployee(employee: Employee, date: Date, shiftOverrides: { [date: string]: { [employeeId: string]: 'first' | 'second' | 'none' } }): 'first' | 'second' | 'none' {
  const dateString = format(date, 'yyyy-MM-dd');
  const override = shiftOverrides[dateString]?.[employee.id];
  return override || employee.defaultShift;
}

