-- Loot History

StefansLootTracker.loadedLootStartIndex = 1
StefansLootTracker.loadedLootEndIndex = StefansLootTracker.itemsLootPerLoad or 30
StefansLootTracker.itemsLootPerLoad = 30

StefansLootTracker.frameLootPool = {}
StefansLootTracker.visibleLootFrames = {}
StefansLootTracker.frameLootHeight = 15

function StefansLootTracker:matchLootMessage(msg)
    local lootPatterns = {
        "You receive loot: .+",
        "You receive item: .+",
        "You receive: .+",
        "You create item: .+",
        "You create: .+",
        "(.+) receives loot: .+",
        "(.+) receives item: .+",
        "(.+) receives: .+",
        "(.+) creates item: .+",
        "(.+) creates: .+"
    }

    for _, pattern in ipairs(lootPatterns) do
        if msg:match(pattern) then
            return true
        end
    end
    return false
end

function StefansLootTracker:HandleLootMessage(lootMessage)
    -- Debug: Log the received loot message
    if self.db.profile.qDebug then
        print("Debug: Received loot string: " .. lootMessage)
    end

    -- Remove the specific pattern |HlootHistory:<digit>|h[Loot]|h:
    lootMessage = lootMessage:gsub("|HlootHistory:%d+|h%[Loot%]|h: ", "")

    -- Replace "You" with the character's name
    local playerName = UnitName("player")
    lootMessage = lootMessage:gsub("You", playerName)

    -- Parse the loot message
    local rarity = self:getRarity(lootMessage)

    -- Debug: Log the parsed details
    if self.db.profile.qDebug then
        print("Debug: Parsed rarity: " .. (rarity or "Unknown"))
    end

    -- Check if the item meets the rarity filter
    if rarity < self.db.profile.rarityFilter then
        if self.db.profile.qDebug then 
            self:Print("LOOT DOESN'T MEET RARITY FILTER")
        end
        return
    end

    -- Get the current timestamp
    local timestamp = date("%Y-%m-%d %H:%M:%S")

    -- Update the data structure
    if not self.db.profile.loothist then
        self.db.profile.loothist = {}
    end

    -- Insert a new loot event with its timestamp and modified message
    table.insert(self.db.profile.loothist, {
        message = lootMessage,
        timestamp = timestamp
    })

    -- Update the window only if it's open
    self:UpdateLootHistoryIfOpen()
end

function StefansLootTracker:ClearLootHistory()
    self.db.profile.result = {} -- Old Loot History Database
    self.db.profile.loothist = {} -- Loot History Database
    self:Print("Loot History has been cleared.")
    if self.lootHistoryFrame and self.lootHistoryFrame:IsShown() then
        self:UpdateLootHistoryWindow()  -- Update the loot history window if it's open
    end
end

local searchLootDebounceTimer
function StefansLootTracker:LootDebouncedSearch(searchLootTerm)
    if searchLootDebounceTimer then
        searchLootDebounceTimer:Cancel()
    end
    searchLootDebounceTimer = C_Timer.After(0.5, function()
        self:UpdateLootHistoryWindow(searchLootTerm)
    end)
end

local loadLootMoreTimer
function StefansLootTracker:DebouncedLootLoadMoreResults()
    if loadLootMoreTimer then
        loadLootMoreTimer:Cancel()
    end
    loadLootMoreTimer = C_Timer.NewTimer(0.2, function()
        self:LootLoadMoreResults()
    end)
end

