// Archivage automatique des sessions terminées (P10) : scheduler sweep() sur base :memory:.
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import { isSessionArchived, openDb, setSetting, type Db } from '../src/db/index.js';
import { RETENTION_DAYS_KEY } from '../src/core/retention-settings.js';
import { SessionArchiveService } from '../src/core/session-archive.js';

let db: Db;

function insertSession(id: string, endedAt: string | null): void {
  db.prepare('INSERT INTO sessions (id, cwd, command, created_at, ended_at) VALUES (?, ?, ?, ?, ?)').run(
    id,
    '/tmp/x',
    'bash',
    '2020-01-01T00:00:00.000Z',
    endedAt,
  );
}

beforeEach(() => {
  db = openDb(':memory:');
  insertSession('old', '2020-01-01T00:00:00.000Z'); // terminée il y a longtemps
  insertSession('recent', new Date().toISOString()); // terminée à l'instant
  insertSession('live', null); // vivante (jamais archivée)
});
afterEach(() => db.close());

describe('SessionArchiveService.sweep', () => {
  it('archive seulement les sessions terminées plus anciennes que la rétention', () => {
    setSetting(db, RETENTION_DAYS_KEY, '30');
    const svc = new SessionArchiveService({ db });
    const events: string[] = [];
    svc.on('session_archived', (e) => events.push(e.id));

    const n = svc.sweep();

    expect(n).toBe(1);
    expect(events).toEqual(['old']);
    expect(isSessionArchived(db, 'old')).toBe(true);
    expect(isSessionArchived(db, 'recent')).toBe(false);
    expect(isSessionArchived(db, 'live')).toBe(false);
  });

  it('est idempotent : un second balayage n’archive rien de plus', () => {
    setSetting(db, RETENTION_DAYS_KEY, '30');
    const svc = new SessionArchiveService({ db });
    expect(svc.sweep()).toBe(1);

    const events: string[] = [];
    svc.on('session_archived', (e) => events.push(e.id));
    expect(svc.sweep()).toBe(0);
    expect(events).toEqual([]);
  });

  it('rétention = 0 → no-op (archivage désactivé)', () => {
    setSetting(db, RETENTION_DAYS_KEY, '0');
    const svc = new SessionArchiveService({ db });
    expect(svc.sweep()).toBe(0);
    expect(isSessionArchived(db, 'old')).toBe(false);
  });

  it('start() déclenche un balayage immédiat puis stop() est sûr', () => {
    setSetting(db, RETENTION_DAYS_KEY, '30');
    const svc = new SessionArchiveService({ db, intervalMs: 60_000 });
    svc.start();
    expect(isSessionArchived(db, 'old')).toBe(true);
    svc.stop();
    svc.stop(); // idempotent
  });
});
