// Réglages CLI Claude (chemin du binaire + override ~/.claude) : validateurs + lecture/écriture DB.
import { chmodSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { openDb, setSetting, type Db } from '../src/db/index.js';
import {
  CLAUDE_BIN_PATH_KEY,
  CLAUDE_HOME_KEY,
  normalizeClaudeBinPath,
  normalizeClaudeHome,
  readClaudeBinPath,
  readClaudeHome,
} from '../src/core/claude-settings.js';

let dir: string;
let execFile: string;
let plainFile: string;
let subDir: string;

beforeAll(() => {
  dir = mkdtempSync(join(tmpdir(), 'arboretum-claude-settings-'));
  execFile = join(dir, 'claude');
  writeFileSync(execFile, '#!/bin/sh\n');
  chmodSync(execFile, 0o755); // exécutable
  plainFile = join(dir, 'notexec');
  writeFileSync(plainFile, 'x');
  chmodSync(plainFile, 0o644); // non exécutable
  subDir = join(dir, 'home');
  mkdirSync(subDir);
});

afterAll(() => rmSync(dir, { recursive: true, force: true }));

describe('normalizeClaudeBinPath', () => {
  it('accepte un chemin absolu vers un fichier exécutable', () => {
    expect(normalizeClaudeBinPath(execFile)).toBe(execFile);
  });
  it('"" = réinitialisation (auto-détection)', () => {
    expect(normalizeClaudeBinPath('')).toBe('');
    expect(normalizeClaudeBinPath('   ')).toBe('');
  });
  it('rejette un fichier non exécutable, un répertoire, un chemin relatif ou avec ".." (null)', () => {
    expect(normalizeClaudeBinPath(plainFile)).toBeNull();
    expect(normalizeClaudeBinPath(subDir)).toBeNull(); // répertoire, pas un fichier
    expect(normalizeClaudeBinPath('relative/claude')).toBeNull();
    expect(normalizeClaudeBinPath(join(dir, '..', 'x'))).toBeNull();
    expect(normalizeClaudeBinPath(join(dir, 'missing'))).toBeNull();
    expect(normalizeClaudeBinPath(42)).toBeNull();
  });
});

describe('normalizeClaudeHome', () => {
  it('accepte un chemin absolu vers un répertoire existant', () => {
    expect(normalizeClaudeHome(subDir)).toBe(subDir);
  });
  it('"" = réinitialisation (défaut)', () => {
    expect(normalizeClaudeHome('')).toBe('');
  });
  it('rejette un fichier, un chemin relatif/inexistant (null)', () => {
    expect(normalizeClaudeHome(execFile)).toBeNull(); // fichier, pas un répertoire
    expect(normalizeClaudeHome('relative/.claude')).toBeNull();
    expect(normalizeClaudeHome(join(dir, 'missing'))).toBeNull();
    expect(normalizeClaudeHome(null)).toBeNull();
  });
});

describe('readClaudeBinPath / readClaudeHome', () => {
  let db: Db;
  beforeAll(() => {
    db = openDb(join(dir, 'settings.db'));
  });
  afterAll(() => db.close());

  it('null quand non défini', () => {
    expect(readClaudeBinPath(db)).toBeNull();
    expect(readClaudeHome(db)).toBeNull();
  });
  it('lit la valeur stockée et traite "" stockée comme null', () => {
    setSetting(db, CLAUDE_BIN_PATH_KEY, execFile);
    setSetting(db, CLAUDE_HOME_KEY, subDir);
    expect(readClaudeBinPath(db)).toBe(execFile);
    expect(readClaudeHome(db)).toBe(subDir);
    setSetting(db, CLAUDE_BIN_PATH_KEY, ''); // réinitialisé
    setSetting(db, CLAUDE_HOME_KEY, '');
    expect(readClaudeBinPath(db)).toBeNull();
    expect(readClaudeHome(db)).toBeNull();
  });
});
