local addonName,BM=...

BM.queueActive=false
BM.queueMode=nil
BM.queueIndex=nil
BM.queueList=nil
BM.queueProcessedCount=0
BM.queueSkippedCount=0

local MONEY_PROCESS_DELAY = 0.12
local ITEM_PROCESS_DELAY = 0.14
local DELETE_PROCESS_DELAY = 0.16
local REFRESH_DELAY = 0.2
local MAX_MAIL_ATTACHMENTS = ATTACHMENTS_MAX_RECEIVE or 16

local function RequestInboxRefresh(delay)
    if CheckInbox then
        CheckInbox()
    end

    C_Timer.After(delay or REFRESH_DELAY, function()
        if CheckInbox then
            CheckInbox()
        end
        if BM.RefreshInbox then
            BM:RefreshInbox()
        end
    end)
end

local function ResetActionButtons()
    BM.queueActive=false
    BM.queueMode=nil
    BM.queueIndex=nil
    BM.queueList=nil
    BM.queueProcessedCount=0
    BM.queueSkippedCount=0

    if BM.TakeGoldButton and BM.TakeGoldButton.label then
        BM.TakeGoldButton:Enable()
        BM.TakeGoldButton.label:SetText(BM:L("take_gold"))
    end

    if BM.TakeAllButton and BM.TakeAllButton.label then
        BM.TakeAllButton:Enable()
        BM.TakeAllButton.label:SetText(BM:L("take_all"))
    end

    if BM.TakeSelectedButton and BM.TakeSelectedButton.label then
        BM.TakeSelectedButton:Enable()
        BM.TakeSelectedButton.label:SetText(BM:L("take_selected"))
    end

    if BM.DeleteButton and BM.DeleteButton.label then
        BM.DeleteButton:Enable()
    end

    if BM.UpdateActionTexts then
        BM:UpdateActionTexts()
    end
end

local function FinishQueue(statusText, color)
    local finishedMode = BM.queueMode

    BM.queueActive = false
    BM.queueMode = nil
    BM.queueIndex = nil
    BM.queueList = nil

    if finishedMode == "delete" then
        BM.selectedMailIndex = nil
        if BM.ClearDeleteSelection then
            BM:ClearDeleteSelection(true)
        end
    end

    if statusText and BM.SetStatus then
        BM:SetStatus(statusText, unpack(color or BM.Theme.mutetext))
    end

    ResetActionButtons()
    RequestInboxRefresh(REFRESH_DELAY)
end

local function ContinueQueue(delay)
    C_Timer.After(delay or 0.05, function()
        if CheckInbox then
            CheckInbox()
        end
        BM:ProcessNextMail()
    end)
end

local function GetMailCollectState(index)
    if not index or index < 1 then
        return nil
    end

    local _, _, _, _, money, codAmount, _, hasItem = GetInboxHeaderInfo(index)
    return {
        money = money or 0,
        codAmount = codAmount or 0,
        hasItem = hasItem or 0,
    }
end

local function IsMailDeletable(state)
    return state
        and (state.codAmount or 0) <= 0
        and (state.money or 0) <= 0
        and (state.hasItem or 0) <= 0
end

local function FindNextCollectableMail(goldOnly)
    local visible, totalItems = GetInboxNumItems()
    local total = math.max(visible or 0, totalItems or 0)

    for index = total, 1, -1 do
        local state = GetMailCollectState(index)
        if state and state.codAmount <= 0 then
            if state.money > 0 then
                return index, state
            end
            if not goldOnly and state.hasItem > 0 then
                return index, state
            end
        end
    end
end

local function BuildSelectionQueue()
    local list = BM.GetDeleteSelectionIndices and BM:GetDeleteSelectionIndices() or {}
    if #list == 0 and BM.selectedMailIndex then
        list = { BM.selectedMailIndex }
    end
    table.sort(list, function(a, b)
        return a > b
    end)
    return list
