--LIBS
local LDB = LibStub("LibDataBroker-1.1")
local DBIcon = LibStub("LibDBIcon-1.0")
local AceDBOptions = LibStub("AceDBOptions-3.0")
StefansLootTracker = LibStub("AceAddon-3.0"):NewAddon("Stefans Loot Tracker", "AceConsole-3.0", "AceEvent-3.0")

local defaults = {
    profile = {
        enabled = true,
        terms = "",
        loothist = {}, -- Loot History Database
        rollhist = {}, -- Roll History Database
        chathist = {}, -- Chat History Database
        qDebug = false,
        alertChat = false,
        rarityFilter = 2,
        excludeItems = "",
        minimap = { hide = false },
        historyWindowPosition = { point = "CENTER", relativePoint = "CENTER", x = 0, y = 0 },
        historyWindowSize = { width = 450, height = 550 }
    },
}

local options = {
    name = "Stefans Loot Tracker",
    handler = StefansLootTracker,
    type = 'group',
    args = {
        enabled = {
            order = 1,
            type = "toggle",
            name = "Enable",
            get = "IsEnabled",
            set = "ToggleEnabled",
        },
        alertChat = {
            order = 2,
            type = "toggle",
            name = "Announce in chat",
            get = "IsAlertChat",
            set = "ToggleAlertChat",
        },
        qDebug = {
            order = 3,
            type = "toggle",
            name = "Debug",
            get = "IsDebug",
            set = "ToggleDebug",
        },
        rarityFilter = {
            order = 4,
            type = "select",
            name = "Minimum Loot Rarity",
            desc = "Only track loot of this rarity or higher",
            values = {
                [0] = "Poor (Gray)",
                [1] = "Common (White)",
                [2] = "Uncommon (Green)",
                [3] = "Rare (Blue)",
                [4] = "Epic (Purple)",
                [5] = "Legendary (Orange)",
            },
            get = "GetRarityFilter",
            set = "SetRarityFilter",
        },
        minimapIcon = {
            order = 5,
            type = "toggle",
            name = "Show Minimap Icon",
            get = function() return not StefansLootTracker.db.profile.minimap.hide end,
            set = function(_, value)
                if value then
                    StefansLootTracker:ShowMinimapIcon()
                else
                    StefansLootTracker:HideMinimapIcon()
                end
            end,
        },
        spacer = {
            order = 6,
            type = "description",
            name = " ",  -- A blank space
            width = "full",
        },
        clearLootHistory = {
            order = 6,
            type = "execute",
            name = "Clear Loot History",
            desc = "Clear all recorded loot history",
            func = "ClearLootHistory",
            confirm = true,
            confirmText = "Are you sure you want to clear all loot history? This action cannot be undone."
        },
        clearRollHistory = {
            order = 7,
            type = "execute",
            name = "Clear Roll History",
            desc = "Clear all recorded roll history",
            func = "ClearRollHistory",
            confirm = true,
            confirmText = "Are you sure you want to clear all roll history? This action cannot be undone."
        },
        clearChatHistory = {
            order = 8,
            type = "execute",
            name = "Clear Chat History",
            desc = "Clear all recorded chat history",
            func = "ClearChatHistory",
            confirm = true,
            confirmText = "Are you sure you want to clear all chat history? This action cannot be undone."
        },

        excludeItems = {
            order = 9,
            type = "input",
            name = "Exclude Items",
            desc = "Enter a comma-separated list of item names to exclude from logging.",
            get = function(info) return StefansLootTracker.db.profile.excludeItems end,
            set = function(info, value) StefansLootTracker.db.profile.excludeItems = value end,
            width = "full",
            multiline = 3,
        },
    },
}

