local _, ns = ...

local ContainerItems = ns.ContainerItems or {}
ns.ContainerItems = ContainerItems

function ContainerItems:GetButtonIcon(button)
    if not button then
        return nil
    end

    local icon = button.icon or button.Icon or button.IconTexture or button.iconTexture
    if icon then
        return icon
    end

    local name = button.GetName and button:GetName() or nil
    if type(name) == "string" and name ~= "" then
        return _G[name .. "IconTexture"] or _G[name .. "Icon"] or _G[name .. "icon"]
    end

    return nil
end

function ContainerItems:GetButtonBagAndSlot(button)
    if not button or (button.IsForbidden and button:IsForbidden()) then
        return nil, nil
    end

    local name = button.GetName and button:GetName() or nil
    local slotID = nil
    local bagID = nil

    if type(button.GetSlotAndBagID) == "function" then
        local okIDs, resolvedSlotID, resolvedBagID = pcall(button.GetSlotAndBagID, button)
        if okIDs then
            slotID = tonumber(resolvedSlotID)
            bagID = tonumber(resolvedBagID)
        end
    end

    if slotID == nil then
        slotID = button.GetID and tonumber(button:GetID()) or tonumber(button.slot)
    end

    if bagID == nil and type(button.GetBagID) == "function" then
        local okBagID, resolvedBagID = pcall(button.GetBagID, button)
        if okBagID then
            bagID = tonumber(resolvedBagID)
        end
    end

    if bagID == nil then
        bagID = tonumber(button.bagID or button.BagID)
    end

    if bagID == nil and button.GetParent then
        local parent = button:GetParent()
        local guard = 0
        while parent and guard < 4 and bagID == nil do
            if type(parent.GetBagID) == "function" then
                local okParentBagID, resolvedParentBagID = pcall(parent.GetBagID, parent)
                if okParentBagID then
                    bagID = tonumber(resolvedParentBagID)
                end
            end

            if bagID == nil and guard == 0 and type(parent.GetID) == "function" then
                local okParentID, resolvedParentID = pcall(parent.GetID, parent)
                if okParentID then
                    bagID = tonumber(resolvedParentID)
                end
            end

            parent = parent.GetParent and parent:GetParent() or nil
            guard = guard + 1
        end
    end

    if type(name) == "string" and slotID == nil then
        slotID = tonumber(name:match("^ReagentBankFrameItem(%d+)$"))
            or tonumber(name:match("^BankPanelItem(%d+)$"))
            or tonumber(name:match("^BankFrameItem(%d+)$"))
    end

    if bagID == nil and type(name) == "string" then
        if name:match("^ReagentBankFrameItem%d+$") then
            bagID = tonumber(REAGENTBANK_CONTAINER)
        elseif name:match("^BankPanelItem%d+$") or name:match("^BankFrameItem%d+$") then
            bagID = tonumber(BANK_CONTAINER)
        end
    end

    if bagID == nil or slotID == nil or slotID < 1 then
        return nil, nil
    end

    return bagID, slotID
end

function ContainerItems:GetItemLink(bagID, slotID)
    local containerAPI = C_Container
    if containerAPI and type(containerAPI.GetContainerItemLink) == "function" then
        local okLink, itemLink = pcall(containerAPI.GetContainerItemLink, bagID, slotID)
        if okLink then
            return itemLink
        end
    end

    if type(GetContainerItemLink) == "function" then
        local okLink, itemLink = pcall(GetContainerItemLink, bagID, slotID)
        if okLink then
            return itemLink
        end
    end

    return nil
end

function ContainerItems:GetQuality(bagID, slotID, itemLink)
    local quality = nil
    local containerAPI = C_Container
    if bagID ~= nil and slotID ~= nil and containerAPI and type(containerAPI.GetContainerItemInfo) == "function" then
        local okInfo, info = pcall(containerAPI.GetContainerItemInfo, bagID, slotID)
        if okInfo and type(info) == "table" then
            quality = tonumber(info.quality or info.qualityID)
        end
    elseif bagID ~= nil and slotID ~= nil and type(GetContainerItemInfo) == "function" then
        local okInfo, _, _, _, resolvedQuality = pcall(GetContainerItemInfo, bagID, slotID)
        if okInfo then
            quality = tonumber(resolvedQuality)
        end
    end

    if quality == nil and itemLink and type(GetItemInfo) == "function" then
        local _, _, itemQuality = GetItemInfo(itemLink)
        quality = tonumber(itemQuality)
    end

    return quality
end

function ContainerItems:GetButtonItemLink(button, bagID, slotID)
    local itemLink = nil

    if bagID ~= nil and slotID ~= nil then
        itemLink = ContainerItems:GetItemLink(bagID, slotID)
        if type(itemLink) == "string" and itemLink ~= "" then
            return itemLink
        end
    end

    if button and type(button.GetItemLocation) == "function" and C_Item and type(C_Item.GetItemLink) == "function" then
        local okLocation, itemLocation = pcall(button.GetItemLocation, button)
        if okLocation and itemLocation then
            local okLink, resolvedLink = pcall(C_Item.GetItemLink, itemLocation)
            if okLink and type(resolvedLink) == "string" and resolvedLink ~= "" then
                return resolvedLink
            end
        end
    end

    local rawLocation = button and (button.itemLocation or button.ItemLocation) or nil
    if rawLocation and C_Item and type(C_Item.GetItemLink) == "function" then
        local okLink, resolvedLink = pcall(C_Item.GetItemLink, rawLocation)
        if okLink and type(resolvedLink) == "string" and resolvedLink ~= "" then
            return resolvedLink
        end
    end

    if button and type(button.GetItem) == "function" then
        local okItem, _, resolvedLink = pcall(button.GetItem, button)
        if okItem and type(resolvedLink) == "string" and resolvedLink ~= "" then
            return resolvedLink
        end
    end

    itemLink = button and (button.itemLink or button.link or button.hyperlink) or nil
    if type(itemLink) == "string" and itemLink ~= "" then
        return itemLink
    end

    return nil
end