function StefansLootTracker:CreateLootHistoryWindow()
    -- Check if the frame already exists to avoid creating duplicates
    if self.lootHistoryFrame then
        self.lootHistoryFrame:Show()
        return
    end

    local f = CreateFrame("Frame", "StefansLootTrackerLootHistoryFrame", UIParent, "BackdropTemplate")
    local pos = self.db.profile.lootHistorywindowPosition
    local size = self.db.profile.lootHistorywindowSize
    f:SetSize(size.width, size.height)
    f:SetPoint(pos.point, UIParent, pos.relativePoint, pos.x, pos.y)
    f:SetMovable(true)
    f:SetResizable(true)
    f:SetResizeBounds(300, 200) -- Set minimum size
    f:EnableMouse(true)
    f:RegisterForDrag("LeftButton")
    f:SetScript("OnDragStart", f.StartMoving)
    f:SetScript("OnDragStop", f.StopMovingOrSizing)
    f:SetHyperlinksEnabled(true)
    f:SetScript("OnHyperlinkClick", ChatFrame_OnHyperlinkShow)
    f:Hide()

    f:SetBackdrop({
        bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
        edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
        tile = true,
        tileSize = 32,
        edgeSize = 32,
        insets = { left = 8, right = 8, top = 8, bottom = 8 }
    })

    -- Create the title frame
    local titleFrame = CreateFrame("Frame", nil, f)
    titleFrame:SetSize(f:GetWidth(), 30)
    titleFrame:SetPoint("TOP", f, "TOP", 0, 10)

    local titleText = titleFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge")
    titleText:SetPoint("CENTER", titleFrame, "CENTER")
    titleText:SetText("Loot History")

    -- Create the close button
    local closeButton = CreateFrame("Button", nil, f, "UIPanelCloseButton")
    closeButton:SetPoint("TOPRIGHT", f, "TOPRIGHT", -5, -5)
    closeButton:SetScript("OnClick", function()
        f:Hide()
        StefansLootTracker.isLootHistoryWindowOpen = false
        StefansLootTracker:ResetLootLazyLoading()
    end)

    -- Create the refresh button
    local refreshButton = self:CreateRefreshButton(f)
    refreshButton:SetScript("OnClick", function()
        self:UpdateLootHistoryWindow()
    end)

    -- Create search box
    local searchBox = CreateFrame("EditBox", nil, f, "InputBoxTemplate")
    searchBox:SetPoint("TOPLEFT", f, "TOPLEFT", 15, -50)
    searchBox:SetPoint("RIGHT", f, "RIGHT", -15, 0)
    searchBox:SetHeight(20)
    searchBox:SetFontObject("GameFontNormal")
    searchBox:SetAutoFocus(false)
    searchBox:SetScript("OnEscapePressed", function(self) self:ClearFocus() end)
    searchBox:SetTextInsets(22, 10, 2, 2)

    local bg = searchBox:CreateTexture(nil, "BACKGROUND")
    bg:SetAllPoints()
    bg:SetColorTexture(0, 0, 0, 0.1)

    local searchIcon = f:CreateTexture(nil, "ARTWORK")
    searchIcon:SetTexture("Interface\\Common\\UI-Searchbox-Icon")
    searchIcon:SetSize(14, 14)
    searchIcon:SetPoint("LEFT", searchBox, "LEFT", 6, 0)

    searchBox.placeholderText = searchBox:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
    searchBox.placeholderText:SetPoint("LEFT", searchIcon, "RIGHT", 10, 0)
    searchBox.placeholderText:SetText("Search")
    searchBox.placeholderText:SetTextColor(0.6, 0.6, 0.6)

    searchBox:SetScript("OnTextChanged", function(self)
        local text = self:GetText()
        if text == "" then
            self.placeholderText:Show()
        else
            self.placeholderText:Hide()
        end
        StefansLootTracker:LootDebouncedSearch(text)
    end)

    searchBox:SetScript("OnEditFocusGained", function(self)
        self.placeholderText:Hide()
    end)

    searchBox:SetScript("OnEditFocusLost", function(self)
        if self:GetText() == "" then
            self.placeholderText:Show()
        end
    end)

    f.searchBox = searchBox

    -- Create the scroll frame
    local scrollFrame = CreateFrame("ScrollFrame", nil, f, "UIPanelScrollFrameTemplate")
    scrollFrame:SetPoint("TOPLEFT", f, "TOPLEFT", 10, -80)
    scrollFrame:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", -30, 10)
    scrollFrame:SetScript("OnVerticalScroll", function(self, offset)
        self.ScrollBar:SetValue(offset)
        StefansLootTracker:UpdateLootHistoryDisplay()
    end)

    local scrollChild = CreateFrame("Frame", nil, scrollFrame)
    scrollChild:SetWidth(scrollFrame:GetWidth() - 16)  -- Subtract scrollbar width
    scrollFrame:SetScrollChild(scrollChild)
    f.scrollFrame = scrollFrame
    f.scrollChild = scrollChild

    f.noResultsText = f:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
    f.noResultsText:SetPoint("CENTER", f.scrollChild, "CENTER")
    f.noResultsText:SetText("No results found")
    f.noResultsText:Hide()

    f.UpdateNoResults = function(self, noResults)
        if noResults then
            self.noResultsText:Show()
        else
            self.noResultsText:Hide()
        end
    end

    -- Create resize handle
    local resizeHandle = CreateFrame("Button", nil, f)
    resizeHandle:SetPoint("BOTTOMRIGHT")
    resizeHandle:SetSize(16, 16)
    resizeHandle:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Up")
    resizeHandle:SetHighlightTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Highlight")
    resizeHandle:SetPushedTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Down")
    
    resizeHandle:SetScript("OnMouseDown", function(self, button)
        f:StartSizing("BOTTOMRIGHT")
    end)
    
    resizeHandle:SetScript("OnMouseUp", function(self, button)
        f:StopMovingOrSizing()
        StefansLootTracker:UpdateLootHistoryLayout()
        -- Save the new size
        StefansLootTracker.db.profile.lootHistorywindowSize = { width = f:GetWidth(), height = f:GetHeight() }
    end)

    self.lootHistoryFrame = f

    self.frameLootPool = {}
    self.visibleLootFrames = {}

    self:UpdateLootHistoryWindow()
