import { getPrisma } from '../infrastructure/database/PrismaSingleton';
import { HolidayRepository } from '../repositories/HolidayRepository';
import { LeaveRepository } from '../repositories/LeaveRepository';
import { EmployeeSettingsService } from './EmployeeSettingsService';
import { isWeekend, parseDateOnly, toDateOnly, todayInCompanyTz } from '../domain/leave/dateUtils';

export class AutoWeekdayAttendanceService {
  constructor(
    private employeeSettings = new EmployeeSettingsService(),
    private leaveRepo = new LeaveRepository(),
    private holidayRepo = new HolidayRepository(),
  ) {}

  private prisma = getPrisma();

  async syncEmployeeDay(employeeId: string, dateStr: string): Promise<boolean> {
    if (!await this.employeeSettings.isAutoWeekdays(employeeId)) return false;
    if (isWeekend(dateStr)) return false;

    const holidays = await this.holidayRepo.listInRange(parseDateOnly(dateStr), parseDateOnly(dateStr));
    if (holidays.length > 0) return false;

    const leave = await this.leaveRepo.findApprovedOverlapping(employeeId, parseDateOnly(dateStr));
    if (leave) return false;

    await this.prisma.attendance_daily_summary.upsert({
      where: { employee_id_date: { employee_id: employeeId, date: parseDateOnly(dateStr) } },
      create: {
        employee_id: employeeId,
        date: parseDateOnly(dateStr),
        status: 'present',
        hours_worked: 9,
        is_late: false,
      },
      update: {
        status: 'present',
        hours_worked: 9,
        is_late: false,
      },
    });
    return true;
  }

  async syncRange(from: string, to: string, employeeIds?: string[]) {
    const ids = employeeIds ?? await this.employeeSettings.listAutoWeekdayEmployeeIds();
    let synced = 0;
    let cur = from;
    while (cur <= to) {
      for (const id of ids) {
        if (await this.syncEmployeeDay(id, cur)) synced++;
      }
      const d = parseDateOnly(cur);
      d.setUTCDate(d.getUTCDate() + 1);
      cur = toDateOnly(d);
    }
    return { synced, employeeCount: ids.length, from, to };
  }

  async syncCurrentMonth() {
    const today = todayInCompanyTz();
    const from = `${today.slice(0, 7)}-01`;
    return this.syncRange(from, today);
  }
}
