---@class LibAT : AceAddon, AceEvent-3.0, AceConsole-3.0
local LibAT = LibStub('AceAddon-3.0'):NewAddon('Libs-AddonTools', 'AceEvent-3.0', 'AceConsole-3.0')
-- Global namespace
_G.LibAT = LibAT

-- Debug flag - set to true to enable debug messages during development/testing
LibAT.DebugMode = false

-- Version information
LibAT.Version = C_AddOns.GetAddOnMetadata('Libs-AddonTools', 'Version') or 0
LibAT.BuildNum = C_AddOns.GetAddOnMetadata('Libs-AddonTools', 'X-Build') or 0
LibAT.BuildType = 'Release'
--@alpha@
LibAT.BuildType = 'ALPHA ' .. LibAT.BuildNum
--@end-alpha@
--@beta@
LibAT.BuildType = 'BETA ' .. LibAT.BuildNum
--@end-beta@

-- Core systems storage
LibAT.UI = {}
LibAT.Components = {}
LibAT.Systems = {}

-- UI ready flag - set to true after UI components are loaded
-- Systems can check this flag to ensure UI is available before using it
LibAT.UI.Ready = false

---Debug print function - only prints if DebugMode is enabled
---@param ... any Messages to print
function LibAT:Debug(...)
	if self.DebugMode then
		self:Print('[DEBUG]', ...)
	end
end

---Safely reload the UI with instance+combat check
---@param showMessage? boolean Whether to show error message (default: true)
---@return boolean success Whether reload was initiated or would be allowed
function LibAT:SafeReloadUI(showMessage)
	if showMessage == nil then
		showMessage = true
	end

	local inInstance = IsInInstance()
	local inCombat = InCombatLockdown()

	if inInstance and inCombat then
		if showMessage then
			self:Print('|cffff0000Cannot reload UI while in combat in an instance|r')
		end
		return false
	end

	ReloadUI()
	return true
end

---Options Manager - Simple interface for managing AceConfig options
LibAT.Options = {
	optionsTable = {},
	registry = nil,
	dialog = nil,
}

---Initialize the Options system with AceConfig
function LibAT.Options:Init()
	if not self.registry then
		self.registry = LibStub('AceConfigRegistry-3.0', true)
		self.dialog = LibStub('AceConfigDialog-3.0', true)
	end
end

---Add options to the config system
---@param options table The options table
---@param name string The name for this options group
---@param parent? string Optional parent category
function LibAT.Options:AddOptions(options, name, parent)
	self:Init()

	if not self.registry then
		LibAT:Print('Warning: AceConfig not available, options cannot be registered')
		return
	end

	-- Store the options
	self.optionsTable[name] = options

	-- Register with AceConfig if available
	if self.registry and self.dialog then
		self.registry:RegisterOptionsTable(name, options)

		-- Try to add to Blizzard options
		-- If parent is specified but doesn't exist, add without parent
		local success, err = pcall(function()
			if parent then
				-- First ensure parent exists by trying to create it
				if not self.optionsTable[parent] then
					-- Create a dummy parent category
					local parentOptions = {
						type = 'group',
						name = parent,
						args = {},
					}
					self.registry:RegisterOptionsTable(parent, parentOptions)
					self.dialog:AddToBlizOptions(parent, parent)
					self.optionsTable[parent] = parentOptions
				end
				self.dialog:AddToBlizOptions(name, name, parent)
			else
				self.dialog:AddToBlizOptions(name, name)
			end
		end)

		if not success then
			-- Fallback: add without parent if there was an error
			LibAT:Print('Warning: Could not add options with parent "' .. tostring(parent) .. '", adding as standalone. Error: ' .. tostring(err))
			pcall(function()
				self.dialog:AddToBlizOptions(name, name)
			end)
		end
	end
end

