import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { AttendanceService } from './attendance.service';

@Injectable()
export class PayrollService {
  constructor(
    private prisma: PrismaService,
    private attendanceService: AttendanceService,
  ) {}

  async list(month?: number, year?: number) {
    const m = month ?? new Date().getMonth() + 1;
    const y = year ?? new Date().getFullYear();
    return this.prisma.payroll.findMany({
      where: { month: m, year: y },
      include: { employee: { include: { department: true } } },
      orderBy: [{ employee: { lastName: 'asc' } }],
    });
  }

  async calculate(employeeId: number, month: number, year: number) {
    const emp = await this.prisma.employee.findUnique({
      where: { id: employeeId },
      include: { shift: true },
    });
    if (!emp) throw new Error('Employee not found');

    const workedDays = await this.attendanceService.getWorkedDays(employeeId, year, month);
    const daysInMonth = new Date(year, month, 0).getDate();
    const absentDays = Math.max(0, daysInMonth - workedDays);

    const baseSalary = emp.salary;
    const dailyRate = baseSalary / 22;
    const netSalary = Math.max(0, workedDays * dailyRate);

    return {
      employeeId,
      month,
      year,
      baseSalary,
      workedDays,
      absentDays,
      dailyRate,
      netSalary,
      deductions: absentDays * dailyRate,
      bonuses: 0,
    };
  }

  async generate(month: number, year: number) {
    const employees = await this.prisma.employee.findMany({
      where: { status: 'active' },
    });

    const results = [];
    for (const emp of employees) {
      const calc = await this.calculate(emp.id, month, year);
      const existing = await this.prisma.payroll.findFirst({
        where: { employeeId: emp.id, month, year },
      });

      if (existing) {
        await this.prisma.payroll.update({
          where: { id: existing.id },
          data: {
            baseSalary: calc.baseSalary,
            workedDays: calc.workedDays,
            absentDays: calc.absentDays,
            deductions: calc.deductions,
            netSalary: calc.netSalary,
          },
        });
        results.push({ employeeId: emp.id, action: 'updated' });
      } else {
        await this.prisma.payroll.create({
          data: {
            employeeId: emp.id,
            month,
            year,
            baseSalary: calc.baseSalary,
            workedDays: calc.workedDays,
            absentDays: calc.absentDays,
            deductions: calc.deductions,
            bonuses: 0,
            netSalary: calc.netSalary,
            status: 'draft',
          },
        });
        results.push({ employeeId: emp.id, action: 'created' });
      }
    }
    return { generated: results.length, results };
  }

  async approve(id: number) {
    return this.prisma.payroll.update({
      where: { id },
      data: { status: 'approved' },
    });
  }

  async markPaid(id: number) {
    return this.prisma.payroll.update({
      where: { id },
      data: { status: 'paid' },
    });
  }
}