end

local function BuildDeleteQueue()
    return BuildSelectionQueue()
end

local function StartQueue(mode, index, list)
    if BM.queueActive then
        return false
    end

    BM.queueActive = true
    BM.queueMode = mode
    BM.queueIndex = index
    BM.queueList = list
    BM.queueProcessedCount = 0
    BM.queueSkippedCount = 0
    return true
end

function BM:ProcessNextMail()
    if not BM.queueActive then
        return
    end

    local mode = BM.queueMode
    local state
    local index = BM.queueIndex

    if mode == "delete" then
        local queue = BM.queueList or {}
        if #queue == 0 then
            if BM.queueProcessedCount > 0 and BM.queueSkippedCount > 0 then
                FinishQueue(BM:L("delete_partial", BM.queueProcessedCount), BM.Theme.mutetext)
            elseif BM.queueProcessedCount > 1 then
                FinishQueue(BM:L("delete_done_multi", BM.queueProcessedCount), BM.Theme.success)
            elseif BM.queueProcessedCount == 1 then
                FinishQueue(BM:L("delete_done"), BM.Theme.success)
            else
                FinishQueue(BM:L("delete_blocked"), BM.Theme.mutetext)
            end
            return
        end

        index = table.remove(queue, 1)
        BM.queueList = queue
        state = GetMailCollectState(index)

        if not state then
            ContinueQueue(0.05)
            return
        end

        if not IsMailDeletable(state) then
            BM.queueSkippedCount = BM.queueSkippedCount + 1
            ContinueQueue(0.05)
            return
        end

        DeleteInboxItem(index)
        BM.queueProcessedCount = BM.queueProcessedCount + 1
        ContinueQueue(DELETE_PROCESS_DELAY)
        return
    elseif mode == "selected_group" then
        local queue = BM.queueList or {}
        if #queue == 0 then
            FinishQueue(BM:L("done"), BM.Theme.success)
            return
        end

        index = table.remove(queue, 1)
        BM.queueList = queue
        state = GetMailCollectState(index)

        if not state then
            ContinueQueue(0.05)
            return
        end
    elseif mode == "selected" then
        state = GetMailCollectState(index)
        if not state then
            BM.selectedMailIndex = nil
            FinishQueue(BM:L("done"), BM.Theme.success)
            return
        end
    else
        index, state = FindNextCollectableMail(mode == "gold")
        if not index then
            if mode == "gold" then
                FinishQueue(BM:L("take_gold"), BM.Theme.success)
            else
                FinishQueue(BM:L("done"), BM.Theme.success)
            end
            return
        end
    end

    if state.codAmount and state.codAmount > 0 then
        if mode == "selected" then
            FinishQueue(BM:L("selected_mail_empty"), BM.Theme.mutetext)
        else
            BM.queueSkippedCount = BM.queueSkippedCount + 1
            ContinueQueue(0.05)
        end
        return
    end

    if state.money and state.money > 0 then
        TakeInboxMoney(index)
        ContinueQueue(MONEY_PROCESS_DELAY)
        return
    end

    if mode ~= "gold" and state.hasItem and state.hasItem > 0 then
        for attachmentIndex = 1, MAX_MAIL_ATTACHMENTS do
            local itemName = GetInboxItem(index, attachmentIndex)
            if itemName then
                TakeInboxItem(index, attachmentIndex)
                ContinueQueue(ITEM_PROCESS_DELAY)
                return
            end
        end
    end

    if mode == "selected" then
        BM.selectedMailIndex = nil
        FinishQueue(BM:L("done"), BM.Theme.success)
    else
        ContinueQueue(0.05)
    end
end