function StefansLootTracker:OnInitialize()
    -- Called when the addon is loaded
    self.db = LibStub("AceDB-3.0"):New("StefansLootTrackerDB", defaults, true)
    
    -- Create profile options
    local profileOptions = AceDBOptions:GetOptionsTable(self.db)

    LibStub("AceConfig-3.0"):RegisterOptionsTable("StefansLootTracker", options, {"StefansLootTracker", "slt"})
    
    -- Register the profile options table
    LibStub("AceConfig-3.0"):RegisterOptionsTable("StefansLootTracker_Profiles", profileOptions)
    
    -- Create the options panels
    self.optionsFrame = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("StefansLootTracker", "Stefans Loot Tracker")
    
    -- Create a separate panel for profiles
    self.profilesFrame = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("StefansLootTracker_Profiles", "Profiles", "Stefans Loot Tracker")

    self:RegisterChatCommand("slt", "ChatCommand")

    -- Create the LDB object
    local LDB_Object = LDB:NewDataObject("StefansLootTracker", {
        type = "data source",
        text = "Stefans Loot Tracker",
        icon = "Interface\\Icons\\INV_Misc_Bag_08",
        OnClick = function(_, button)
            if button == "LeftButton" then
                self:ToggleHistoryWindow()
            elseif button == "RightButton" then
                self:OpenOptions()
            end
        end,
        OnTooltipShow = function(tooltip)
            tooltip:AddLine("Stefans Loot Tracker")
            tooltip:AddLine("Left-click to toggle the history window")
            tooltip:AddLine("Right-click to open settings")
        end,
    })

    -- Register the LDB object with LibDBIcon
    DBIcon:Register("StefansLootTracker", LDB_Object, self.db.profile.minimap)

    -- Ensure the loot history window is closed by default
    if not self.historyFrame then
        self:CreateHistoryWindow()
    end
    self.historyFrame:Hide()
    self.isHistoryWindowOpen = false

    -- Register callbacks for profile changes
    self.db.RegisterCallback(self, "OnProfileChanged", "RefreshConfig")
    self.db.RegisterCallback(self, "OnProfileCopied", "RefreshConfig")
    self.db.RegisterCallback(self, "OnProfileReset", "RefreshConfig")

    self:ApplySettings()
end

function StefansLootTracker:OnEnable()
    -- Called when the addon is enabled
    self:RegisterEvent("CHAT_MSG_LOOT")
    self:RegisterEvent("CHAT_MSG_PARTY")
    self:RegisterEvent("CHAT_MSG_PARTY_LEADER")
    self:RegisterEvent("CHAT_MSG_RAID")
    self:RegisterEvent("CHAT_MSG_RAID_LEADER")
    self:RegisterEvent("CHAT_MSG_SYSTEM")
    self:RegisterEvent("CHAT_MSG_LOOT")

    -- Ensure the loot history window is created
    if not self.historyFrame then
        self:CreateHistoryWindow()
    end
end

function StefansLootTracker:OnDisable()
    -- Called when the addon is disabled
    if self.historyFrame and self.historyFrame:IsShown() then
        self.historyFrame:Hide()
    end
end

function StefansLootTracker:debugPrint(message)
    if self.db.profile.qDebug then
        print("Debug: " .. message)
    end
end

function StefansLootTracker:getRarity(str)
    if not str or type(str) ~= "string" or str == "" then
        print("Error: Received an invalid loot string.")
        return 0
    end

    self:debugPrint("Received loot string: " .. str)

    local rarityHex = string.match(str, "|c(%x+)|H")
    local rarity = self:getRarityFromHex(rarityHex)

    return rarity
end

function StefansLootTracker:CHAT_MSG_PARTY(event, arg1, arg2)
    self:debugPrint("CHAT_MSG_PARTY event received")
    self:debugPrint("arg1: " .. tostring(arg1))
    self:debugPrint("arg2: " .. tostring(arg2))

    message = tostring(arg2) .. ": " .. tostring(arg1)

    if not self.db.profile.enabled then return end
    if self:matchExclude(message) then return end
    self:HandleChatMessage(message)
end

