import {
  classifyIndividualSummaryBucket,
  classifyMemberMonthSummaryField,
  countGroupedPresentRecords,
  isAttendanceToday,
  isGroupedAbsent,
  isGroupedPresent,
} from './attendance-summary.util';

describe('attendance-summary.util', () => {
  const today = new Date();
  const todayStartUtc = new Date(
    Date.UTC(
      today.getUTCFullYear(),
      today.getUTCMonth(),
      today.getUTCDate(),
      0,
      0,
      0,
      0,
    ),
  );
  const todayEndUtc = new Date(
    Date.UTC(
      today.getUTCFullYear(),
      today.getUTCMonth(),
      today.getUTCDate(),
      23,
      59,
      59,
      999,
    ),
  );
  const yesterday = new Date(todayStartUtc.getTime() - 24 * 60 * 60 * 1000);

  describe('isAttendanceToday', () => {
    it('returns true for a date within today range', () => {
      expect(
        isAttendanceToday(today.toISOString(), todayStartUtc, todayEndUtc),
      ).toBe(true);
    });

    it('returns false for a past date', () => {
      expect(
        isAttendanceToday(yesterday, todayStartUtc, todayEndUtc),
      ).toBe(false);
    });
  });

  describe('isGroupedPresent', () => {
    it('counts in-progress statuses as present for today', () => {
      expect(isGroupedPresent('check_in', true)).toBe(true);
      expect(isGroupedPresent('on_break', true)).toBe(true);
    });

    it('counts past attendance statuses as present for previous days', () => {
      expect(isGroupedPresent('late', false)).toBe(true);
      expect(isGroupedPresent('half_day', false)).toBe(true);
      expect(isGroupedPresent('remote', false)).toBe(true);
    });

    it('does not count in-progress statuses as present for past days', () => {
      expect(isGroupedPresent('check_in', false)).toBe(false);
      expect(isGroupedPresent('on_break', false)).toBe(false);
    });
  });

  describe('classifyIndividualSummaryBucket', () => {
    it('classifies today in-progress statuses as present', () => {
      expect(classifyIndividualSummaryBucket('check_in', true)).toBe(
        'present',
      );
      expect(classifyIndividualSummaryBucket('on_break', true)).toBe('present');
    });

    it('classifies past late, half_day, and remote into individual buckets', () => {
      expect(classifyIndividualSummaryBucket('late', false)).toBe('late');
      expect(classifyIndividualSummaryBucket('half_day', false)).toBe(
        'half_day',
      );
      expect(classifyIndividualSummaryBucket('remote', false)).toBe('present');
    });

    it('does not classify past late or half_day as absent', () => {
      expect(classifyIndividualSummaryBucket('late', false)).not.toBe('absent');
      expect(classifyIndividualSummaryBucket('half_day', false)).not.toBe(
        'absent',
      );
    });

    it('classifies past in-progress statuses as absent', () => {
      expect(classifyIndividualSummaryBucket('check_in', false)).toBe('absent');
      expect(classifyIndividualSummaryBucket('on_break', false)).toBe('absent');
    });

    it('skips weekend and holiday statuses', () => {
      expect(classifyIndividualSummaryBucket('weekend', false)).toBe('skip');
      expect(classifyIndividualSummaryBucket('holiday', true)).toBe('skip');
    });
  });

  describe('isGroupedAbsent', () => {
    it('returns true for absent and unfinished past days', () => {
      expect(isGroupedAbsent('absent', false)).toBe(true);
      expect(isGroupedAbsent('check_in', false)).toBe(true);
    });

    it('returns false for grouped present statuses', () => {
      expect(isGroupedAbsent('late', false)).toBe(false);
      expect(isGroupedAbsent('half_day', false)).toBe(false);
    });
  });

  describe('classifyMemberMonthSummaryField', () => {
    it('maps half_day and remote to total_present', () => {
      expect(classifyMemberMonthSummaryField('half_day', false)).toBe(
        'total_present',
      );
      expect(classifyMemberMonthSummaryField('remote', false)).toBe(
        'total_present',
      );
    });

    it('maps today in-progress statuses to total_present', () => {
      expect(classifyMemberMonthSummaryField('check_in', true)).toBe(
        'total_present',
      );
      expect(classifyMemberMonthSummaryField('on_break', true)).toBe(
        'total_present',
      );
    });

    it('maps past in-progress statuses to total_absent', () => {
      expect(classifyMemberMonthSummaryField('check_in', false)).toBe(
        'total_absent',
      );
    });

    it('keeps late in total_late', () => {
      expect(classifyMemberMonthSummaryField('late', false)).toBe('total_late');
    });
  });

  describe('countGroupedPresentRecords', () => {
    it('matches total_present + total_late when using member month card rules', () => {
      const records = [
        { status: 'present', date: yesterday },
        { status: 'remote', date: yesterday },
        { status: 'half_day', date: yesterday },
        { status: 'late', date: yesterday },
        { status: 'check_in', date: today.toISOString() },
        { status: 'absent', date: yesterday },
      ];

      let totalPresent = 0;
      let totalLate = 0;

      for (const record of records) {
        const isToday = isAttendanceToday(
          record.date,
          todayStartUtc,
          todayEndUtc,
        );
        const field = classifyMemberMonthSummaryField(record.status, isToday);
        if (field === 'total_present') totalPresent += 1;
        if (field === 'total_late') totalLate += 1;
      }

      expect(totalPresent + totalLate).toBe(
        countGroupedPresentRecords(records, todayStartUtc, todayEndUtc),
      );
    });
  });
});
