local git_root_cache = {}

local function get_git_root(path)
	local dir = vim.fn.fnamemodify(path, ":h")
	if git_root_cache[dir] then
		return git_root_cache[dir]
	end
	local root = vim.fn.systemlist("git -C " .. vim.fn.shellescape(dir) .. " rev-parse --show-toplevel 2>/dev/null")[1]
	if vim.v.shell_error ~= 0 or not root or root == "" then
		root = false
	end
	git_root_cache[dir] = root
	return root
end

local function git_relative_path(abs_path)
	if abs_path == "" then
		return "[No Name]"
	end
	local root = get_git_root(abs_path)
	if root then
		local rel = abs_path:sub(#root + 2) -- strip root + trailing /
		return rel ~= "" and rel or abs_path
	end
	return abs_path
end

vim.api.nvim_create_autocmd("DirChanged", {
	callback = function()
		git_root_cache = {}
	end,
})

local mru_bufs = {}

-- Initialize with currently listed buffers
for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
	if vim.bo[bufnr].buflisted then
		table.insert(mru_bufs, bufnr)
	end
end

local augroup = vim.api.nvim_create_augroup("MRU_Buffers", { clear = true })

vim.api.nvim_create_autocmd("BufEnter", {
	group = augroup,
	callback = function(args)
		local bufnr = args.buf
		if vim.bo[bufnr].buflisted then
			for i, b in ipairs(mru_bufs) do
				if b == bufnr then
					table.remove(mru_bufs, i)
					break
				end
			end
			table.insert(mru_bufs, 1, bufnr)
		end
	end,
})

vim.api.nvim_create_autocmd("BufDelete", {
	group = augroup,
	callback = function(args)
		local bufnr = args.buf
		for i, b in ipairs(mru_bufs) do
			if b == bufnr then
				table.remove(mru_bufs, i)
				break
			end
		end
	end,
})

function _G.TabLine()
	local current_buf = vim.api.nvim_get_current_buf()
	local available_width = vim.o.columns
	local used_width = 0
	local tabline = ""
	local ellipsis = "%#TabLineFill# ..."

	local valid_bufs = {}

	-- 1. Always place the current buffer first
	if vim.bo[current_buf].buflisted then
		table.insert(valid_bufs, current_buf)
	end

	-- 2. Add the rest of the buffers in native ID order (matches :bnext)
	for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
		if bufnr ~= current_buf and vim.api.nvim_buf_is_valid(bufnr) and vim.bo[bufnr].buflisted then
			table.insert(valid_bufs, bufnr)
		end
	end

	for _, bufnr in ipairs(valid_bufs) do
		local is_current = (bufnr == current_buf)
		local name = git_relative_path(vim.api.nvim_buf_get_name(bufnr))

		local hl = is_current and "%#WildMenu#" or "%#TabLine#"

		local status_raw = ""
		local status_hl = ""
		if vim.bo[bufnr].modified then
			status_raw = status_raw .. "● "
			status_hl = status_hl .. "%#Error#● " .. hl
		end
		if vim.bo[bufnr].readonly then
			status_raw = status_raw .. " "
			status_hl = status_hl .. "%#Error# " .. hl
		end

		local text_to_measure = string.format(" %s %s", name, status_raw)
		local display_width = vim.api.nvim_strwidth(text_to_measure)

		if used_width + display_width > available_width - 4 then
			tabline = tabline .. ellipsis
			break
		end

		local segment = string.format("%s %s %s", hl, name, status_hl)
		tabline = tabline .. segment
		used_width = used_width + display_width
	end

	return tabline .. "%#TabLineFill#"
end

vim.opt.tabline = "%!v:lua.TabLine()"
vim.opt.showtabline = 2 -- always show tabs

-- Adds the buffer name to the top of each window
vim.opt.winbar = " %t %m"