function BM:TakeSelectedMail()
    if BM.queueActive then
        return
    end

    local selectedQueue = BuildSelectionQueue()
    if #selectedQueue == 0 then
        BM:SetStatus(BM:L("selected_mail_empty"), unpack(BM.Theme.mutetext))
        return
    end

    if #selectedQueue == 1 and BM.selectedMailIndex and selectedQueue[1] == BM.selectedMailIndex then
        BM:TakeSingleMail(BM.selectedMailIndex)
        return
    end

    if not StartQueue("selected_group", nil, selectedQueue) then
        return
    end

    if BM.TakeSelectedButton then
        BM.TakeSelectedButton:Disable()
        if BM.TakeSelectedButton.label then
            BM.TakeSelectedButton.label:SetText(BM:L("collecting"))
        end
    end

    if BM.TakeGoldButton then BM.TakeGoldButton:Disable() end
    if BM.TakeAllButton then BM.TakeAllButton:Disable() end
    if BM.DeleteButton then BM.DeleteButton:Disable() end

    BM:ProcessNextMail()
end

function BM:TakeSingleMail(index)
    if BM.queueActive or not index then
        return
    end

    local state = GetMailCollectState(index)
    if not state or state.codAmount > 0 or not ((state.money and state.money > 0) or (state.hasItem and state.hasItem > 0)) then
        BM:SetStatus(BM:L("selected_mail_empty"), unpack(BM.Theme.mutetext))
        return
    end

    if not StartQueue("selected", index) then
        return
    end

    if BM.TakeSelectedButton then
        BM.TakeSelectedButton:Disable()
        if BM.TakeSelectedButton.label then
            BM.TakeSelectedButton.label:SetText(BM:L("collecting"))
        end
    end

    if BM.TakeGoldButton then
        BM.TakeGoldButton:Disable()
    end

    if BM.TakeAllButton then
        BM.TakeAllButton:Disable()
    end

    if BM.DeleteButton then
        BM.DeleteButton:Disable()
    end

    BM:ProcessNextMail()
end

function BM:DeleteSelectedMail()
    if BM.queueActive then
        return
    end

    local deleteQueue = BuildDeleteQueue()
    if #deleteQueue == 0 then
        if BM.SetStatus then
            BM:SetStatus(BM:L("delete_selection_empty"), unpack(BM.Theme.mutetext))
        end
        return
    end

    if not StartQueue("delete", nil, deleteQueue) then
        return
    end

    if BM.DeleteButton then
        BM.DeleteButton:Disable()
        if BM.DeleteButton.label then
            BM.DeleteButton.label:SetText(BM:L("deleting"))
        end
    end

    if BM.TakeGoldButton then BM.TakeGoldButton:Disable() end
    if BM.TakeAllButton then BM.TakeAllButton:Disable() end
    if BM.TakeSelectedButton then BM.TakeSelectedButton:Disable() end

    BM:ProcessNextMail()
end

