-------------------------
-- AiB QoL Features
-- Zusammenstellung praktischer Komfort-Funktionen
-------------------------

AiBQOL = AiBQOL or {}
AiBQOL.misc = AiBQOL.misc or {
    fasterLoot          = true,
    suppressLootWarnings = true,
    autoFillDelete      = true,
    autoSlotKeystone    = true,
    ahCurrentExpansion  = false,
    cancelProfBuffs     = false,
}

-------------------------
-- 1. FASTER LOOT
-- Lootet automatisch alle Items sobald ein Loot-Fenster öffnet
-------------------------
local lastLootTime = 0

local function IsLootEnabled()
    return AiBQOL.misc and AiBQOL.misc.fasterLoot
end

local function ShouldAutoLoot()
    local autoLootOn = GetCVarBool("autoLootDefault")
    local modifierHeld = IsModifiedClick("AUTOLOOTTOGGLE")
    if autoLootOn then
        return not modifierHeld
    else
        return modifierHeld
    end
end

local function CollectLoot()
    if not IsLootEnabled() then return end
    if not ShouldAutoLoot() then return end

    local throttle = 0.2
    local now = GetTime()
    if now - lastLootTime < throttle then return end
    lastLootTime = now

    if GetCursorInfo() then return end

    local slotCount = GetNumLootItems()
    for i = 1, slotCount do
        LootSlot(i)
    end
end

local lootFrame = CreateFrame("Frame", "AiBQOL_FasterLoot")
lootFrame:RegisterEvent("PLAYER_LOGIN")
lootFrame:SetScript("OnEvent", function(self, event)
    if event == "PLAYER_LOGIN" then
        if IsLootEnabled() then
            self:RegisterEvent("LOOT_READY")
        end
        self:UnregisterEvent("PLAYER_LOGIN")
        return
    end
    if event == "LOOT_READY" then
        CollectLoot()
    end
end)

-------------------------
-- 2. SUPPRESS LOOT WARNINGS
-- Unterdrückt Loot-Bestätigungs-Dialoge automatisch
-------------------------
local CONFIRMATIONS = {
    CONFIRM_LOOT_ROLL = {
        confirm = "ConfirmLootRoll",
        popup   = "CONFIRM_LOOT_ROLL",
        forwardArgs = true,
    },
    CONFIRM_DISENCHANT_ROLL = {
        confirm = "ConfirmLootRoll",
        popup   = "CONFIRM_LOOT_ROLL",
        forwardArgs = true,
    },
    LOOT_BIND_CONFIRM = {
        confirm     = "ConfirmLootSlot",
        popup       = "LOOT_BIND",
        forwardArgs = true,
        spreadExtra = true,
    },
    MERCHANT_CONFIRM_TRADE_TIMER_REMOVAL = {
        confirm = "SellCursorItem",
    },
    MAIL_LOCK_SEND_ITEMS = {
        confirm     = "RespondMailLockSendItem",
        forwardArgs = true,
        appendTrue  = true,
    },
}

local function IsLootWarningsEnabled()
    return AiBQOL.misc and AiBQOL.misc.suppressLootWarnings
end

local function HandleConfirmation(event, arg1, arg2, ...)
    local entry = CONFIRMATIONS[event]
    if not entry then return end
    local fn = _G[entry.confirm]
    if not fn then return end

    if entry.appendTrue then
        fn(arg1, true)
    elseif entry.forwardArgs then
        fn(arg1, arg2)
    else
        fn()
    end

    if entry.popup then
        if entry.spreadExtra then
            StaticPopup_Hide(entry.popup, ...)
        else
            StaticPopup_Hide(entry.popup)
        end
    end
end

local warningFrame = CreateFrame("Frame", "AiBQOL_LootWarnings")
warningFrame:RegisterEvent("PLAYER_LOGIN")
warningFrame:SetScript("OnEvent", function(self, event, arg1, arg2, ...)
    if event == "PLAYER_LOGIN" then
        if IsLootWarningsEnabled() then
            for evtName in pairs(CONFIRMATIONS) do
                self:RegisterEvent(evtName)
            end
        end
        self:UnregisterEvent("PLAYER_LOGIN")
        return
    end
    HandleConfirmation(event, arg1, arg2, ...)
end)

-------------------------
-- 3. EASY ITEM DESTROY
-- Füllt den Lösch-Dialog automatisch aus
-------------------------
local DELETE_GOOD_ITEM_STR = DELETE_GOOD_ITEM

local function IsDestroyEnabled()
    return AiBQOL.misc and AiBQOL.misc.autoFillDelete
end

