import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { SyncTimer } from '../../src/main/services/SyncTimer.js';

describe('SyncTimer', () => {
  let syncSvc: { sync: ReturnType<typeof vi.fn> };
  let settings: {
    isAutoSyncEnabled: ReturnType<typeof vi.fn>;
    getSyncIntervalMin: ReturnType<typeof vi.fn>;
    getSyncRepoUrl: ReturnType<typeof vi.fn>;
  };
  let timer: SyncTimer;

  beforeEach(() => {
    vi.useFakeTimers();
    syncSvc = { sync: vi.fn(async () => ({ ok: true })) };
    settings = {
      isAutoSyncEnabled: vi.fn(async () => true),
      getSyncIntervalMin: vi.fn(async () => 5),
      getSyncRepoUrl: vi.fn(async () => 'git@host:u/r.git')
    };
    timer = new SyncTimer(syncSvc as never, settings as never);
  });

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

  it('start — interval 마다 syncSvc.sync 호출', async () => {
    await timer.start();
    expect(syncSvc.sync).not.toHaveBeenCalled();
    await vi.advanceTimersByTimeAsync(5 * 60 * 1000);
    expect(syncSvc.sync).toHaveBeenCalledTimes(1);
    await vi.advanceTimersByTimeAsync(5 * 60 * 1000);
    expect(syncSvc.sync).toHaveBeenCalledTimes(2);
  });

  it('auto disabled → 시작 안 함 (sync 0회)', async () => {
    settings.isAutoSyncEnabled.mockResolvedValueOnce(false);
    await timer.start();
    await vi.advanceTimersByTimeAsync(60 * 60 * 1000);
    expect(syncSvc.sync).not.toHaveBeenCalled();
  });

  it('repo URL 미설정 → 시작 안 함', async () => {
    settings.getSyncRepoUrl.mockResolvedValueOnce(null);
    await timer.start();
    await vi.advanceTimersByTimeAsync(60 * 60 * 1000);
    expect(syncSvc.sync).not.toHaveBeenCalled();
  });

  it('reconfigure — stop + 새 interval 로 start', async () => {
    await timer.start();
    await vi.advanceTimersByTimeAsync(5 * 60 * 1000);
    expect(syncSvc.sync).toHaveBeenCalledTimes(1);

    settings.getSyncIntervalMin.mockResolvedValueOnce(10);
    await timer.reconfigure();
    await vi.advanceTimersByTimeAsync(5 * 60 * 1000);
    // not enough time for new interval — still 1 call
    expect(syncSvc.sync).toHaveBeenCalledTimes(1);
    await vi.advanceTimersByTimeAsync(5 * 60 * 1000);
    expect(syncSvc.sync).toHaveBeenCalledTimes(2);
  });

  it('stop — 호출 후 더 이상 sync 발생 안 함', async () => {
    await timer.start();
    timer.stop();
    await vi.advanceTimersByTimeAsync(60 * 60 * 1000);
    expect(syncSvc.sync).not.toHaveBeenCalled();
  });
});
