import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
import { createIsolatedEnv, type IsolatedEnv, updateIsolatedConfig } from '../helpers/isolated-env';
import { createLocalRepo, type LocalRepo } from '../helpers/test-repo';
import { runTakt } from '../helpers/takt-runner';

describe('E2E: Codex permission mode readonly/full', () => {
  let isolatedEnv: IsolatedEnv;
  let repo: LocalRepo;
  let piecePath: string;

  beforeEach(() => {
    isolatedEnv = createIsolatedEnv();
    repo = createLocalRepo();
    piecePath = join(repo.path, 'permission-mode-e2e-piece.yaml');

    writeFileSync(
      piecePath,
      [
        'name: permission-mode-e2e',
        'description: Verify readonly/full behavior in codex sandbox',
        'max_movements: 3',
        'initial_movement: write_check',
        'movements:',
        '  - name: write_check',
        '    agent: codex',
        '    allowed_tools:',
        '      - Bash',
        '    required_permission_mode: readonly',
        '    instruction_template: |',
        '      Run this exact command in repository root:',
        '      /bin/sh -lc \'printf "ok\\n" > epperm-check.txt\'',
        '      If file creation succeeds, reply exactly: COMPLETE',
        '    rules:',
        '      - condition: COMPLETE',
        '        next: COMPLETE',
      ].join('\n'),
      'utf-8',
    );
  });

  afterEach(() => {
    try { repo.cleanup(); } catch { /* best-effort */ }
    try { isolatedEnv.cleanup(); } catch { /* best-effort */ }
  });

  it('readonly で失敗し full で成功する', () => {
    updateIsolatedConfig(isolatedEnv.taktDir, {
      provider_profiles: {
        codex: { default_permission_mode: 'readonly' },
      },
    });

    const readonlyResult = runTakt({
      args: ['--task', 'Run write permission check', '--piece', piecePath],
      cwd: repo.path,
      env: isolatedEnv.env,
      timeout: 240_000,
    });

    const readonlyOutput = `${readonlyResult.stdout}\n${readonlyResult.stderr}`;
    expect(existsSync(join(repo.path, 'epperm-check.txt'))).toBe(false);
    expect(
      [
        'EPERM',
        'permission denied',
        'Permission denied',
        'Operation not permitted',
        'read-only',
        'Read-only',
      ].some((marker) => readonlyOutput.includes(marker)),
    ).toBe(true);

    updateIsolatedConfig(isolatedEnv.taktDir, {
      provider_profiles: {
        codex: { default_permission_mode: 'full' },
      },
    });

    const fullResult = runTakt({
      args: ['--task', 'Run write permission check', '--piece', piecePath],
      cwd: repo.path,
      env: isolatedEnv.env,
      timeout: 240_000,
    });

    expect(fullResult.exitCode).toBe(0);
    expect(existsSync(join(repo.path, 'epperm-check.txt'))).toBe(true);
    expect(readFileSync(join(repo.path, 'epperm-check.txt'), 'utf-8')).toContain('ok');
  }, 300_000);
});