function BM:CreateTakeAll()
    local actionBar = CreateFrame("Frame", nil, BM.MainFrame)
    actionBar:SetAllPoints(BM.MainFrame)

    local buttonAnchor = CreateFrame("Frame", nil, actionBar)
    buttonAnchor:SetPoint("BOTTOM", BM.MainFrame, "BOTTOM", 126, 58)
    buttonAnchor:SetSize(820, 32)

    local selectedBtn = BM:CreateFlatActionButton(buttonAnchor, 170, 32, "")
    selectedBtn:SetPoint("LEFT", buttonAnchor, "LEFT", 0, 0)
    selectedBtn:SetScript("OnClick", function()
        if BM.TakeSelectedMail then
            BM:TakeSelectedMail()
        elseif BM.selectedMailIndex then
            BM:TakeSingleMail(BM.selectedMailIndex)
        elseif BM.SetStatus then
            BM:SetStatus(BM:L("selected_mail_empty"), unpack(BM.Theme.mutetext))
        end
    end)

    local goldBtn = BM:CreateFlatActionButton(buttonAnchor, 170, 32, "")
    goldBtn:SetPoint("LEFT", selectedBtn, "RIGHT", 12, 0)
    goldBtn:SetScript("OnClick", function()
        if BM.queueActive then return end
        if not StartQueue("gold") then return end
        goldBtn:Disable()
        if goldBtn.label then goldBtn.label:SetText(BM:L("collecting")) end
        if BM.TakeAllButton then BM.TakeAllButton:Disable() end
        if BM.TakeSelectedButton then BM.TakeSelectedButton:Disable() end
        if BM.DeleteButton then BM.DeleteButton:Disable() end
        BM:ProcessNextMail()
    end)

    local btn=BM:CreateFlatActionButton(buttonAnchor, 170, 32, "")
    btn:SetPoint("LEFT", goldBtn, "RIGHT", 12, 0)
    btn:SetScript("OnClick",function()
        if BM.queueActive then return end
        if not StartQueue("all") then return end
        btn:Disable()
        if btn.label then btn.label:SetText(BM:L("collecting")) end
        if BM.TakeGoldButton then BM.TakeGoldButton:Disable() end
        if BM.TakeSelectedButton then BM.TakeSelectedButton:Disable() end
        if BM.DeleteButton then BM.DeleteButton:Disable() end
        BM:ProcessNextMail()
    end)

    local deleteBtn = BM:CreateFlatActionButton(buttonAnchor, 170, 32, "")
    deleteBtn:SetPoint("LEFT", btn, "RIGHT", 12, 0)
    deleteBtn:SetScript("OnClick", function()
        BM:DeleteSelectedMail()
    end)

    local refreshBtn = BM:CreateFlatActionButton(buttonAnchor, 132, 32, "")
    refreshBtn:SetPoint("LEFT", deleteBtn, "RIGHT", 12, 0)
    refreshBtn:SetScript("OnClick", function()
        CheckInbox()
        BM:SetStatus(BM:L("refreshing"), 0.13, 0.72, 1)
        C_Timer.After(.3, function()
            BM:RefreshInbox()
        end)
    end)

    BM.TakeAllButton = btn
    BM.TakeGoldButton = goldBtn
    BM.TakeSelectedButton = selectedBtn
    BM.DeleteButton = deleteBtn
    BM.RefreshButton = refreshBtn
    BM.ActionButtonAnchor = buttonAnchor
    BM.ActionBar = actionBar
    BM:UpdateActionTexts()
end

function BM:UpdateActionTexts()
    local deleteCount = BM.GetDeleteSelectionCount and BM:GetDeleteSelectionCount() or 0
    local deleteText = deleteCount > 1 and BM:L("delete_selected") or BM:L("delete")

    if BM.TakeAllButton and BM.TakeAllButton.label and not BM.queueActive then BM.TakeAllButton.label:SetText(BM:L("take_all")) end
    if BM.TakeGoldButton and BM.TakeGoldButton.label and not BM.queueActive then BM.TakeGoldButton.label:SetText(BM:L("take_gold")) end
    if BM.TakeSelectedButton and BM.TakeSelectedButton.label and not BM.queueActive then BM.TakeSelectedButton.label:SetText(BM:L("take_selected")) end
    if BM.DeleteButton and BM.DeleteButton.label and not BM.queueActive then BM.DeleteButton.label:SetText(deleteText) end
    if BM.RefreshButton and BM.RefreshButton.label then BM.RefreshButton.label:SetText(BM:L("refresh")) end
    if BM.TakeSelectedButton then
        if BM.queueActive then
            BM.TakeSelectedButton:Disable()
        else
            BM.TakeSelectedButton:Enable()
        end
    end
    if BM.DeleteButton then
        if BM.queueActive then
            BM.DeleteButton:Disable()
        else
            BM.DeleteButton:Enable()
        end
    end
end

function BM:ProcessMail()
    if BM.queueActive then
        BM:ProcessNextMail()
    end
end

function BM:ProcessGoldOnly()
    if BM.queueActive then
        BM:ProcessNextMail()
    end
end

