import { describe, expect, it, beforeEach, afterEach } from 'vitest';
import { mkdtempSync, writeFileSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { readProcStart, isLive, readRegistry, findByPid } from '../src/core/session-registry.js';

const DEAD_PID = 2 ** 31 - 1; // pid quasi impossible à attribuer

describe('readProcStart / isLive', () => {
  it('lit le procStart du process courant et le valide', () => {
    const ps = readProcStart(process.pid);
    expect(ps).not.toBeNull();
    expect(isLive(process.pid, ps as string)).toBe(true);
  });
  it('process absent → mort', () => {
    expect(readProcStart(DEAD_PID)).toBeNull();
    expect(isLive(DEAD_PID, '123')).toBe(false);
  });
  it('procStart discordant (pid recyclé) → stale → mort', () => {
    expect(isLive(process.pid, 'definitely-not-the-real-starttime')).toBe(false);
  });
  it('procStart inconnu mais process vivant → incertain → vivant', () => {
    expect(isLive(process.pid, null)).toBe(true);
  });
});

describe('readRegistry', () => {
  let dir: string;
  beforeEach(() => {
    dir = mkdtempSync(join(tmpdir(), 'arb-reg-'));
  });
  afterEach(() => {
    rmSync(dir, { recursive: true, force: true });
  });

  it('dossier absent → vide', () => {
    expect(readRegistry(join(dir, 'nope'))).toEqual([]);
  });

  it('calcule live par pid+procStart et ignore les fichiers malformés', () => {
    const ps = readProcStart(process.pid) as string;
    writeFileSync(
      join(dir, `${process.pid}.json`),
      JSON.stringify({ pid: process.pid, procStart: ps, sessionId: 'live-sid', cwd: '/x', status: 'busy' }),
    );
    writeFileSync(
      join(dir, `${DEAD_PID}.json`),
      JSON.stringify({ pid: DEAD_PID, procStart: '999', sessionId: 'dead-sid', cwd: '/y', status: 'idle' }),
    );
    writeFileSync(join(dir, 'broken.json'), '{ not json');

    const entries = readRegistry(dir);
    expect(entries).toHaveLength(2);
    const live = entries.find((e) => e.pid === process.pid);
    expect(live?.live).toBe(true);
    expect(live?.status).toBe('busy');
    expect(live?.claudeSessionId).toBe('live-sid');
    const dead = entries.find((e) => e.pid === DEAD_PID);
    expect(dead?.live).toBe(false);
    expect(findByPid(dir, process.pid)?.claudeSessionId).toBe('live-sid');
  });

  it('normalise un status inconnu en null', () => {
    writeFileSync(join(dir, `${DEAD_PID}.json`), JSON.stringify({ pid: DEAD_PID, status: 'weird' }));
    expect(readRegistry(dir)[0].status).toBeNull();
  });
});