local function ResolveItemLinkFromCursor()
    local infoType, id, link = GetCursorInfo()
    if not infoType then return nil end

    if infoType == "battlepet" then
        local name = C_PetJournal and C_PetJournal.GetPetInfoBySpeciesID(id)
        if name and name ~= "" then
            return "|cff0070dd[" .. name .. "]|r"
        end
        return nil
    end

    if infoType == "item" and link then return link end
    return nil
end

local function StripDeleteInstruction(originalText)
    if not originalText then return originalText end
    local deleteGoodStr = DELETE_GOOD_ITEM_STR
    if not deleteGoodStr then return originalText end
    local boundary = string.find(deleteGoodStr, "\n")
    if not boundary then return originalText end
    local instructionBlock = string.sub(deleteGoodStr, boundary)
    local cleanedBlock = string.gsub(instructionBlock, "%%s", "")
    cleanedBlock = strtrim(cleanedBlock)
    if cleanedBlock == "" then return originalText end
    local matchStart = string.find(originalText, cleanedBlock, 1, true)
    if matchStart then
        return strtrim(string.sub(originalText, 1, matchStart - 1))
    end
    return originalText
end

local function OnDeleteHyperlinkEnter(self, linkData, text)
    if not linkData then return end
    local linkType = string.match(linkData, "^(%a+)")
    if linkType == "item" then
        GameTooltip:SetOwner(self, "ANCHOR_CURSOR")
        GameTooltip:SetHyperlink(linkData)
        GameTooltip:Show()
    elseif linkType == "battlepet" and BattlePetToolTip_ShowLink then
        GameTooltip:SetOwner(self, "ANCHOR_CURSOR")
        BattlePetToolTip_ShowLink(linkData)
    end
end

local function OnDeleteHyperlinkLeave(self)
    GameTooltip:Hide()
    if BattlePetTooltip then BattlePetTooltip:Hide() end
end

local DESTROY_DIALOG_NAMES = { "DELETE_ITEM", "DELETE_QUEST_ITEM", "DELETE_GOOD_QUEST_ITEM" }

local function PatchDeleteDialogs()
    for _, name in ipairs(DESTROY_DIALOG_NAMES) do
        local dlg = StaticPopupDialogs[name]
        if dlg then
            dlg.OnHyperlinkEnter = OnDeleteHyperlinkEnter
            dlg.OnHyperlinkLeave = OnDeleteHyperlinkLeave
        end
    end
end

local function HandleDeleteConfirm()
    if not IsDestroyEnabled() then return end

    local popupCount = STATICPOPUP_NUMDIALOGS or 4
    local activePopup, activeEditBox, activeButton

    for i = 1, popupCount do
        local popup = _G["StaticPopup" .. i]
        if popup and popup:IsShown() then
            local editBox = _G["StaticPopup" .. i .. "EditBox"]
            local btn     = _G["StaticPopup" .. i .. "Button1"]
            if editBox and btn then
                activePopup   = popup
                activeEditBox = editBox
                activeButton  = btn
                break
            end
        end
    end

    if not activePopup then return end

    local itemLink = ResolveItemLinkFromCursor()
    local requiresTyping = activeEditBox and activeEditBox:IsShown()

    if activeEditBox then activeEditBox:Hide() end
    if activeButton  then activeButton:Enable() end

    local popupName  = activePopup:GetName()
    local textRegion = popupName and _G[popupName .. "Text"]
    if textRegion and itemLink then
        local currentText = textRegion:GetText() or ""
        local cleanText   = StripDeleteInstruction(currentText)
        if not requiresTyping then
            local extraHeight = itemLink and 32 or 0
            activePopup:SetHeight(activePopup:GetHeight() + extraHeight)
        end
        textRegion:SetText(cleanText .. "\n\n" .. itemLink)
    end
end

local destroyFrame = CreateFrame("Frame", "AiBQOL_EasyItemDestroy")
destroyFrame:RegisterEvent("DELETE_ITEM_CONFIRM")
destroyFrame:RegisterEvent("PLAYER_LOGIN")
destroyFrame:SetScript("OnEvent", function(self, event, arg1)
    if event == "PLAYER_LOGIN" then
        if IsDestroyEnabled() then PatchDeleteDialogs() end
        self:UnregisterEvent("PLAYER_LOGIN")
        return
    end
    if event == "DELETE_ITEM_CONFIRM" then
        HandleDeleteConfirm()
    end
end)

