import { describe, expect, it } from 'vitest';
import {
  assessTerminalTool,
  assessTerminalToolForAiMode,
  assessTerminalLine,
  classifyTerminalLine,
  classifyTerminalTool,
  normalizeTerminalPath,
  parseTerminalLine,
} from '../index';

describe('terminal domain', () => {
  it('parses pipelines, redirection, and statements without Bash expansion', () => {
    expect(parseTerminalLine('grep -R "Fourier" . | head -n 20 > results.txt; pwd')).toEqual([
      { pipeline: [
        { command: 'grep', args: ['-R', 'Fourier', '.'] },
        { command: 'head', args: ['-n', '20'], redirect: { path: 'results.txt', append: false } },
      ] },
      { pipeline: [{ command: 'pwd', args: [] }] },
    ]);
  });

  it('cannot escape /workspace', () => {
    expect(normalizeTerminalPath('/workspace/data', '../main.tex')).toBe('/workspace/main.tex');
    expect(() => normalizeTerminalPath('/workspace', '/etc/passwd')).toThrow(/restricted to \/workspace/u);
  });

  it('classifies destructive and write operations for the shared capability policy', () => {
    expect(classifyTerminalLine('cat main.tex')).toBe('read-local');
    expect(classifyTerminalLine('tex main.tex')).toBe('compute-local');
    expect(classifyTerminalLine('grep x main.tex > result.txt')).toBe('write-local');
    expect(classifyTerminalLine('rm -r figures')).toBe('destructive-local');
    expect(classifyTerminalLine('python analysis.py')).toBe('compute-local');
    expect(classifyTerminalLine('Rscript analysis.R')).toBe('compute-local');
    expect(classifyTerminalLine('clang analysis.c -o build/analysis.wasm')).toBe('compute-local');
    expect(classifyTerminalLine('clang++ model.cpp -o build/model.wasm')).toBe('compute-local');
    expect(classifyTerminalLine('wasm-run build/analysis.wasm')).toBe('compute-local');
    expect(classifyTerminalLine('wasix install clang')).toBe('network');
    expect(classifyTerminalLine('wasix install pandoc')).toBe('network');
    expect(classifyTerminalLine('pandoc notes.md -o reports/notes.html')).toBe('compute-local');
    expect(classifyTerminalLine("jaq '.value' data.json")).toBe('compute-local');
    expect(classifyTerminalLine("jq '.value' data.json")).toBe('compute-local');
    expect(classifyTerminalLine("sqlite3 results.db 'select 1'")).toBe('write-local');
    expect(classifyTerminalLine('runtime doctor')).toBe('read-local');
    expect(classifyTerminalLine('runtime status --json')).toBe('read-local');
    expect(classifyTerminalLine('runtime reset python')).toBe('compute-local');
    expect(classifyTerminalLine('runtime restart all')).toBe('compute-local');
  });

  it('classifies browser Git and HTTP by effect instead of granting a generic shell permission', () => {
    expect(classifyTerminalLine('git status')).toBe('read-local');
    expect(classifyTerminalLine('git diff paper.tex')).toBe('read-local');
    expect(classifyTerminalLine('git add .')).toBe('write-local');
    expect(classifyTerminalLine('git commit -m "Update results"')).toBe('write-local');
    expect(classifyTerminalLine('git branch -d old-analysis')).toBe('destructive-local');
    expect(classifyTerminalLine('git checkout main')).toBe('destructive-local');
    expect(classifyTerminalLine('git fetch origin')).toBe('network');
    expect(classifyTerminalLine('git push origin')).toBe('network');
    expect(classifyTerminalLine('git reset --hard')).toBe('unsupported');
    expect(classifyTerminalLine('curl https://example.org/data.csv')).toBe('network');
  });

  it('fails closed and distinguishes human intent from AI-originated execution', () => {
    expect(assessTerminalLine('cat main.tex', 'ai')).toEqual({
      capability: 'read-local',
      action: 'allow',
    });
    expect(assessTerminalLine('tex main.tex', 'ai').action).toBe('confirm');
    expect(assessTerminalLine('touch analysis.py', 'user').action).toBe('allow');
    expect(assessTerminalLine('rm analysis.py', 'user').action).toBe('confirm');
    expect(assessTerminalLine('definitely-not-a-command', 'user').action).toBe('deny');
  });

  it('keeps AI on structured fail-closed tools instead of unrestricted shell execution', () => {
    expect(classifyTerminalTool('workspace.readFile')).toBe('read-local');
    expect(assessTerminalTool('workspace.readFile', 'ai').action).toBe('allow');
    expect(assessTerminalTool('scientific.run', 'ai').action).toBe('confirm');
    expect(assessTerminalTool('scientific.compileC', 'ai').action).toBe('confirm');
    expect(assessTerminalTool('scientific.compileCpp', 'ai').action).toBe('confirm');
    expect(assessTerminalTool('scientific.installToolchain', 'ai').action).toBe('confirm');
    expect(assessTerminalTool('scientific.installUtility', 'ai').action).toBe('confirm');
    expect(assessTerminalTool('scientific.runUtility', 'ai').action).toBe('confirm');
    expect(classifyTerminalTool('workflow.graph')).toBe('read-local');
    expect(classifyTerminalTool('workflow.trace')).toBe('read-local');
    expect(classifyTerminalTool('workflow.changedArtifacts')).toBe('read-local');
    expect(classifyTerminalTool('paperMemory.search')).toBe('read-local');
    expect(classifyTerminalTool('workflow.rerunArtifact')).toBe('compute-local');
    expect(assessTerminalTool('manuscript.proposeResults', 'ai').action).toBe('confirm');
    expect(assessTerminalTool('workspace.writeFile', 'ai').action).toBe('confirm');
    expect(assessTerminalTool('git.stage', 'ai').action).toBe('confirm');
    expect(assessTerminalTool('git.push', 'ai').action).toBe('confirm');
    expect(assessTerminalTool('network.http', 'ai').action).toBe('confirm');
    expect(assessTerminalTool('shell.executeAnything', 'ai').action).toBe('deny');
  });
  it('enforces bounded Assisted and Agent mode execution semantics', () => {
    expect(assessTerminalToolForAiMode('workspace.readFile', 'assisted', { planApproved: true }).action).toBe('allow');
    expect(assessTerminalToolForAiMode('scientific.run', 'assisted', { planApproved: true }).action).toBe('confirm');
    expect(assessTerminalToolForAiMode('scientific.run', 'agent', { planApproved: true }).action).toBe('allow');
    expect(assessTerminalToolForAiMode('workflow.rerunArtifact', 'agent', { planApproved: true }).action).toBe('allow');
    expect(assessTerminalToolForAiMode('scientific.run', 'agent').action).toBe('confirm');
    expect(assessTerminalToolForAiMode('workspace.writeFile', 'agent', { planApproved: true }).action).toBe('confirm');
    expect(assessTerminalToolForAiMode('workspace.writeFile', 'agent', { planApproved: true, stepApproved: true }).action).toBe('allow');
    expect(assessTerminalToolForAiMode('git.push', 'agent', { planApproved: true }).action).toBe('confirm');
    expect(assessTerminalToolForAiMode('workspace.readFile', 'copilot', { planApproved: true }).action).toBe('deny');
    expect(assessTerminalToolForAiMode('shell.executeAnything', 'agent', { planApproved: true, stepApproved: true }).action).toBe('deny');
  });

});
