"use server";
import { prisma } from "@/lib/prisma";
import { revalidatePath } from "next/cache";

export async function getPayslips(year: number, month: number) {
  try {
    const slips = await prisma.payslip.findMany({
      where: { year, month },
      include: {
        staff: true,
        transaction: true
      },
      orderBy: { staff: { fullName: 'asc' } }
    });
    return { success: true, slips };
  } catch (error: any) {
    console.error("Error fetching payslips:", error);
    return { success: false, error: error.message };
  }
}

// Generate missing payslips for a given month for all active staff
export async function generatePayslips(year: number, month: number) {
  try {
    const activeStaff = await prisma.staff.findMany({
      where: { isActive: true },
      select: { id: true }
    });
    
    const jalaali = require('date-fns-jalali');
    // Get start and end of the requested jalali month
    // Note: JS months are 0-indexed in Date constructor, but let's assume year=1403, month=2 is Ordibehesht.
    // date-fns-jalali can create dates.
    
    let generatedCount = 0;
    
    for (const st of activeStaff) {
       const existing = await prisma.payslip.findUnique({
          where: { staffId_year_month: { staffId: st.id, year, month } }
       });
       if (!existing) {
          // default Iranian labor law mock template limits (user can edit later)
          const base = 7166184; // پایه حقوق وزارت کار ۱۴۰۳
          const housing = 900000; // حق مسکن
          const grocery = 1400000; // بن خواربار
          const insurance = Math.round((base + housing + grocery) * 0.07); // ۷٪ سهم کارگر (حدودی)
          
          // Calculate Unpaid Leaves
          // We fetch all APPROVED UNPAID leaves that might overlap with this month.
          // Since exact Jalali month boundary calculation is complex without full date logic, 
          // we fetch leaves and roughly approximate or if we have the exact Date range:
          // Let's get the first day and last day of the given Jalali month
          let startDate, endDate;
          try {
             // month is 1-12
             startDate = new Date(year, month - 1, 1); 
             // wait, date-fns-jalali new Date doesn't take Jalali year directly like this in native Date.
             // We'll just fetch all unpaid leaves for the staff and filter those created/overlapping recently.
             // Actually, it's safer to fetch all APPROVED UNPAID leaves for the staff in the last 40 days, or we can just fetch all of them and filter using date-fns-jalali `isSameMonth` or getting the Jalali month.
          } catch(e) {}

          const leaves = await prisma.staffLeave.findMany({
             where: { staffId: st.id, type: 'UNPAID', status: 'APPROVED' }
          });
          
          let unpaidLeaveDays = 0;
          for (const leave of leaves) {
             const fromJalaliMonth = jalaali.getMonth(leave.fromDate) + 1;
             const fromJalaliYear = jalaali.getYear(leave.fromDate);
             const toJalaliMonth = jalaali.getMonth(leave.toDate) + 1;
             const toJalaliYear = jalaali.getYear(leave.toDate);

             // If the leave overlaps with the target month
             if (fromJalaliYear === year && fromJalaliMonth === month) {
                 // Calculate days
                 const days = jalaali.differenceInDays(leave.toDate, leave.fromDate) + 1;
                 unpaidLeaveDays += days;
             } else if (toJalaliYear === year && toJalaliMonth === month) {
                 // Started in previous month, ended in this month
                 const startOfMonth = jalaali.startOfMonth(leave.toDate);
                 const days = jalaali.differenceInDays(leave.toDate, startOfMonth) + 1;
                 unpaidLeaveDays += days;
             }
          }

          const dailyRate = Math.round(base / 30);
          const leaveDeduction = unpaidLeaveDays * dailyRate;

          const totalEarn = base + housing + grocery;
          const totalDed = insurance + leaveDeduction;
          const net = totalEarn - totalDed;
          
          await prisma.payslip.create({
            data: {
               staffId: st.id,
               year, month,
               baseSalary: base,
               housingAllowance: housing,
               groceryAllowance: grocery,
               totalEarnings: totalEarn,
               insuranceDeduction: insurance,
               otherDeductions: leaveDeduction,
               totalDeductions: totalDed,
               netPayable: net,
               status: 'DRAFT'
            }
          });
          generatedCount++;
       }
    }
    revalidatePath("/admin/payroll");
    return { success: true, generatedCount };
  } catch (error: any) {
    console.error("Error generating payslips:", error);
    return { success: false, error: "خطا در تولید فیش‌های حقوقی." };
  }
}

export async function updatePayslip(id: string, data: any) {
  try {
     const totalEarnings = (data.baseSalary||0) + (data.housingAllowance||0) + (data.groceryAllowance||0) + (data.childAllowance||0) + (data.overtimePay||0) + (data.otherAdditions||0);
     const totalDeductions = (data.insuranceDeduction||0) + (data.taxDeduction||0) + (data.advances||0) + (data.otherDeductions||0);
     const netPayable = totalEarnings - totalDeductions;
     
     const updated = await prisma.payslip.update({
        where: { id },
        data: {
           ...data,
           totalEarnings,
           totalDeductions,
           netPayable
        }
     });
     
     revalidatePath("/admin/payroll");
     return { success: true, payslip: updated };
  } catch(error: any) {
     return { success: false, error: 'امکان بروزرسانی فیش وجود ندارد.' };
  }
}

export async function payPayslip(id: string, bankAccountId: string) {
  try {
    const slip = await prisma.payslip.findUnique({ where: { id }, include: { staff: true } });
    if (!slip) return { success: false, error: 'فیش یافت نشد.' };
    if (slip.status === 'PAID') return { success: false, error: 'این فیش قبلاً پرداخت شده است.' };
    
    // Create accounting transaction
    const transaction = await prisma.transaction.create({
       data: {
          accountId: bankAccountId,
          amount: -slip.netPayable, // Negative because it's a payment
          type: 'SALARY',
          description: `پرداخت حقوق ${slip.staff.fullName || slip.staff.username} - ماه ${slip.month} سال ${slip.year}`,
       }
    });
    
    // Mark payslip as paid and link trans
    await prisma.payslip.update({
       where: { id },
       data: {
          status: 'PAID',
          paymentDate: new Date(),
          transactionId: transaction.id
       }
    });
    
    // Also update bank account balance
    await prisma.bankAccount.update({
       where: { id: bankAccountId },
       data: { balance: { decrement: slip.netPayable } }
    });
    
    revalidatePath("/admin/payroll");
    revalidatePath("/admin/accounting");
    return { success: true };
  } catch(error: any) {
    return { success: false, error: 'خطا در عملیات پرداخت حقوق و ثبت سند حسابداری.' };
  }
}
