import {
  mkdir,
  mkdtemp,
  readFile,
  rm,
  stat,
  writeFile,
} from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import { afterEach, describe, expect, test } from 'vitest';

import { prepareCodexWorkspaceFiles } from '../../src/codex-runtime';

const tempDirs: string[] = [];

const mode = async (filePath: string) => (await stat(filePath)).mode & 0o777;

describe('Codex runtime preparation', () => {
  afterEach(async () => {
    await Promise.all(
      tempDirs.map((dir) => rm(dir, { force: true, recursive: true })),
    );
    tempDirs.length = 0;
  });

  test('prepares writable Codex directories and preserves project config contents', async () => {
    const workdir = await mkdtemp(path.join(os.tmpdir(), 'spoon-codex-'));
    tempDirs.push(workdir);
    const repoDir = path.join(workdir, 'repo');
    await mkdir(path.join(repoDir, '.codex'), { recursive: true });
    const projectConfig = path.join(repoDir, '.codex', 'config.toml');
    await writeFile(projectConfig, '[features]\ncodex_hooks = true\n');

    await prepareCodexWorkspaceFiles({ workdir, repoDir });

    await expect(readFile(projectConfig, 'utf8')).resolves.toBe(
      '[features]\ncodex_hooks = true\n',
    );
    await expect(mode(workdir)).resolves.toBe(0o755);
    await expect(mode(repoDir)).resolves.toBe(0o755);
    await expect(mode(path.join(workdir, '.codex'))).resolves.toBe(0o755);
    await expect(mode(path.join(workdir, '.config'))).resolves.toBe(0o755);
    await expect(mode(path.join(workdir, '.local', 'share'))).resolves.toBe(
      0o755,
    );
    await expect(mode(path.join(repoDir, '.codex'))).resolves.toBe(0o755);
    await expect(mode(projectConfig)).resolves.toBe(0o644);
  });
});
