-- lx-bundle:true

local core = require("core")
local command = require("core.command")
local keymap = require("core.keymap")
local LogView = require("core.log.view")

-- Returns the first open log view and the node that owns it
local function find_log_view()
	for _, view in ipairs(core.workspace_view.root_node:get_children()) do
		if view:is(LogView) then
			return view, core.workspace_view.root_node:get_node_for_view(view)
		end
	end
end

-- Returns an unlocked leaf node suitable for opening utility views
local function find_openable_leaf()
	local active = core.workspace_view:get_active_node()
	if active and not active.locked then
		return active
	end

	local root = core.workspace_view.root_node
	if core.last_active_view then
		local last_node = root:get_node_for_view(core.last_active_view)
		if last_node and not last_node.locked then
			return last_node
		end
	end

	local stack = { root }
	while #stack > 0 do
		local node = table.remove(stack)
		if node.type == "leaf" then
			if not node.locked then
				return node
			end
		else
			table.insert(stack, node.b)
			table.insert(stack, node.a)
		end
	end
end

-- Activates an existing log view or opens one in the active node
local function open_log_view()
	local log_view, node = find_log_view()
	if log_view and node then
		node:set_active_view(log_view)
		return log_view
	end

	node = find_openable_leaf()
	if node then
		local view = LogView()
		node:add_view(view)
		return view
	end
	core.log_quiet("No unlocked pane available to open log view")
	return nil
end

-- Closes an open log view, if any
local function close_log_view()
	local log_view, node = find_log_view()
	if not (log_view and node) then
		return false
	end

	node:set_active_view(log_view)
	node:close_active_view(core.workspace_view.root_node)
	return true
end

command.add({
	-- Opens the log view in the active node
	["log:open"] = function()
		open_log_view()
	end,

	-- Opens the log view and jumps to the newest error-level entry
	["log:open-last-error"] = function()
		local view = open_log_view()
		if not view then
			return
		end
		-- Sync last_item so LogView:update does not immediately auto-scroll away
		view.last_item = core.log_items[#core.log_items]
		-- Prefer exact captured startup error ID and pin it against subsequent log churn
		if view:pin_item_by_id(core.startup_error_log_id) then
			return
		end
		-- Fallback to newest startup-tagged/generic error if exact ID is unavailable
		local idx = view:get_latest_startup_error_index() or view:get_latest_error_index()
		if idx and view:scroll_to_item(idx) then
			return
		end
		view:scroll_home()
	end,

	-- Toggles the log view open/closed
	["log:toggle"] = function()
		if not close_log_view() then
			open_log_view()
		end
	end,

	-- Scrolls log view one row toward newer entries
	["log:scroll-up"] = {
		requires = { "log_view" },
		perform = function()
			core.active_view:scroll_rows(-1)
		end,
	},

	-- Scrolls log view one row toward older entries
	["log:scroll-down"] = {
		requires = { "log_view" },
		perform = function()
			core.active_view:scroll_rows(1)
		end,
	},

	-- Scrolls log view by one page toward newer entries
	["log:page-up"] = {
		requires = { "log_view" },
		perform = function()
			core.active_view:scroll_page(-1)
		end,
	},

	-- Scrolls log view by one page toward older entries
	["log:page-down"] = {
		requires = { "log_view" },
		perform = function()
			core.active_view:scroll_page(1)
		end,
	},

	-- Jumps to newest log entries
	["log:home"] = {
		requires = { "log_view" },
		perform = function()
			core.active_view:scroll_home()
		end,
	},

	-- Jumps to oldest log entries
	["log:end"] = {
		requires = { "log_view" },
		perform = function()
			core.active_view:scroll_end()
		end,
	},
})

-- Register log navigation keys in plugin layer so defaults remain unchanged
keymap.add({
	["up"] = "log:scroll-up",
	["down"] = "log:scroll-down",
	["home"] = "log:home",
	["end"] = "log:end",
	["ctrl+home"] = "log:home",
	["ctrl+end"] = "log:end",
	["pageup"] = "log:page-up",
	["pagedown"] = "log:page-down",
}, {
	layer = "plugin"
})

return {
	open_log_view = open_log_view,
	close_log_view = close_log_view,
}