-------------------------
-- 4. AUTO KEYSTONE
-- Setzt den Schlüsselstein automatisch ein
-------------------------
local function TrySlotKeystone()
    local reagentType  = Enum.ItemClass.Reagent
    local keystoneType = Enum.ItemReagentSubclass.Keystone

    for bag = 0, (NUM_BAG_FRAMES or 4) do
        local slots = C_Container.GetContainerNumSlots(bag)
        for slot = 1, slots do
            local itemID = C_Container.GetContainerItemID(bag, slot)
            if itemID then
                local _, _, _, _, _, _, _, _, _, _, _, itemClass, itemSub = C_Item.GetItemInfo(itemID)
                if itemClass == reagentType and itemSub == keystoneType then
                    C_Container.PickupContainerItem(bag, slot)
                    if C_Cursor.GetCursorItem() then
                        C_ChallengeMode.SlotKeystone()
                        return
                    end
                end
            end
        end
    end
end

local keystoneWatcher = CreateFrame("Frame", "AiBQOL_AutoKeystone")
keystoneWatcher:RegisterEvent("ADDON_LOADED")
keystoneWatcher:SetScript("OnEvent", function(self, event, loaded)
    if loaded ~= "Blizzard_ChallengesUI" then return end
    self:UnregisterEvent("ADDON_LOADED")

    local keystoneUI = ChallengesKeystoneFrame
    if not keystoneUI then return end

    keystoneUI:HookScript("OnShow", function()
        local db = AiBQOL.misc
        if not db or not db.autoSlotKeystone then return end
        if C_ChallengeMode.HasSlottedKeystone() then return end
        TrySlotKeystone()
    end)
end)

-------------------------
-- 5. AUCTION HOUSE FILTER
-- Filtert das AH automatisch auf die aktuelle Erweiterung
-------------------------
local ahFrame = CreateFrame("Frame", "AiBQOL_AHFilter")
ahFrame:RegisterEvent("AUCTION_HOUSE_SHOW")
ahFrame:SetScript("OnEvent", function(self, event)
    local db = AiBQOL and AiBQOL.misc
    if not db or not db.ahCurrentExpansion then return end

    C_Timer.After(0, function()
        if AuctionHouseFrame and AuctionHouseFrame.SearchBar then
            local filterBtn = AuctionHouseFrame.SearchBar.FilterButton
            if filterBtn and filterBtn.filters then
                filterBtn.filters[Enum.AuctionHouseFilter.CurrentExpansionOnly] = true
                AuctionHouseFrame.SearchBar:UpdateClearFiltersButton()
            end
        end
    end)
end)

-------------------------
-- 6. CANCEL PROFESSION BUFFS
-- Cancelt automatisch unerwünschte Berufs-Buffs und Kostüme
-------------------------
local CANCEL_SPELL_IDS = {
    [394005] = true,  -- Herbalism:      A Cultivator's Colors
    [394006] = true,  -- Mining:         Rockin' Mining Gear
    [394011] = true,  -- Skinning:       Dressed To Kill
    [394016] = true,  -- Inscription:    Artist's Duds
    [394003] = true,  -- Alchemy:        Spark of Madness
    [388658] = true,  -- Blacksmithing:  Suited For Smithing
    [394008] = true,  -- Enchanting:     A Looker's Charm
    [394007] = true,  -- Engineering:    Ready To Build
    [394015] = true,  -- Jewelcrafting:  An Eye For Shine
    [394001] = true,  -- Leatherworking: Sculpting Leather Finery
    [391312] = true,  -- Tailoring:      Wrapped Up In Weaving
    [391775] = true,  -- Cooking:        What's Cookin', Good Lookin'?
    -- [394009] = true,  -- Fishing: nicht aktiv (cancelt den Angelwurf)
}

local cancelFrame = CreateFrame("Frame", "AiBQOL_CancelBuffs")
cancelFrame:RegisterEvent("PLAYER_LOGIN")
cancelFrame:SetScript("OnEvent", function(self, event, unit)
    if event == "PLAYER_LOGIN" then
        if AiBQOL.misc and AiBQOL.misc.cancelProfBuffs then
            self:RegisterEvent("UNIT_AURA")
        end
        self:UnregisterEvent("PLAYER_LOGIN")
        return
    end

    if event == "UNIT_AURA" then
        if unit ~= "player" then return end
        if not (AiBQOL.misc and AiBQOL.misc.cancelProfBuffs) then return end

        -- In Instanzen/Raids werden Aura-Daten im Kampf gesperrt
        local _, instanceType = IsInInstance()
        if (instanceType == "raid" or instanceType == "party") and UnitAffectingCombat("player") then return end

        for i = 1, 40 do
            local aura = C_UnitAuras.GetAuraDataByIndex("player", i)
            if not aura then break end
            if aura.spellId and CANCEL_SPELL_IDS[aura.spellId] then
                CancelUnitBuff("player", i)
            end
        end
    end
end)

AiB.Config:Log("QoL", "Features geladen")
