import { TimeWindow } from '../../../../src/domain/value-objects/time-window.vo';

describe('TimeWindow Value Object', () => {
  describe('constants', () => {
    it('should have default online window of 180 seconds', () => {
      expect(TimeWindow.DEFAULT_ONLINE_WINDOW_SECONDS).toBe(180);
    });

    it('should have default heartbeat interval of 60 seconds', () => {
      expect(TimeWindow.DEFAULT_HEARTBEAT_INTERVAL_SECONDS).toBe(60);
    });
  });

  describe('default', () => {
    it('should create default TimeWindow with 180 seconds', () => {
      const window = TimeWindow.default();
      expect(window.windowSeconds).toBe(180);
    });
  });

  describe('ofSeconds', () => {
    it('should create TimeWindow with custom seconds', () => {
      const window = TimeWindow.ofSeconds(300);
      expect(window.windowSeconds).toBe(300);
    });

    it('should create TimeWindow with 1 second', () => {
      const window = TimeWindow.ofSeconds(1);
      expect(window.windowSeconds).toBe(1);
    });

    it('should throw error for zero seconds', () => {
      expect(() => TimeWindow.ofSeconds(0)).toThrow('TimeWindow must be positive');
    });

    it('should throw error for negative seconds', () => {
      expect(() => TimeWindow.ofSeconds(-1)).toThrow('TimeWindow must be positive');
      expect(() => TimeWindow.ofSeconds(-100)).toThrow('TimeWindow must be positive');
    });
  });

  describe('getThresholdTimestamp', () => {
    it('should calculate threshold timestamp correctly', () => {
      const window = TimeWindow.ofSeconds(180);
      const now = new Date('2025-01-01T12:00:00.000Z');
      const threshold = window.getThresholdTimestamp(now);

      // now: 1735732800 (2025-01-01 12:00:00 UTC)
      // threshold: 1735732800 - 180 = 1735732620
      const expectedTimestamp = Math.floor(now.getTime() / 1000) - 180;
      expect(threshold).toBe(expectedTimestamp);
    });

    it('should use current time if no date provided', () => {
      const window = TimeWindow.ofSeconds(180);
      const beforeCall = Math.floor(Date.now() / 1000);
      const threshold = window.getThresholdTimestamp();
      const afterCall = Math.floor(Date.now() / 1000);

      // threshold should be in range [beforeCall - 180, afterCall - 180]
      expect(threshold).toBeGreaterThanOrEqual(beforeCall - 180);
      expect(threshold).toBeLessThanOrEqual(afterCall - 180);
    });

    it('should handle different window sizes', () => {
      const now = new Date('2025-01-01T12:00:00.000Z');
      const nowTimestamp = Math.floor(now.getTime() / 1000);

      const window60 = TimeWindow.ofSeconds(60);
      const window300 = TimeWindow.ofSeconds(300);
      const window3600 = TimeWindow.ofSeconds(3600);

      expect(window60.getThresholdTimestamp(now)).toBe(nowTimestamp - 60);
      expect(window300.getThresholdTimestamp(now)).toBe(nowTimestamp - 300);
      expect(window3600.getThresholdTimestamp(now)).toBe(nowTimestamp - 3600);
    });
  });

  describe('windowSeconds getter', () => {
    it('should return the configured window seconds', () => {
      const window = TimeWindow.ofSeconds(120);
      expect(window.windowSeconds).toBe(120);
    });
  });
});