end

function StefansLootTracker:UpdateLootHistoryLayout()
    local f = self.lootHistoryFrame
    if not f then return end

    -- Update search box width
    f.searchBox:SetWidth(f:GetWidth() - 30)

    -- Update scroll frame size
    f.scrollFrame:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", -30, 10)

    -- Update scroll child width
    f.scrollChild:SetWidth(f.scrollFrame:GetWidth() - 16)  -- Subtract scrollbar width

    -- Update visible frames width
    for _, frame in ipairs(self.visibleLootFrames) do
        frame:SetWidth(f.scrollChild:GetWidth() - 10)
        frame.messageButton:SetPoint("RIGHT", frame, "RIGHT", 0, 0)
    end

    -- Update the display
    self:UpdateLootHistoryDisplay()
end

function StefansLootTracker:UpdateLootHistoryWindow(searchLootTerm)
    local frame = self.lootHistoryFrame
    if not frame then return end

    searchLootTerm = searchLootTerm or ""

    if searchLootTerm ~= self.lastsearchLootTerm then
        self:ResetLootLazyLoading()
        self.lastsearchLootTerm = searchLootTerm
    end

    -- Initialize FilteredLootIndices
    self.FilteredLootIndices = {}
    for i = #self.db.profile.loothist, 1, -1 do
        local entry = self.db.profile.loothist[i]
        if searchLootTerm == "" or entry.message:lower():find(searchLootTerm:lower(), 1, true) then
            table.insert(self.FilteredLootIndices, i)
        end
    end

    local totalFilteredLootItems = #self.FilteredLootIndices
    local displayedHeight = totalFilteredLootItems * self.frameLootHeight
    frame.scrollChild:SetHeight(displayedHeight)

    self:UpdateLootHistoryLayout()
    self:UpdateLootHistoryDisplay()

    frame:UpdateNoResults(totalFilteredLootItems == 0)
end

function StefansLootTracker:UpdateLootHistoryDisplay()
    local frame = self.lootHistoryFrame
    local scrollFrame = frame.scrollFrame
    local scrollOffset = scrollFrame:GetVerticalScroll()
    local visibleHeight = scrollFrame:GetHeight()
    
    if not self.FilteredLootIndices then
        self:UpdateLootHistoryWindow()
    end

    local totalItems = #self.FilteredLootIndices
    local itemsPerPage = math.floor(visibleHeight / self.frameLootHeight)
    
    local startIndex = math.floor(scrollOffset / self.frameLootHeight) + 1
    local endIndex = math.min(startIndex + itemsPerPage - 1, totalItems)

    for i = 1, itemsPerPage do
        local dataIndex = startIndex + i - 1
        local entryFrame = self.visibleLootFrames[i] or self:CreateLootEntryFrame(frame.scrollChild)
        
        if dataIndex <= totalItems then
            local entry = self.db.profile.loothist[self.FilteredLootIndices[dataIndex]]
            
            entryFrame:SetPoint("TOPLEFT", frame.scrollChild, "TOPLEFT", 5, -((dataIndex-1) * self.frameLootHeight))
            entryFrame:SetPoint("RIGHT", frame.scrollChild, "RIGHT", -5, 0)
            entryFrame:SetHeight(self.frameLootHeight)

            entryFrame.timestampText:SetText(string.format("[%s]", entry.timestamp))
            entryFrame.messageButton.text:SetText(entry.message)

            entryFrame:Show()
            self.visibleLootFrames[i] = entryFrame
        else
            entryFrame:Hide()
        end
    end

    -- Hide any extra frames
    for i = itemsPerPage + 1, #self.visibleLootFrames do
        self.visibleLootFrames[i]:Hide()
    end

    -- Update scroll child height
    local newHeight = totalItems * self.frameLootHeight
    if frame.scrollChild:GetHeight() ~= newHeight then
        frame.scrollChild:SetHeight(newHeight)
        scrollFrame.ScrollBar:SetMinMaxValues(0, max(newHeight - scrollFrame:GetHeight(), 0))
    end
