-- LSP capabilities (blink.cmp augments these automatically)
local capabilities = vim.lsp.protocol.make_client_capabilities()

-- on_attach function with LSP keybindings
local on_attach = function(client, bufnr)
  -- Attach navic for breadcrumb tracking
  if client.server_capabilities.documentSymbolProvider then
    require("nvim-navic").attach(client, bufnr)
  end

  local function opts(desc)
    return { buffer = bufnr, desc = "LSP " .. desc }
  end

  local map = vim.keymap.set

  -- Navigation
  map("n", "gD", vim.lsp.buf.declaration, opts "Go to declaration")
  map("n", "gd", vim.lsp.buf.definition, opts "Go to definition")
  map("n", "gi", vim.lsp.buf.implementation, opts "Go to implementation")
  map("n", "gr", vim.lsp.buf.references, opts "Show references")
  map("n", "<leader>sh", vim.lsp.buf.signature_help, opts "Show signature help")
  map("n", "<leader>D", vim.lsp.buf.type_definition, opts "Go to type definition")

  -- Workspace
  map("n", "<leader>wa", vim.lsp.buf.add_workspace_folder, opts "Add workspace folder")
  map("n", "<leader>wr", vim.lsp.buf.remove_workspace_folder, opts "Remove workspace folder")
  map("n", "<leader>wl", function()
    print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
  end, opts "List workspace folders")

  -- Actions
  map("n", "<leader>ra", vim.lsp.buf.rename, opts "Rename symbol")
  map({ "n", "v" }, "<leader>ca", vim.lsp.buf.code_action, opts "Code action")

  -- Diagnostics (already mapped in mappings.lua, but keeping for consistency)
  map("n", "[d", vim.diagnostic.goto_prev, opts "Go to previous diagnostic")
  map("n", "]d", vim.diagnostic.goto_next, opts "Go to next diagnostic")
  map("n", "<leader>q", vim.diagnostic.setloclist, opts "Set loclist")
end

local servers = {
  rust_analyzer = {
    filetypes = { "rust" },
    on_attach = on_attach,
    capabilities = capabilities,
    settings = {
      ["rust-analyzer"] = {
        completion = {
          addCallParenthesis = true,
          addCallArgumentSnippets = false,
          postfix = {
            enabled = false,
          },
        },
        callInfo = {
          full = false,
        },
      }
    }
  },
  csharp_ls = {
    filetypes = { "cs" },
    on_attach = on_attach,
    capabilities = capabilities,
  },
  clangd = {
    filetypes = { "c", "cpp", "objc", "objcpp" },
    on_attach = on_attach,
    capabilities = capabilities,
  },
  glsl_analyzer = {
    filetypes = { "glsl" },
    on_attach = on_attach,
    capabilities = capabilities,
  },
  wgsl_analyzer = {
    filetypes = { "wgsl", "wesl" },
    on_attach = on_attach,
    capabilities = capabilities,
  },
  pylsp = {
    filetypes = { "python" },
    on_attach = on_attach,
    capabilities = capabilities,
  },
  ron_lsp = {
    cmd = { "ron-lsp" },
    filetypes = { "ron" },
    root_dir = function(fname)
      local util = require("lspconfig.util")
      return util.root_pattern("Cargo.toml", ".git")(fname) or vim.uv.cwd()
    end,
    on_attach = on_attach,
    capabilities = capabilities,
  },
}

for server, opts in pairs(servers) do
  vim.lsp.config(server, opts)
  if opts.filetypes then
    vim.api.nvim_create_autocmd("FileType", {
      pattern = opts.filetypes,
      callback = function()
        vim.lsp.enable(server)
      end,
    })
  else
    vim.lsp.enable(server)
  end
end
