import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest';
import * as timer from '../session-timer';

describe('session-timer', () => {
  beforeEach(() => {
    vi.useFakeTimers();
    // Reset to default config for each test
    timer.setConfig({ mode: 'inactivity', minutes: 15 });
    timer.stopTimer();
  });

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

  it('fires callback after inactivity timeout', () => {
    const cb = vi.fn();
    timer.onExpired(cb);
    timer.resetTimer();

    // Default is 15 minutes = 900_000 ms
    vi.advanceTimersByTime(899_999);
    expect(cb).not.toHaveBeenCalled();

    vi.advanceTimersByTime(1);
    expect(cb).toHaveBeenCalledTimes(1);
  });

  it('resets timer on each resetTimer() call', () => {
    const cb = vi.fn();
    timer.onExpired(cb);
    timer.resetTimer();

    // Advance 10 minutes
    vi.advanceTimersByTime(600_000);
    expect(cb).not.toHaveBeenCalled();

    // Reset — clock should restart
    timer.resetTimer();

    // Advance another 10 minutes (20 total, but only 10 since last reset)
    vi.advanceTimersByTime(600_000);
    expect(cb).not.toHaveBeenCalled();

    // Advance remaining 5 minutes to hit the 15-minute mark from last reset
    vi.advanceTimersByTime(300_000);
    expect(cb).toHaveBeenCalledTimes(1);
  });

  it('does not fire when mode is every_time', () => {
    const cb = vi.fn();
    timer.onExpired(cb);
    timer.setConfig({ mode: 'every_time' });
    timer.resetTimer();

    // Advance well past the default 15 minutes
    vi.advanceTimersByTime(60 * 60 * 1000);
    expect(cb).not.toHaveBeenCalled();
  });

  it('respects updated minutes', () => {
    const cb = vi.fn();
    timer.onExpired(cb);
    timer.setConfig({ mode: 'inactivity', minutes: 5 });
    timer.resetTimer();

    vi.advanceTimersByTime(4 * 60 * 1000);
    expect(cb).not.toHaveBeenCalled();

    vi.advanceTimersByTime(60 * 1000);
    expect(cb).toHaveBeenCalledTimes(1);
  });

  it('getConfig returns current config', () => {
    // Default
    expect(timer.getConfig()).toEqual({ mode: 'inactivity', minutes: 15 });

    // After set
    timer.setConfig({ mode: 'every_time' });
    expect(timer.getConfig()).toEqual({ mode: 'every_time' });

    timer.setConfig({ mode: 'inactivity', minutes: 30 });
    expect(timer.getConfig()).toEqual({ mode: 'inactivity', minutes: 30 });
  });

  it('stopTimer prevents firing', () => {
    const cb = vi.fn();
    timer.onExpired(cb);
    timer.resetTimer();

    vi.advanceTimersByTime(600_000); // 10 minutes in
    timer.stopTimer();

    // Advance past what would have been the 15-minute mark
    vi.advanceTimersByTime(600_000);
    expect(cb).not.toHaveBeenCalled();
  });
});