end

function StefansLootTracker:CreateLootEntryFrame(parent)
    local frame = CreateFrame("Frame", nil, parent)
    frame:SetSize(parent:GetWidth() - 10, self.frameLootHeight)

    frame.timestampText = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    frame.timestampText:SetPoint("LEFT", frame, "LEFT", 0, 0)

    -- Create a Button instead of a FontString for the message
    frame.messageButton = CreateFrame("Button", nil, frame)
    frame.messageButton:SetPoint("LEFT", frame.timestampText, "RIGHT", 5, 0)
    frame.messageButton:SetPoint("RIGHT", frame, "RIGHT", 0, 0)
    frame.messageButton:SetHeight(self.frameLootHeight)
    
    frame.messageButton.text = frame.messageButton:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    frame.messageButton.text:SetAllPoints()
    frame.messageButton.text:SetJustifyH("LEFT")

    -- Enable hyperlinks on the button
    frame.messageButton:SetHyperlinksEnabled(true)
    frame.messageButton:SetScript("OnHyperlinkClick", ChatFrame_OnHyperlinkShow)
    frame.messageButton:SetScript("OnHyperlinkEnter", function(self, link, text)
        GameTooltip:SetOwner(self, "ANCHOR_CURSOR")
        GameTooltip:SetHyperlink(link)
        GameTooltip:Show()
    end)
    frame.messageButton:SetScript("OnHyperlinkLeave", function(self)
        GameTooltip:Hide()
    end)

    return frame
end

function StefansLootTracker:ToggleLootHistoryWindow()
    if not self.lootHistoryFrame then
        self:CreateLootHistoryWindow()
    end

    if self.isLootHistoryWindowOpen then
        self.lootHistoryFrame:Hide()
        self.isLootHistoryWindowOpen = false
        self:ResetLootLazyLoading()
    else
        -- Reset the lazy loading and search box
        if self.lootHistoryFrame.searchBox then
            self.lootHistoryFrame.searchBox:SetText("")
            self.lootHistoryFrame.searchBox.placeholderText:Show()
        end

        self:ResetLootLazyLoading()

        -- Update the layout and window, then show it
        self:UpdateLootHistoryLayout()
        self:UpdateLootHistoryWindow()
        self.lootHistoryFrame:Show()
        self.isLootHistoryWindowOpen = true

        -- Ensure the scroll is at the top
        C_Timer.After(0, function()
            self.lootHistoryFrame.scrollFrame:SetVerticalScroll(0)
            self:UpdateLootHistoryDisplay()
        end)
    end
end

function StefansLootTracker:UpdateLootHistoryIfOpen()
    if self.isLootHistoryWindowOpen then
        self:UpdateLootHistoryWindow()
    end
end

function StefansLootTracker:LootOnScroll()
    local frame = self.lootHistoryFrame
    local scrollFrame = frame.scrollFrame
    local scrollOffset = scrollFrame:GetVerticalScroll()
    local scrollHeight = scrollFrame:GetHeight()
    local childHeight = frame.scrollChild:GetHeight()

    -- Check if we're near the bottom of the scroll frame
    if (scrollOffset + scrollHeight) >= (childHeight - 20) then
        -- Prevent multiple triggers
        if self.loadingLootMore then return end
        self.loadingLootMore = true

        -- Load more results
        self:LootLoadMoreResults()
    end
end

function StefansLootTracker:LootLoadMoreResults()
    if self.loadingLootMore then return end
    self.loadingLootMore = true

    -- Increase the loaded loot range for the next batch
    self.loadedLootStartIndex = math.max(self.loadedLootStartIndex - self.itemsLootPerLoad, 1)

    -- Update the window with the current search term
    self:UpdateLootHistoryWindow(self.lastsearchLootTerm)
    
    self.loadingLootMore = false
end

function StefansLootTracker:ResetLootLazyLoading()
    self.loadedLootStartIndex = 1
    self.loadedLootEndIndex = math.min(self.itemsLootPerLoad, #self.db.profile.loothist)
    self.FilteredLootIndices = nil  -- Reset FilteredLootIndices
    self.lastsearchLootTerm = nil
end