---Toggle options dialog
---@param path? table Optional path to specific options
function LibAT.Options:ToggleOptions(path)
	self:Init()

	if self.dialog then
		if path and #path > 0 then
			-- Open specific options page
			Settings.OpenToCategory(path[#path])
		else
			-- Open main LibAT options
			Settings.OpenToCategory('Libs-AddonTools')
		end
	end
end

---Register a system with LibAT
---@param name string The name of the system
---@param system table The system object
function LibAT:RegisterSystem(name, system)
	if not name or not system then
		self:Print('RegisterSystem: Invalid parameters')
		return
	end
	self.Systems[name] = system
	self:Debug(string.format('Registered system: %s', name))
end

---Initialize the LibAT framework
function LibAT:OnInitialize()
	-- Initialize database
	local defaults = {
		profile = {
			errorDisplay = {
				autoPopup = false,
				chatframe = true,
				fontSize = 12,
				minimapIcon = { hide = false, minimapPos = 97.66349921766368 },
				ignoredErrors = {}, -- Store signatures of errors to ignore
			},
			profileManager = {
				lastExportFormat = 'text',
				defaultProfileName = 'LibAT Import',
			},
		},
	}

	self.Database = LibStub('AceDB-3.0'):New('LibsAddonToolsDB', defaults, 'Default')
	self.DB = self.Database.profile
end

---Enable the LibAT framework
function LibAT:OnEnable()
	-- Mark UI as ready - all UI components have been loaded
	self.UI.Ready = true
	if LibAT.Log then
		LibAT.Log('UI components loaded and ready', 'Core.Framework', 'debug')
	end
end

---Handle slash commands
SLASH_LIBAT1 = '/libat'
SlashCmdList['LIBAT'] = function(msg)
	local args = { strsplit(' ', msg) }
	local command = args[1] and args[1]:lower() or ''
	local subcommand = args[2] and args[2]:lower() or ''

	if command == 'debug' then
		LibAT.DebugMode = not LibAT.DebugMode
		LibAT:Print('Debug mode:', LibAT.DebugMode and '|cff00ff00Enabled|r' or '|cffff0000Disabled|r')
	elseif command == 'errors' or command == 'error' then
		-- Default action: show errors (or handle subcommands if added later)
		if subcommand == 'show' or subcommand == '' then
			if LibAT.ErrorDisplay then
				LibAT.ErrorDisplay.BugWindow:OpenErrorWindow()
			elseif _G.LibATErrorDisplay then
				_G.LibATErrorDisplay.BugWindow:OpenErrorWindow()
			else
				LibAT:Print('Error Display system not available')
			end
		else
			LibAT:Print('Unknown errors subcommand: ' .. subcommand)
			LibAT:Print('Available: show')
		end
	elseif command == 'profiles' or command == 'profile' then
		-- Default action: open profile manager (or handle subcommands if added later)
		if subcommand == 'show' or subcommand == '' then
			if LibAT.ProfileManager then
				LibAT.ProfileManager:ToggleWindow()
			else
				LibAT:Print('Profile Manager system not available')
			end
		else
			LibAT:Print('Unknown profiles subcommand: ' .. subcommand)
			LibAT:Print('Available: show')
		end
	elseif command == 'logs' or command == 'log' then
		-- Default action: toggle logs (or handle subcommands if added later)
		if subcommand == 'show' or subcommand == 'toggle' or subcommand == '' then
			if LibAT.Logger then
				LibAT.Logger.ToggleWindow()
			else
				LibAT:Print('Logger system not available')
			end
		else
			LibAT:Print('Unknown logs subcommand: ' .. subcommand)
			LibAT:Print('Available: show, toggle')
		end
	else
		LibAT:Print('LibAT Commands:')
		LibAT:Print('  /libat debug - Toggle debug mode (shows initialization messages)')
		LibAT:Print('  /libat errors [show] - Open error display window')
		LibAT:Print('  /libat profiles [show] - Open profile manager')
		LibAT:Print('  /libat logs [show|toggle] - Toggle logger window')
		LibAT:Print(' ')
		LibAT:Print('Shortcuts:')
		LibAT:Print('  /errors - Open error display')
		LibAT:Print('  /logs - Toggle logger')
		LibAT:Print('  /profiles - Open profile manager')
	end
end

-- Shortcut aliases
SLASH_ERRORS1 = '/errors'
SlashCmdList['ERRORS'] = function(msg)
	SlashCmdList['LIBAT']('errors ' .. (msg or ''))
end

SLASH_LOGS1 = '/logs'
SlashCmdList['LOGS'] = function(msg)
	SlashCmdList['LIBAT']('logs ' .. (msg or ''))
end

SLASH_PROFILES1 = '/profiles'
SlashCmdList['PROFILES'] = function(msg)
	SlashCmdList['LIBAT']('profiles ' .. (msg or ''))
end

SLASH_RL1 = '/rl'
SlashCmdList['RL'] = function()
	LibAT:SafeReloadUI()
end