function StefansLootTracker:CHAT_MSG_PARTY_LEADER(event, arg1, arg2)
    self:debugPrint("CHAT_MSG_PARTY_LEADER event received")
    self:debugPrint("arg1: " .. tostring(arg1))
    self:debugPrint("arg2: " .. tostring(arg2))

    message = tostring(arg2) .. ": " .. tostring(arg1)

    if not self.db.profile.enabled then return end
    if self:matchExclude(message) then return end
    self:HandleChatMessage(message)
end

function StefansLootTracker:CHAT_MSG_RAID(event, arg1, arg2)
    self:debugPrint("CHAT_MSG_RAID event received")
    self:debugPrint("arg1: " .. tostring(arg1))
    self:debugPrint("arg2: " .. tostring(arg2))

    message = tostring(arg2) .. ": " .. tostring(arg1)

    if not self.db.profile.enabled then return end
    if self:matchExclude(message) then return end
    self:HandleChatMessage(message)
end

function StefansLootTracker:CHAT_MSG_RAID_LEADER(event, arg1, arg2)
    self:debugPrint("CHAT_MSG_RAID_LEADER event received")
    self:debugPrint("arg1: " .. tostring(arg1))
    self:debugPrint("arg2: " .. tostring(arg2))

    message = tostring(arg2) .. ": " .. tostring(arg1)

    if not self.db.profile.enabled then return end
    if self:matchExclude(message) then return end
    self:HandleChatMessage(message)
end

function StefansLootTracker:CHAT_MSG_SYSTEM(event, arg1)
    self:debugPrint("CHAT_MSG_SYSTEM event received")
    self:debugPrint("arg1: " .. tostring(arg1))

    if not self.db.profile.enabled then return end
    if self:matchExclude(arg1) then return end
    self:HandleChatRollMessage(arg1)
end

function StefansLootTracker:CHAT_MSG_LOOT(event, arg1)
    self:debugPrint("CHAT_MSG_LOOT event received")
    self:debugPrint("arg1: " .. tostring(arg1))

    if not self.db.profile.enabled then return end
    if self:matchExclude(arg1) then return end
    if self:matchLootMessage(arg1) then self:HandleLootMessage(arg1) end
    if self:matchRollMessage(arg1) then self:HandleRollMessage(arg1) end
end

function StefansLootTracker:ChatCommand(input)
    if not input or input:trim() == "" then
        print("Stefans Loot Tracker commands:")
        print("/slt settings  - Open Settings")
        print("/slt history   - Open History Window")
        print("/slt lootclear - Clear Loot History")
        print("/slt rollclear - Clear Roll History")
        print("/slt chatclear - Clear Chat History")
    elseif input:trim() == "settings" then
        self:OpenOptions()
    elseif input:trim() == "history" then
        self:ToggleLootHistoryWindow()
    elseif input:trim() == "lootclear" then
        self:ClearLootHistory()
    elseif input:trim() == "rollclear" then
        self:ClearRollHistory()
    elseif input:trim() == "chatclear" then
        self:ClearChatHistory()
    else
        LibStub("AceConfigCmd-3.0"):HandleCommand("slt", "StefansLootTracker", input)
    end
end

function StefansLootTracker:IsEnabled(info)
    return self.db.profile.enabled
end

function StefansLootTracker:ToggleEnabled(info, value)
    self.db.profile.enabled = value
end

function StefansLootTracker:IsDebug(info)
    return self.db.profile.qDebug
end

function StefansLootTracker:ToggleDebug(info, value)
    self.db.profile.qDebug = value
end

function StefansLootTracker:IsAlertChat(info)
    return self.db.profile.alertChat
end

function StefansLootTracker:ToggleAlertChat(info, value)
    self.db.profile.alertChat = value
end

function StefansLootTracker:SetTerms(info, newValue)
    self:debugPrint("SetTerms "..newValue)
    self.db.profile.terms = newValue
end

function StefansLootTracker:ShowMinimapIcon()
    DBIcon:Show("StefansLootTracker")
    self.db.profile.minimap.hide = false
end

