// lib/parsers/arg-parser.mjs
// Parse $ARGUMENTS strings for the four ultra commands.
//
// Each command has its own valid-flag set; passing flags from another command
// produces an `unknown_flags` array but does not error — the caller decides.

const FLAG_SCHEMA = {
  ultrabrief: {
    boolean: ['--quick', '--fg'],
    valued: [],
    aliases: {},
  },
  ultraresearch: {
    boolean: ['--quick', '--local', '--external', '--fg'],
    valued: ['--project'],
    aliases: {},
  },
  ultraplan: {
    boolean: ['--quick', '--fg'],
    valued: ['--project', '--brief', '--export', '--decompose'],
    multi: ['--research'],
    aliases: {},
  },
  ultraexecute: {
    boolean: ['--resume', '--dry-run', '--validate', '--fg'],
    valued: ['--project', '--step', '--session'],
    aliases: {},
  },
  ultrareview: {
    boolean: ['--quick', '--fg', '--dry-run', '--validate'],
    valued: ['--project', '--since'],
    aliases: {},
  },
  ultracontinue: {
    boolean: ['--help', '--cleanup', '--confirm', '--dry-run'],
    valued: [],
    aliases: {},
  },
};

/**
 * @param {string} argString  Raw $ARGUMENTS as the command sees it.
 * @param {keyof FLAG_SCHEMA} command
 * @returns {{
 *   command: string,
 *   flags: Record<string, true | string | string[]>,
 *   positional: string[],
 *   unknown: string[],
 *   errors: Array<{code: string, message: string}>,
 * }}
 */
export function parseArgs(argString, command) {
  const schema = FLAG_SCHEMA[command];
  if (!schema) {
    return {
      command,
      flags: {},
      positional: [],
      unknown: [],
      errors: [{ code: 'ARG_UNKNOWN_COMMAND', message: `Unknown command: ${command}` }],
    };
  }

  const tokens = tokenize(argString);
  const flags = {};
  const positional = [];
  const unknown = [];
  const errors = [];

  for (let i = 0; i < tokens.length; i++) {
    const tok = tokens[i];

    if (!tok.startsWith('--')) {
      positional.push(tok);
      continue;
    }

    if (schema.boolean.includes(tok)) {
      flags[tok] = true;
      continue;
    }

    if (schema.valued.includes(tok)) {
      const next = tokens[i + 1];
      if (next === undefined || next.startsWith('--')) {
        errors.push({ code: 'ARG_MISSING_VALUE', message: `Flag ${tok} requires a value` });
      } else {
        flags[tok] = next;
        i++;
      }
      continue;
    }

    if (schema.multi && schema.multi.includes(tok)) {
      const collected = [];
      while (i + 1 < tokens.length && !tokens[i + 1].startsWith('--')) {
        collected.push(tokens[i + 1]);
        i++;
      }
      if (collected.length === 0) {
        errors.push({ code: 'ARG_MISSING_VALUE', message: `Flag ${tok} requires at least one value` });
      } else {
        flags[tok] = collected;
      }
      continue;
    }

    unknown.push(tok);
  }

  return { command, flags, positional, unknown, errors };
}

function tokenize(s) {
  if (typeof s !== 'string') return [];
  const trimmed = s.trim();
  if (trimmed === '') return [];
  const out = [];
  const re = /"([^"]*)"|'([^']*)'|(\S+)/g;
  let m;
  while ((m = re.exec(trimmed)) !== null) {
    out.push(m[1] !== undefined ? m[1] : m[2] !== undefined ? m[2] : m[3]);
  }
  return out;
}

export { FLAG_SCHEMA };
