-- Custom nvim-cmp source for Cursor Agent autocompletion
local cmp = require('cmp')
local source = {}

source.new = function()
  return setmetatable({}, { __index = source })
end

source.is_available = function()
  -- Check if cursor-agent is available
  return vim.fn.executable('cursor-agent') == 1
end

source.get_trigger_characters = function()
  return {}
end

source.complete = function(self, request, callback)
  -- Only trigger if there's meaningful context (at least 3 characters typed)
  local bufnr = request.context.bufnr
  local cursor = vim.api.nvim_win_get_cursor(0)
  local line_num = cursor[1]
  local col_num = cursor[2] + 1  -- Convert to 1-indexed
  
  -- Get current line and context
  local current_line = vim.api.nvim_buf_get_lines(bufnr, line_num - 1, line_num, false)[1] or ''
  local before_cursor = current_line:sub(1, col_num - 1)
  
  -- Skip if too little context (less than 3 characters before cursor)
  if #before_cursor:gsub('%s+', '') < 3 then
    callback({ items = {} })
    return
  end
  
  -- Get surrounding context (last 30 lines for better context)
  local start_line = math.max(0, line_num - 30)
  local context_lines = vim.api.nvim_buf_get_lines(bufnr, start_line, line_num, false)
  local context = table.concat(context_lines, '\n')
  
  -- Build prompt for cursor-agent - optimized for completion
  local prompt = string.format(
    "Complete the code after the cursor. Return ONLY the text that should appear after the cursor position, nothing else. Do not include any explanation or the existing code.\n\nContext:\n%s\n\nComplete after cursor (|): %s|",
    context,
    before_cursor
  )
  
  -- Call cursor-agent with --print flag
  local cmd = {
    'cursor-agent',
    '--print',
    '--output-format', 'text',
    prompt
  }
  
  local completed = false
  local job_id = vim.fn.jobstart(cmd, {
    stdout_buffered = true,
    stderr_buffered = true,
    on_stdout = function(_, data, _)
      if completed then return end
      completed = true
      
      if not data or #data == 0 then
        callback({ items = {} })
        return
      end
      
      -- Parse completion suggestions
      local items = {}
      local full_text = table.concat(data, '\n'):gsub('%s+', ' '):gsub('^%s+', ''):gsub('%s+$', '')
      
      if full_text and full_text ~= '' then
        -- Try to extract just the completion part
        -- Remove any text that matches the before_cursor context
        local completion = full_text
        
        -- Clean up common prefixes that might be repeated
        if before_cursor ~= '' then
          local escaped_prefix = vim.pesc(before_cursor:match('[%w_]+$') or '')
          if escaped_prefix ~= '' then
            completion = completion:gsub('^' .. escaped_prefix, '')
          end
        end
        
        -- Split into potential multiple completions (by lines or common patterns)
        if completion:find('\n') then
          -- Multiple lines - create separate items
          for line in completion:gmatch('[^\n]+') do
            line = line:gsub('^%s+', ''):gsub('%s+$', '')
            if line ~= '' and #line > 0 then
              table.insert(items, {
                label = line,
                kind = cmp.lsp.CompletionItemKind.Text,
                documentation = {
                  kind = 'markdown',
                  value = '**Cursor AI Completion**\n\n' .. line
                },
                sortText = '0' .. line,  -- Prioritize Cursor completions
              })
            end
          end
        else
          -- Single line completion
          completion = completion:gsub('^%s+', ''):gsub('%s+$', '')
          if completion ~= '' and #completion > 0 then
            -- Create multiple suggestions: full completion, first word, etc.
            table.insert(items, {
              label = completion,
              kind = cmp.lsp.CompletionItemKind.Text,
              documentation = {
                kind = 'markdown',
                value = '**Cursor AI Completion**\n\n' .. completion
              },
              sortText = '0' .. completion,
            })
            
            -- Also add first word/phrase as a shorter option
            local first_part = completion:match('^([%w_]+)') or completion:match('^([^%s]+)')
            if first_part and first_part ~= completion and #first_part > 2 then
              table.insert(items, {
                label = first_part,
                kind = cmp.lsp.CompletionItemKind.Text,
                documentation = {
                  kind = 'markdown',
                  value = '**Cursor AI Completion** (partial)\n\n' .. first_part
                },
                sortText = '1' .. first_part,
              })
            end
          end
        end
      end
      
      callback({ items = items })
    end,
    on_stderr = function(_, data, _)
      if completed then return end
      completed = true
      -- On error, return empty completions
      callback({ items = {} })
    end,
    on_exit = function(_, code, _)
      if completed then return end
      completed = true
      if code ~= 0 then
        callback({ items = {} })
      end
    end
  })
  
  -- Set timeout (8 seconds for AI completion)
  vim.defer_fn(function()
    if not completed and vim.fn.jobwait({ job_id }, 0)[1] == -1 then
      vim.fn.jobstop(job_id)
      completed = true
      callback({ items = {} })
    end
  end, 8000)
end

return source