function StefansLootTracker:HideMinimapIcon()
    DBIcon:Hide("StefansLootTracker")
    self.db.profile.minimap.hide = true
end

function StefansLootTracker:GetRarityFilter(info)
    return self.db.profile.rarityFilter
end

function StefansLootTracker:SetRarityFilter(info, value)
    self.db.profile.rarityFilter = value
end

function StefansLootTracker:OpenOptions()
    InterfaceOptionsFrame_OpenToCategory(self.optionsFrame)
    InterfaceOptionsFrame_OpenToCategory(self.optionsFrame) -- Call twice to workaround a Blizzard UI bug
end

function StefansLootTracker:RefreshConfig()
    self:Print("Profile changed. Refreshing configuration.")
    
    -- Re-apply settings from the new profile
    self:ApplySettings()
    
    -- Refresh the loot history window if it's open
    if self.isLootHistoryWindowOpen then
        self:UpdateLootHistoryWindow()
    end

    -- Refresh the loot history window if it's open
    if self.isRollHistoryWindowOpen then
        self:UpdateRollHistoryWindow()
    end

    -- Refresh the chat history window if it's open
    if self.isChatHistoryWindowOpen then
        self:UpdateChatHistoryWindow()
    end
    
    -- Update minimap icon visibility
    if self.db.profile.minimap.hide then
        self:HideMinimapIcon()
    else
        self:ShowMinimapIcon()
    end
    
    -- Re-register events (in case they were unregistered)
    self:RegisterEvent("CHAT_MSG_LOOT")
    self:RegisterEvent("CHAT_MSG_PARTY")
    self:RegisterEvent("CHAT_MSG_PARTY_LEADER")
    self:RegisterEvent("CHAT_MSG_RAID")
    self:RegisterEvent("CHAT_MSG_RAID_LEADER")
    self:RegisterEvent("CHAT_MSG_SYSTEM")
    self:RegisterEvent("CHAT_MSG_LOOT")
    
    -- Refresh any open config panels
    LibStub("AceConfigRegistry-3.0"):NotifyChange("StefansLootTracker")

    self:ApplySettings()
end

function StefansLootTracker:ApplySettings()
    -- Apply settings from the current profile
    if self.db.profile.enabled then
        self:OnEnable()
    else
        self:OnDisable()
    end
    
    -- Apply other settings
    self.qDebug = self.db.profile.qDebug
    self.alertChat = self.db.profile.alertChat
    self.rarityFilter = self.db.profile.rarityFilter
    
    -- Apply Loot History window position and size if the window exists
    if self.historyFrame then
        local pos = self.db.profile.historyWindowPosition
        local size = self.db.profile.historyWindowSize
        self.historyFrame:ClearAllPoints()
        self.historyFrame:SetPoint(pos.point, UIParent, pos.relativePoint, pos.x, pos.y)
        self.historyFrame:SetSize(size.width, size.height)
    end
end

function StefansLootTracker:matchExclude(itemName)
    local excludeItems = self.db.profile.excludeItems
    if excludeItems and excludeItems ~= "" then
        local excludedItemsList = {strsplit(",", excludeItems)}
        if #excludedItemsList == 0 then
            return false  -- List is empty, so no items to exclude.
        end
        for _, excludedItem in ipairs(excludedItemsList) do
            local trimmedExcludedItem = strtrim(excludedItem):lower()
            if itemName:lower():match(trimmedExcludedItem) then
                return true  -- Item matches something in the exclusion list.
            end
        end
    end
    return false  -- No match found or list is empty.
end

function StefansLootTracker:getRarityFromHex(hex)
    local rarityMap = {
        ["ff9d9d9d"] = 0,
        ["ffffffff"] = 1,
        ["ff1eff00"] = 2,
        ["ff0070dd"] = 3,
        ["ffa335ee"] = 4,
        ["ffff8000"] = 5
    }
    return rarityMap[hex] or 0  -- Default to 0 (Poor) if hex is not found
end