import { describe, test, expect } from 'vitest';
import { msUntilNextRun, shouldCollectNow, shouldCollectOnOpen } from './schedule.js';

const HOUR = 3600 * 1000;

describe('msUntilNextRun', () => {
  test('returns the gap until the target time later today', () => {
    const now = new Date('2026-02-05T09:00:00'); // local
    expect(msUntilNextRun(now, 23, 0)).toBe(14 * HOUR);
  });

  test('rolls to tomorrow when the target already passed today', () => {
    const now = new Date('2026-02-05T23:30:00');
    expect(msUntilNextRun(now, 9, 0)).toBe(9.5 * HOUR);
  });

  test('rolls a full day when now is exactly the target (no immediate refire)', () => {
    const now = new Date('2026-02-05T09:00:00');
    expect(msUntilNextRun(now, 9, 0)).toBe(24 * HOUR);
  });

  test('accounts for minutes', () => {
    const now = new Date('2026-02-05T09:00:00');
    expect(msUntilNextRun(now, 9, 30)).toBe(0.5 * HOUR);
  });
});

describe('shouldCollectNow', () => {
  const hour = 23;

  test('skips when already collected today', () => {
    const now = new Date('2026-02-05T10:00:00');
    expect(shouldCollectNow(now, hour, '2026-02-05')).toBe(false);
  });

  test('seeds a baseline on the very first run (no prior date)', () => {
    const now = new Date('2026-02-05T10:00:00');
    expect(shouldCollectNow(now, hour, null)).toBe(true);
  });

  test('waits for the hour when yesterday is already covered', () => {
    const now = new Date('2026-02-05T10:00:00'); // before 23:00, no gap yet
    expect(shouldCollectNow(now, hour, '2026-02-04')).toBe(false);
  });

  test('fires once the scheduled hour arrives', () => {
    const now = new Date('2026-02-05T23:00:00');
    expect(shouldCollectNow(now, hour, '2026-02-04')).toBe(true);
  });

  test('catches up immediately when a full day was missed, even before the hour', () => {
    const now = new Date('2026-02-05T10:00:00'); // last run was 2 days ago
    expect(shouldCollectNow(now, hour, '2026-02-03')).toBe(true);
  });
});

describe('shouldCollectOnOpen', () => {
  test('collects when today has not been collected yet (any hour)', () => {
    const now = new Date('2026-02-05T09:00:00'); // morning, before the scheduled hour
    expect(shouldCollectOnOpen(now, '2026-02-04')).toBe(true);
    expect(shouldCollectOnOpen(now, null)).toBe(true);
  });

  test('skips when today is already collected', () => {
    const now = new Date('2026-02-05T09:00:00');
    expect(shouldCollectOnOpen(now, '2026-02-05')).toBe(false);
  });
});
