const ALLOWED_TOOLS_VALUES = new Set([
  'Read',
  'Read,Write',
  'Read,Write,Edit',
  'Read,Write,Edit,Bash',
]);

const ALLOWED_OUTPUT_FORMATS = new Set(['json', 'text', 'stream-json']);

function fail(message) {
  const error = new Error(message);
  error.code = 'CLAUDE_COMMAND_REJECTED';
  throw error;
}

export function parseCommand(command) {
  const input = String(command || '');
  const argv = [];
  let token = '';
  let quote = null;
  let escaped = false;

  for (const ch of input) {
    if (escaped) {
      token += ch;
      escaped = false;
      continue;
    }
    if (ch === '\\') {
      escaped = true;
      continue;
    }
    if (quote) {
      if (ch === quote) quote = null;
      else token += ch;
      continue;
    }
    if (ch === '"' || ch === "'") {
      quote = ch;
      continue;
    }
    if (/\s/.test(ch)) {
      if (token) {
        argv.push(token);
        token = '';
      }
      continue;
    }
    token += ch;
  }

  if (escaped) token += '\\';
  if (quote) fail('Unclosed quote in command');
  if (token) argv.push(token);
  return argv;
}

function readOption(argv, name) {
  const index = argv.indexOf(name);
  if (index === -1) return null;
  if (index === argv.length - 1 || argv[index + 1].startsWith('--')) fail(`${name} requires a value`);
  return argv[index + 1];
}

export function validateClaudeCommand(command, { maxTurns = process.env.MAX_CLAUDE_TURNS || 12 } = {}) {
  const argv = parseCommand(command);
  if (argv[0] !== 'claude') fail('Only claude CLI commands can be approved');

  const args = argv.slice(1);
  if (!args.length) fail('Claude command has no arguments');

  const allowedOptions = new Set(['-p', '--allowedTools', '--max-turns', '--output-format']);
  for (let i = 0; i < args.length; i += 2) {
    const option = args[i];
    const value = args[i + 1];
    if (!allowedOptions.has(option)) fail(`Unsupported Claude argument: ${option}`);
    if (!value || value.startsWith('--')) fail(`${option} requires a value`);
  }

  const prompt = readOption(args, '-p');
  if (!prompt) fail('Claude command must include -p');

  const allowedTools = readOption(args, '--allowedTools');
  if (!allowedTools || !ALLOWED_TOOLS_VALUES.has(allowedTools)) {
    fail('Claude command uses disallowed --allowedTools value');
  }

  const turns = Number(readOption(args, '--max-turns') || 12);
  const limit = Math.max(1, Math.min(50, Number(maxTurns) || 12));
  if (!Number.isInteger(turns) || turns < 1 || turns > limit) {
    fail(`Claude command --max-turns must be between 1 and ${limit}`);
  }

  const outputFormat = readOption(args, '--output-format');
  if (outputFormat && !ALLOWED_OUTPUT_FORMATS.has(outputFormat)) {
    fail('Claude command uses disallowed --output-format value');
  }

  return { argv, args, prompt, allowedTools, turns, outputFormat };
}
