import {
  calculateAttendanceHours,
  determineAttendanceStatus,
  combineDateAndTime,
} from './attendance-hours.helper';

describe('Attendance Hours Helper & Break Calculation', () => {
  const timeZone = 'Asia/Dhaka';
  const schedule = {
    start_time: '09:00',
    end_time: '17:00',
    break_start: '13:00',
    break_end: '14:00',
  };

  it('should deduct 0 break when checkout is before break starts', () => {
    const checkIn = combineDateAndTime('2026-08-27', '09:00', timeZone);
    const checkOut = combineDateAndTime('2026-08-27', '12:00', timeZone);

    const result = calculateAttendanceHours(checkIn, checkOut, schedule, timeZone);

    expect(result.work_hours).toBe(3);
    expect(result.break_hours).toBe(0);
    expect(result.net_hours).toBe(3);
    expect(result.overtime_hours).toBe(0);
  });

  it('should deduct partial break when checkout is during break period', () => {
    const checkIn = combineDateAndTime('2026-08-27', '09:00', timeZone);
    const checkOut = combineDateAndTime('2026-08-27', '13:30', timeZone); // 30 mins into break

    const result = calculateAttendanceHours(checkIn, checkOut, schedule, timeZone);

    expect(result.work_hours).toBe(4.5);
    expect(result.break_hours).toBe(0.5); // 30 mins in break
    expect(result.net_hours).toBe(4);
    expect(result.overtime_hours).toBe(0);
  });

  it('should deduct full break when checkout is after break ended', () => {
    const checkIn = combineDateAndTime('2026-08-27', '09:00', timeZone);
    const checkOut = combineDateAndTime('2026-08-27', '17:00', timeZone);

    const result = calculateAttendanceHours(checkIn, checkOut, schedule, timeZone);

    expect(result.work_hours).toBe(8);
    expect(result.break_hours).toBe(1); // 1 hour break
    expect(result.net_hours).toBe(7);
    expect(result.overtime_hours).toBe(0);
  });

  it('should calculate overtime when checkout is after scheduled end time', () => {
    const checkIn = combineDateAndTime('2026-08-27', '09:00', timeZone);
    const checkOut = combineDateAndTime('2026-08-27', '18:30', timeZone); // 1.5h overtime

    const result = calculateAttendanceHours(checkIn, checkOut, schedule, timeZone);

    expect(result.work_hours).toBe(9.5);
    expect(result.break_hours).toBe(1);
    expect(result.net_hours).toBe(8.5);
    expect(result.overtime_hours).toBe(1.5);
  });

  it('should mark present when check-in is within grace period', () => {
    const checkInOnTime = combineDateAndTime('2026-08-27', '09:05', timeZone);
    const status1 = determineAttendanceStatus(checkInOnTime, '09:00', 15, timeZone);
    expect(status1).toBe('present');

    const checkInAtGraceLimit = combineDateAndTime('2026-08-27', '09:15', timeZone);
    const status2 = determineAttendanceStatus(checkInAtGraceLimit, '09:00', 15, timeZone);
    expect(status2).toBe('present');
  });

  it('should mark late when check-in is after grace period', () => {
    const checkInLate = combineDateAndTime('2026-08-27', '09:16', timeZone);
    const status = determineAttendanceStatus(checkInLate, '09:00', 15, timeZone);
    expect(status).toBe('late');
  });
});
