local tasks = require('tasks')
local utils = require('tasks.utils')
local constants = require('tasks.constants')
local subcommands = {}

--- Completes `:Task` command.
---@param arg string: Current argument under cursor.
---@param cmd_line string: All arguments.
---@return table: List of all commands matched with `arg`.
function subcommands.complete(arg, cmd_line)
  local matches = {}

  local words = vim.split(cmd_line, ' ', { trimempty = true })
  if not vim.endswith(cmd_line, ' ') then
    -- Last word is not fully typed, don't count it
    table.remove(words, #words)
  end

  if #words == 1 then
    for subcommand in pairs(tasks) do
      if vim.startswith(subcommand, arg) and subcommand ~= 'setup' then
        table.insert(matches, subcommand)
      end
    end
  elseif #words == 2 then
    if words[2] == 'start' or words[2] == 'set_task_param' or words[2] == 'set_module_param' then
      local module_names = utils.get_module_names()
      table.insert(module_names, 'auto') -- Special value for automatic module detection
      for _, module_name in ipairs(module_names) do
        if vim.startswith(module_name, arg) then
          table.insert(matches, module_name)
        end
      end
    end
  elseif #words == 3 then
    if words[2] == 'start' or words[2] == 'set_task_param' or words[2] == 'set_module_param' then
      local ok, module = pcall(require, 'tasks.module.' .. words[3])
      if ok then
        for key, value in pairs(words[2] == 'set_module_param' and module.params or module.tasks) do
          local name = type(key) == 'number' and value or key -- Handle arrays
          if vim.startswith(name, arg) then
            table.insert(matches, name)
          end
        end
      end
    end
  elseif #words == 4 then
    if words[2] == 'set_task_param' then
      for _, param_name in ipairs(constants.task_params) do
        if vim.startswith(param_name, arg) then
          table.insert(matches, param_name)
        end
      end
    end
  end

  return matches
end

--- Run specified subcommand received from completion.
---@param subcommand table
function subcommands.run(subcommand)
  local subcommand_func = tasks[subcommand.fargs[1]]
  if not subcommand_func then
    utils.notify(string.format('No such subcommand named "%s"', subcommand.fargs[1]), vim.log.levels.ERROR)
    return
  end
  local subcommand_info = debug.getinfo(subcommand_func)
  if subcommand_info.isvararg and #subcommand.fargs - 1 < subcommand_info.nparams then
    utils.notify(string.format('Subcommand %s should have at least %s argument(s)', subcommand.fargs[1], subcommand_info.nparams + 1), vim.log.levels.ERROR)
    return
  elseif not subcommand_info.isvararg and #subcommand.fargs - 1 ~= subcommand_info.nparams then
    utils.notify(string.format('Subcommand %s should have %s argument(s)', subcommand.fargs[1], subcommand_info.nparams + 1), vim.log.levels.ERROR)
    return
  end
  subcommand_func(unpack(subcommand.fargs, 2))
end

return subcommands
