vim.pack.add({
	{ src = "https://github.com/folke/which-key.nvim" },
	{ src = "https://github.com/tpope/vim-fugitive" },
	{ src = "https://github.com/stevearc/oil.nvim" },
	{ src = "https://github.com/echasnovski/mini.icons" },
	{ src = "https://github.com/yorickpeterse/nvim-jump" },
	{ src = "https://github.com/ibhagwan/fzf-lua" },
})
require("which-key").setup({
	preset = "helix",
})

vim.keymap.set("n", "<leader>gs", vim.cmd.Git, { desc = "Fugitive git command" })

require("oil").setup({
	default_file_explorer = true,
	view_options = {
		show_hidden = true,
	},
	preview = {
		max_width = 0.9,
		min_width = { 40, 0.4 },
		max_height = 0.9,
		min_height = { 5, 0.1 },
	},
	float = {
		max_width = math.floor(vim.o.columns * 0.66),
		max_height = math.floor(vim.o.lines * 0.66),
	},
	keymaps = {
		["<Esc><Esc>"] = { "actions.close", mode = "n" },
	},
})

vim.api.nvim_create_autocmd("User", {
	pattern = "OilEnter",
	callback = vim.schedule_wrap(function(args)
		local oil = require("oil")
		if vim.api.nvim_get_current_buf() == args.data.buf and oil.get_current_dir() then
			require("oil.actions").preview.callback()
		end
	end),
})

vim.keymap.set("n", "<leader>pv", function()
	if vim.o.lines >= 40 and vim.o.columns >= 120 then
		require("oil").open_float()
	else
		require("oil").open()
	end
end, { desc = "Open file explorer" })
vim.keymap.set({ "n", "x", "o" }, "<leader>f", require("jump").start, {})

local function get_project_root()
	-- 1. Prioritize Terraform or nvim config project root (keeps search local to the TF module)
	local tf_root = vim.fs.root(0, { ".terraform", ".terraform.lock.hcl" })
	local nvim_root = vim.fs.root(0, { "nvim-pack-lock.json" })

	-- 2. Fallback to Git root (prioritizes the top-level repo for Rust/Go/etc.)
	local git_root = vim.fs.root(0, ".git")

	-- 3. Fallback to language markers if not in a git repo
	local lang_root = vim.fs.root(0, {
		"Cargo.toml",
		"go.mod",
		"pyproject.toml",
		"requirements.txt",
		"pom.xml",
		"build.gradle",
		".luarc.json",
	})

	-- Chain them in the exact priority order you want
	return tf_root or nvim_root or git_root or lang_root or vim.fn.getcwd()
end

local function get_submodule_excludes()
	local git_root = vim.fs.root(0, ".git")
	if not git_root then
		return {}
	end
	local handle =
		io.popen("git -C " .. vim.fn.shellescape(git_root) .. " submodule --quiet foreach 'echo $sm_path' 2>/dev/null")
	if not handle then
		return {}
	end
	local excludes = {}
	for line in handle:lines() do
		table.insert(excludes, line)
	end
	handle:close()
	return excludes
end

vim.keymap.set("n", "<leader>pf", function()
	local fzf = require("fzf-lua")
	local defaults = fzf.defaults.files
	local fd_opts = defaults.fd_opts
	local rg_opts = defaults.rg_opts
	for _, sub in ipairs(get_submodule_excludes()) do
		fd_opts = fd_opts .. " --exclude " .. vim.fn.shellescape(sub)
		rg_opts = "-g '!" .. sub .. "' " .. rg_opts
	end
	rg_opts = "--hidden " .. rg_opts
	fzf.files({ cwd = get_project_root(), fd_opts = fd_opts, rg_opts = rg_opts })
end, { desc = "Fuzzy find project files" })

vim.keymap.set("n", "<leader>ps", function()
	local fzf = require("fzf-lua")
	local defaults = fzf.defaults.grep
	local rg_opts = defaults.rg_opts
	for _, sub in ipairs(get_submodule_excludes()) do
		rg_opts = "-g '!" .. sub .. "' " .. rg_opts
	end
	rg_opts = "--hidden " .. rg_opts
	fzf.live_grep({ cwd = get_project_root(), rg_opts = rg_opts })
end, { desc = "Live grep project text" })

vim.keymap.set("n", "<leader><space>", function()
	require("fzf-lua").buffers()
end, { desc = "Fuzzy find open files" })

vim.keymap.set("n", "<leader>gf", function()
	local excludes = get_submodule_excludes()
	local pathspecs = {}
	for _, sub in ipairs(excludes) do
		table.insert(pathspecs, ":(exclude)" .. sub)
	end
	require("fzf-lua").git_files({ cmd = "git ls-files --exclude-standard -- . " .. table.concat(pathspecs, " ") })
end, { desc = "Fuzzy find tracked Git files" })

vim.api.nvim_create_autocmd("BufEnter", {
	group = vim.api.nvim_create_augroup("AutoChdirProjectRoot", { clear = true }),
	callback = function(args)
		-- Only change directory for normal files
		if vim.bo[args.buf].buftype == "" and vim.api.nvim_buf_get_name(args.buf) ~= "" then
			local root = get_project_root()
			if root and root ~= vim.fn.getcwd() then
				vim.api.nvim_set_current_dir(root)
			end
		end
	end,
})
