import { evaluateSLAStatus } from '../slaHelper';

describe('#SLA Helpers', () => {
  const currentTimestamp = 1700000000; // Fixed timestamp for testing

  beforeEach(() => {
    vi.useFakeTimers();
    vi.setSystemTime(currentTimestamp * 1000);
  });

  afterEach(() => {
    vi.useRealTimers();
  });

  describe('evaluateSLAStatus', () => {
    describe('when inputs are invalid', () => {
      it('returns empty status when appliedSla is null', () => {
        const result = evaluateSLAStatus({ appliedSla: null, chat: {} });
        expect(result).toEqual({
          type: '',
          threshold: '',
          icon: '',
          isSlaMissed: false,
        });
      });

      it('returns empty status when chat is null', () => {
        const result = evaluateSLAStatus({ appliedSla: {}, chat: null });
        expect(result).toEqual({
          type: '',
          threshold: '',
          icon: '',
          isSlaMissed: false,
        });
      });
    });

    describe('FRT (First Response Time)', () => {
      it('returns FRT status when first reply not made and within threshold', () => {
        const appliedSla = { sla_frt_due_at: currentTimestamp + 3600 }; // 1 hour from now
        const chat = { first_reply_created_at: null, status: 'open' };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.type).toBe('FRT');
        expect(result.threshold).toBe('1h');
        expect(result.icon).toBe('alarm');
        expect(result.isSlaMissed).toBe(false);
      });

      it('returns missed FRT status when threshold is exceeded', () => {
        const appliedSla = { sla_frt_due_at: currentTimestamp - 1800 }; // 30 min ago
        const chat = { first_reply_created_at: null, status: 'open' };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.type).toBe('FRT');
        expect(result.threshold).toBe('30m');
        expect(result.icon).toBe('flame');
        expect(result.isSlaMissed).toBe(true);
      });

      it('does not return FRT when first reply was made before due time', () => {
        const appliedSla = { sla_frt_due_at: currentTimestamp + 3600 };
        const chat = {
          first_reply_created_at: currentTimestamp - 1000,
          status: 'open',
        };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.type).not.toBe('FRT');
      });

      it('does not return FRT when first reply was made at due time', () => {
        const appliedSla = {
          sla_frt_due_at: currentTimestamp - 600,
          sla_rt_due_at: currentTimestamp + 1800,
        };
        const chat = {
          first_reply_created_at: currentTimestamp - 600,
          status: 'open',
        };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.type).toBe('RT');
      });

      it('returns missed FRT when first reply was made after due time', () => {
        const appliedSla = {
          sla_frt_due_at: currentTimestamp - 600,
          sla_rt_due_at: currentTimestamp + 1800,
        };
        const chat = {
          first_reply_created_at: currentTimestamp - 300,
          status: 'open',
        };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.type).toBe('FRT');
        expect(result.threshold).toBe('10m');
        expect(result.icon).toBe('flame');
        expect(result.isSlaMissed).toBe(true);
      });

      it('returns missed FRT when live first reply timestamp is an ISO string after due time', () => {
        const appliedSla = {
          sla_frt_due_at: currentTimestamp - 600,
          sla_rt_due_at: currentTimestamp + 1800,
        };
        const chat = {
          first_reply_created_at: new Date(
            (currentTimestamp - 300) * 1000
          ).toISOString(),
          status: 'open',
        };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.type).toBe('FRT');
        expect(result.threshold).toBe('10m');
        expect(result.icon).toBe('flame');
        expect(result.isSlaMissed).toBe(true);
      });

      it('uses the due time for a missed FRT event created after the deadline', () => {
        const appliedSla = { sla_frt_due_at: currentTimestamp - 3600 };
        const chat = { first_reply_created_at: null, status: 'open' };
        const slaEvents = [
          { event_type: 'frt', created_at: currentTimestamp - 1800 },
        ];

        const result = evaluateSLAStatus({ appliedSla, chat, slaEvents });

        expect(result.type).toBe('FRT');
        expect(result.threshold).toBe('1h');
        expect(result.icon).toBe('flame');
        expect(result.isSlaMissed).toBe(true);
      });
    });

    describe('NRT (Next Response Time)', () => {
      it('returns NRT status when waiting for response and within threshold', () => {
        const appliedSla = { sla_nrt_due_at: currentTimestamp + 1800 }; // 30 min from now
        const chat = {
          first_reply_created_at: currentTimestamp - 7200,
          waiting_since: currentTimestamp - 600,
          status: 'open',
        };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.type).toBe('NRT');
        expect(result.threshold).toBe('30m');
        expect(result.icon).toBe('alarm');
        expect(result.isSlaMissed).toBe(false);
      });

      it('returns missed NRT status when threshold is exceeded', () => {
        const appliedSla = { sla_nrt_due_at: currentTimestamp - 900 }; // 15 min ago
        const chat = {
          first_reply_created_at: currentTimestamp - 7200,
          waiting_since: currentTimestamp - 2700,
          status: 'open',
        };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.type).toBe('NRT');
        expect(result.threshold).toBe('15m');
        expect(result.icon).toBe('flame');
        expect(result.isSlaMissed).toBe(true);
      });

      it('does not return NRT when not waiting for response', () => {
        const appliedSla = { sla_nrt_due_at: currentTimestamp + 1800 };
        const chat = {
          first_reply_created_at: currentTimestamp - 7200,
          waiting_since: null,
          status: 'open',
        };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.type).not.toBe('NRT');
      });

      it('returns missed NRT when a recorded NRT miss exists after response', () => {
        const appliedSla = { sla_rt_due_at: currentTimestamp + 1800 };
        const chat = {
          first_reply_created_at: currentTimestamp - 7200,
          waiting_since: null,
          status: 'open',
        };
        const slaEvents = [
          { event_type: 'nrt', created_at: currentTimestamp - 900 },
        ];

        const result = evaluateSLAStatus({ appliedSla, chat, slaEvents });

        expect(result.type).toBe('NRT');
        expect(result.threshold).toBe('15m');
        expect(result.icon).toBe('flame');
        expect(result.isSlaMissed).toBe(true);
      });

      it('uses the recorded event time for a missed NRT with a new active NRT timer', () => {
        const appliedSla = {
          sla_nrt_due_at: currentTimestamp + 300,
          sla_rt_due_at: currentTimestamp + 1800,
        };
        const chat = {
          first_reply_created_at: currentTimestamp - 7200,
          waiting_since: currentTimestamp - 60,
          status: 'open',
        };
        const slaEvents = [
          { event_type: 'nrt', created_at: currentTimestamp - 1800 },
        ];

        const result = evaluateSLAStatus({ appliedSla, chat, slaEvents });

        expect(result.type).toBe('NRT');
        expect(result.threshold).toBe('30m');
        expect(result.icon).toBe('flame');
        expect(result.isSlaMissed).toBe(true);
      });

      it('does not return NRT when first reply not made', () => {
        const appliedSla = { sla_nrt_due_at: currentTimestamp + 1800 };
        const chat = {
          first_reply_created_at: null,
          waiting_since: currentTimestamp - 600,
          status: 'open',
        };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.type).not.toBe('NRT');
      });
    });

    describe('RT (Resolution Time)', () => {
      it('returns RT status when conversation is open and within threshold', () => {
        const appliedSla = { sla_rt_due_at: currentTimestamp + 7200 }; // 2 hours from now
        const chat = {
          first_reply_created_at: currentTimestamp - 3600,
          status: 'open',
        };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.type).toBe('RT');
        expect(result.threshold).toBe('2h');
        expect(result.icon).toBe('alarm');
        expect(result.isSlaMissed).toBe(false);
      });

      it.each(['pending', 'snoozed'])(
        'returns RT status when conversation is %s and within threshold',
        status => {
          const appliedSla = { sla_rt_due_at: currentTimestamp + 7200 };
          const chat = {
            first_reply_created_at: currentTimestamp - 3600,
            status,
          };

          const result = evaluateSLAStatus({ appliedSla, chat });

          expect(result.type).toBe('RT');
          expect(result.threshold).toBe('2h');
          expect(result.icon).toBe('alarm');
          expect(result.isSlaMissed).toBe(false);
        }
      );

      it('returns missed RT status when threshold is exceeded', () => {
        const appliedSla = { sla_rt_due_at: currentTimestamp - 3600 }; // 1 hour ago
        const chat = {
          first_reply_created_at: currentTimestamp - 7200,
          status: 'open',
        };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.type).toBe('RT');
        expect(result.threshold).toBe('1h');
        expect(result.icon).toBe('flame');
        expect(result.isSlaMissed).toBe(true);
      });

      it('uses the due time for a missed RT event created after the deadline', () => {
        const appliedSla = { sla_rt_due_at: currentTimestamp - 3600 };
        const chat = {
          first_reply_created_at: currentTimestamp - 7200,
          status: 'open',
        };
        const slaEvents = [
          { event_type: 'rt', created_at: currentTimestamp - 1800 },
        ];

        const result = evaluateSLAStatus({ appliedSla, chat, slaEvents });

        expect(result.type).toBe('RT');
        expect(result.threshold).toBe('1h');
        expect(result.icon).toBe('flame');
        expect(result.isSlaMissed).toBe(true);
      });

      it('does not return RT when conversation is resolved', () => {
        const appliedSla = { sla_rt_due_at: currentTimestamp + 7200 };
        const chat = {
          first_reply_created_at: currentTimestamp - 3600,
          status: 'resolved',
        };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.type).toBe('');
      });
    });

    describe('priority selection', () => {
      it('returns most urgent SLA when multiple are active', () => {
        const appliedSla = {
          sla_frt_due_at: currentTimestamp + 7200, // 2h - less urgent
          sla_nrt_due_at: currentTimestamp + 1800, // 30m - most urgent
          sla_rt_due_at: currentTimestamp + 3600, // 1h
        };
        const chat = {
          first_reply_created_at: null,
          waiting_since: currentTimestamp - 600,
          status: 'open',
        };

        const result = evaluateSLAStatus({ appliedSla, chat });

        // FRT is selected because first_reply_created_at is null
        // NRT is not checked when first_reply_created_at is null
        expect(result.type).toBe('RT');
        expect(result.threshold).toBe('1h');
      });

      it('returns most urgent missed SLA over upcoming SLA', () => {
        const appliedSla = {
          sla_nrt_due_at: currentTimestamp - 300, // 5m overdue - most urgent by absolute value
          sla_rt_due_at: currentTimestamp + 3600, // 1h remaining
        };
        const chat = {
          first_reply_created_at: currentTimestamp - 7200,
          waiting_since: currentTimestamp - 2100,
          status: 'open',
        };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.type).toBe('NRT');
        expect(result.isSlaMissed).toBe(true);
      });

      it('returns an existing missed SLA over a closer upcoming SLA', () => {
        const appliedSla = {
          sla_frt_due_at: currentTimestamp - 7200, // 2h overdue
          sla_rt_due_at: currentTimestamp + 300, // 5m remaining
        };
        const chat = {
          first_reply_created_at: null,
          status: 'open',
        };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.type).toBe('FRT');
        expect(result.threshold).toBe('2h');
        expect(result.isSlaMissed).toBe(true);
      });
    });

    describe('time formatting', () => {
      it('formats time in days and hours', () => {
        const appliedSla = { sla_rt_due_at: currentTimestamp + 90000 }; // 25 hours
        const chat = { status: 'open' };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.threshold).toBe('1d 1h');
      });

      it('formats time less than a minute as 1m', () => {
        const appliedSla = { sla_frt_due_at: currentTimestamp + 30 }; // 30 seconds
        const chat = { first_reply_created_at: null, status: 'open' };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.threshold).toBe('1m');
      });

      it('formats months correctly', () => {
        const appliedSla = {
          sla_rt_due_at: currentTimestamp + 2592000 + 86400,
        }; // 1 month + 1 day
        const chat = { status: 'open' };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result.threshold).toBe('1mo 1d');
      });
    });

    describe('empty status scenarios', () => {
      it('returns empty when no SLA thresholds are set', () => {
        const appliedSla = {};
        const chat = { status: 'open' };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result).toEqual({
          type: '',
          threshold: '',
          icon: '',
          isSlaMissed: false,
        });
      });

      it('returns empty when all conditions are met', () => {
        const appliedSla = {
          sla_frt_due_at: currentTimestamp + 3600,
          sla_nrt_due_at: currentTimestamp + 1800,
          sla_rt_due_at: currentTimestamp + 7200,
        };
        const chat = {
          first_reply_created_at: currentTimestamp - 3600, // FRT already hit
          waiting_since: null, // Not waiting, so NRT not applicable
          status: 'resolved', // RT not applicable
        };

        const result = evaluateSLAStatus({ appliedSla, chat });

        expect(result).toEqual({
          type: '',
          threshold: '',
          icon: '',
          isSlaMissed: false,
        });
      });
    });
  });
});
