vim.pack.add({
	{ src = "https://github.com/olimorris/codecompanion.nvim" },
	{ src = "https://github.com/nvim-lua/plenary.nvim" },
	{
		src = "https://github.com/saghen/blink.cmp",
		version = vim.version.range("^1"),
	},
})

local codecompanion = require("codecompanion")
local has_gemini = os.getenv("GEMINI_API_KEY")

codecompanion.setup({
	interactions = {
		chat = {
			adapter = has_gemini and "gemini" or "kiro",
			tools = {
				["web_search"] = {
					opts = { require_approval_before = false },
				},
				["fetch_webpage"] = {
					opts = { require_approval_before = false },
				},
			},
		},
		inline = { adapter = has_gemini and "gemini" or nil },
	},
	adapters = {
		http = {
			gemini = function()
				return require("codecompanion.adapters").extend("gemini", {
					env = {
						api_key = os.getenv("GEMINI_API_KEY") or "cmd:cat ~/.gemini_api_key",
					},
					schema = {
						model = {
							default = "gemini-3.1-pro-preview",
						},
					},
				})
			end,
		},
		acp = {
			kiro = function()
				return require("codecompanion.adapters").extend("kiro", {
					defaults = {
						model = "kiro_default",
					},
				})
			end,
		},
	},
})

-- Optional: Keymaps for CodeCompanion
vim.keymap.set({ "n", "v" }, "<leader>a", "<cmd>CodeCompanionChat Toggle<cr>", { noremap = true, silent = true })
-- Inline prompt for buffer modifications (Generates diffs)
vim.keymap.set({ "n", "v" }, "<leader>ci", "<cmd>CodeCompanion <cr>", { noremap = true, silent = true })
-- Add visual selection to chat
vim.keymap.set("v", "<leader>ca", "<cmd>CodeCompanionChat Add<cr>", { noremap = true, silent = true })
-- Action palette (Use this to Accept/Reject inline diffs)
vim.keymap.set({ "n", "v" }, "<leader>cp", "<cmd>CodeCompanionActions<cr>", { noremap = true, silent = true })
vim.cmd([[cab cc CodeCompanion]])

vim.cmd("packadd blink.cmp")
local blink = require("blink.cmp")
blink.setup({
	keymap = { preset = "default" },
	appearance = { nerd_font_variant = "mono" },
	completion = {
		menu = { border = "rounded" },
		documentation = { auto_show = true, window = { border = "rounded" } },
		ghost_text = { enabled = true }, -- Enables ghost text in insert mode
	},

	cmdline = {
		keymap = { ["<Tab>"] = { "show", "accept" } },
		completion = { menu = { auto_show = true }, ghost_text = { enabled = true } },
	},

	-- By removing `snippets = { preset = 'luasnip' }`, Blink natively
	-- defaults to Neovim 0.11+ built-in `vim.snippet` API.

	sources = {
		-- Added codecompanion, removed emoji
		default = { "lsp", "path", "snippets", "buffer", "codecompanion" },
		providers = {
			cmdline = {
				min_keyword_length = function(ctx)
					if ctx.mode == "cmdline" and string.find(ctx.line, " ") == nil then
						return 3
					end
					return 0
				end,
			},
			-- Wire up CodeCompanion to Blink
			codecompanion = {
				name = "CodeCompanion",
				module = "codecompanion.providers.completion.blink",
				enabled = true,
				score_offset = 100, -- Boosts priority so AI suggestions appear first in ghost text
				async = true, -- Ensures AI fetching doesn't block the UI
			},
		},
	},
	fuzzy = { implementation = "prefer_rust_with_warning" },
})

-- Ensure borders stay colored even after toggling light/dark themes
vim.api.nvim_create_autocmd("ColorScheme", {
	pattern = "*",
	callback = function()
		vim.api.nvim_set_hl(0, "BlinkCmpMenuBorder", { link = "Special" })
		vim.api.nvim_set_hl(0, "BlinkCmpDocBorder", { link = "Special" })
		vim.api.nvim_set_hl(0, "FloatBorder", { link = "Special" })
	end,
})

local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = blink.get_lsp_capabilities(capabilities)

-- Safely merge with existing global LSP capabilities so we don't overwrite settings from ink/lsp.lua
local existing_config = vim.lsp.config["*"]
if type(existing_config) == "table" and type(existing_config.capabilities) == "table" then
	capabilities = vim.tbl_deep_extend("force", existing_config.capabilities, capabilities)
end

-- Apply to all natively loaded 0.12 LSP servers
vim.lsp.config("*", {
	capabilities = capabilities,
	-- Note: We DO NOT use vim.lsp.completion.enable() here because
	-- Blink is taking over the UI rendering.
})
