local createAi = require('/apis/libai');
local createVersion = require('/apis/libversion');

local rawArgs = table.pack(...);
local args = { n = 0 };
local verbose = false;
local agentName = nil;
local parseError = nil;

local argIndex = 1;
while argIndex <= rawArgs.n do
  if rawArgs[argIndex] == '--verbose' or rawArgs[argIndex] == '-v' then
    verbose = true;
  elseif rawArgs[argIndex] == '--agent' or rawArgs[argIndex] == '-a' then
    if argIndex == rawArgs.n then
      parseError = 'missing agent name after ' .. rawArgs[argIndex];
    else
      argIndex = argIndex + 1;
      agentName = rawArgs[argIndex];
    end
  else
    args.n = args.n + 1;
    args[args.n] = rawArgs[argIndex];
  end
  argIndex = argIndex + 1;
end

local function printUsage()
  print('ai usage:');
  print();
  print('  ai <prompt>');
  print('  ai ping');
  print('  ai new <prompt>');
  print('  ai --new <prompt>');
  print('  ai lua-exec <prompt>       (deprecated)');
  print('  ai --lua-exec <prompt>     (deprecated)');
  print('  ai sessions');
  print('  ai --sessions');
  print('  ai --agent <name> <command>');
  print('  ai --verbose <command>');
  print('  ai --version');
  print('  ai --help');
  print();
  print('settings required:');
  print('  opencc.server_url  (http/https opencode serve URL)');
  print();
  print('settings optional:');
  print('  opencc.username    (default: opencode)');
  print('  opencc.password    (Basic Auth password)');
  print('  opencc.session_id  (auto-managed)');
  print('  opencc.directory   (optional session list scope)');
  print('  opencc.agent       (e.g. atm10-expert)');
  print('  opencc.variant     (e.g. low)');
  print('  opencc.provider_id (e.g. anthropic)');
  print('  opencc.model_id    (e.g. claude-opus-4-7)');
  print('  opencc.timeout_seconds  (per HTTP call, max 60)');
end

local function printAiLog(message)
  print('[ai] ' .. tostring(message));
end

local function askOptions()
  local options = nil;
  if verbose then
    options = options or {};
    options.log = printAiLog;
  end
  if agentName then
    options = options or {};
    options.agent = agentName;
  end
  return options;
end

local function joinArgs(start)
  local parts = {};
  for i = start, args.n do
    parts[#parts + 1] = args[i];
  end
  return table.concat(parts, ' ');
end

local function printSessions(ai)
  local ok, result = ai.listSessions(askOptions());
  if not ok then
    print(result);
    return;
  end
  if #result == 0 then
    print('no sessions');
  else
    for _, s in ipairs(result) do
      print((s.id or '?') .. '  ' .. (s.title or '(untitled)'));
    end
  end
end

local function askAndPrint(ai, prompt)
  local ok, result = ai.ask(prompt, askOptions());
  if not ok then
    print(result);
    return;
  end
  print(result.reply);
end

local function printLuaExecLog(message)
  local text = tostring(message or '');
  if text == '' then
    print('[lua-exec]');
    return;
  end

  local start = 1;
  while start <= #text do
    local newline = string.find(text, '\n', start, true);
    if not newline then
      print('[lua-exec] ' .. string.sub(text, start));
      return;
    end
    print('[lua-exec] ' .. string.sub(text, start, newline - 1));
    start = newline + 1;
  end
end

local function luaExec(ai, prompt)
  local ok, result = ai.luaExec(prompt, {
    executor = ai.createLuaExecutor({ live = true }),
    log = printLuaExecLog,
  });
  if not ok then
    printLuaExecLog('failed after ' .. tostring(result.attempts or 0) .. ' attempt(s)');
    if result.errorKind then
      printLuaExecLog('error kind: ' .. tostring(result.errorKind));
    end
    printLuaExecLog(tostring(result.error));
    return;
  end

  printLuaExecLog('final reply:');
  print(result.reply);
end

local command = args[1];

if command == '--version' or command == '-version' or command == 'version' then
  print('v' .. createVersion().forSelf());
  return;
end

if command == '--help' or command == '-help' or command == 'help' then
  printUsage();
  return;
end

if parseError then
  print(parseError);
  printUsage();
  return;
end

if args.n == 0 then
  printUsage();
  return;
end

local ai = createAi();

if (command == 'sessions' or command == '--sessions') and args.n == 1 then
  printSessions(ai);
  return;
end

if command == 'ping' and args.n == 1 then
  local ok, result = ai.ping(askOptions());
  if not ok then
    print(result);
    return;
  end
  print(result.reply);
  return;
end

if command == 'new' or command == '--new' then
  local prompt = joinArgs(2);
  if prompt == '' then
    printUsage();
    return;
  end
  ai.clearSession();
  askAndPrint(ai, prompt);
  return;
end

if command == 'lua-exec' or command == '--lua-exec' then
  local prompt = joinArgs(2);
  if prompt == '' then
    printUsage();
    return;
  end
  print('warning: ai lua-exec is deprecated and will be removed');
  luaExec(ai, prompt);
  return;
end

if string.sub(command, 1, 1) == '-' then
  printUsage();
  return;
end

askAndPrint(ai, joinArgs(1));
