local api = vim.api

---@class mentions_source : cmp.Source
---@field mentions {description: string, command: AvanteMentions, details: string, shorthelp?: string, callback?: AvanteMentionCallback}[]
---@field bufnr integer
local mentions_source = {}
mentions_source.__index = mentions_source

---@param mentions {description: string, command: AvanteMentions, details: string, shorthelp?: string, callback?: AvanteMentionCallback}[]
---@param bufnr integer
function mentions_source:new(mentions, bufnr)
  local instance = setmetatable({}, mentions_source)

  instance.mentions = mentions
  instance.bufnr = bufnr

  return instance
end

function mentions_source:is_available() return api.nvim_get_current_buf() == self.bufnr end

mentions_source.get_position_encoding_kind = function() return "utf-8" end

function mentions_source:get_trigger_characters() return { "@" } end

function mentions_source:get_keyword_pattern() return [[\%(@\|#\|/\)\k*]] end

function mentions_source:complete(_, callback)
  local kind = require("cmp").lsp.CompletionItemKind.Variable

  local items = {}

  for _, mention in ipairs(self.mentions) do
    table.insert(items, {
      label = "@" .. mention.command .. " ",
      kind = kind,
      detail = mention.details,
    })
  end

  callback({
    items = items,
    isIncomplete = false,
  })
end

---@param completion_item table
---@param callback fun(response: {behavior: number})
function mentions_source:execute(completion_item, callback)
  local current_line = api.nvim_get_current_line()
  local label = completion_item.label:match("^@(%S+)") -- Extract mention command without '@' and space

  -- Find the corresponding mention
  local selected_mention
  for _, mention in ipairs(self.mentions) do
    if mention.command == label then
      selected_mention = mention
      break
    end
  end

  -- Execute the mention's callback if it exists
  if selected_mention and type(selected_mention.callback) == "function" then
    selected_mention.callback(selected_mention)
    -- Get the current cursor position
    local row, col = unpack(api.nvim_win_get_cursor(0))

    -- Replace the current line with the new line (removing the mention)
    local new_line = current_line:gsub(vim.pesc(completion_item.label), "")
    api.nvim_buf_set_lines(0, row - 1, row, false, { new_line })

    -- Adjust the cursor position if needed
    local new_col = math.min(col, #new_line)
    api.nvim_win_set_cursor(0, { row, new_col })
  end

  callback({ behavior = require("cmp").ConfirmBehavior.Insert })
end

return mentions_source