--[[
============================================================
Decor Vendor Addon
© 2026 MidniteDestiny. All Rights Reserved.
============================================================

This file is part of the Decor Vendor addon.

All code, structure, and design are the intellectual
property of MidniteDestiny unless otherwise stated.

You may NOT:
• Copy, reproduce, or redistribute this code
• Modify and redistribute this code
• Use this code in other addons or projects

without explicit permission from the author.

This addon is distributed for personal use only.

============================================================
]]
local addonName, dv = ...

 function dv.HasAnySelection(tbl)
    if not tbl then return false end
    for _, v in pairs(tbl) do
        if v then return true end
    end
    return false
end

function dv.GetHeaderWidth()
    if dv.currentTab == "professions" then
        return frame:GetWidth() - 40
    else
        return frame:GetWidth() - frame.sidebar:GetWidth() - 40
    end
end

 function dv.BuildProfessionLookup()
    dv.itemToProfession = {}
    for _, profession in ipairs(dv.professions or {}) do
        for _, recipe in ipairs(profession.items or {}) do
            dv.itemToProfession[recipe.id] = profession.name
        end
    end
end

function dv:GetItemData(itemID)
    return self.ActiveItems[itemID]
end

--[[function dv.IsItemCollected(itemID)
    local itemData = dv.ActiveItems[itemID]
    local noxp = itemData and itemData.noxp

    -- Correct cache usage
    if noxp then
        if vendorSettings.completedDropNoXP[itemID] then return true end
    else
        if vendorSettings.completedDrop[itemID] then return true end
    end

    if dv.collectionCache[itemID] ~= nil then
        return dv.collectionCache[itemID]
    end

    local decorID = itemData and itemData.decorID
    if not decorID then
        dv.collectionCache[itemID] = false
        return false
    end

    local info = C_HousingCatalog.GetCatalogEntryInfoByRecordID(1, decorID, true)
    local isCollected = false

    if info then
        if noxp then
            -- ONLY these rules for NOXP
            if info.quantity > 0 or info.remainingRedeemable > 0 or info.numPlaced > 0 then
                isCollected = true
            end
        else
            -- ONLY this rule for normal items
            if info.firstAcquisitionBonus == 0 then
                isCollected = true
            end
        end
    end

    if isCollected then
        if noxp then
            vendorSettings.completedDropNoXP[itemID] = true
        else
            vendorSettings.completedDrop[itemID] = true
        end

        dv.collectionCache[itemID] = true
        return true
    end

    dv.collectionCache[itemID] = false
    return false
end]]

function dv.IsQuestEffectivelyCompleted(quest)
    if not quest then return false end

    -- 🔥 QUEST COMPLETION (ACCOUNT-WIDE)
    if type(quest.id) == "number" then
        if C_QuestLog.IsQuestFlaggedCompletedOnAccount then
            if C_QuestLog.IsQuestFlaggedCompletedOnAccount(quest.id) then
                return true
            end
        else
            if C_QuestLog.IsQuestFlaggedCompleted(quest.id) then
                return true
            end
        end
    end

    -- 🔥 ITEM COLLECTION (ALREADY ACCOUNT-WIDE)
    if quest.itemID then
        if type(quest.itemID) == "table" then
            for _, itemID in ipairs(quest.itemID) do
                if dv.IsItemCollected(itemID) then
                    return true
                end
            end
        elseif type(quest.itemID) == "number" then
            if dv.IsItemCollected(quest.itemID) then
                return true
            end
        end
    end

    return false
end

function dv.IsItemCollected(itemID)
    local itemData = dv.ActiveItems[itemID]
    local noxp = itemData and itemData.noxp

    -- Correct cache usage
    if noxp then
        if vendorSettings.completedDropNoXP[itemID] then return true end
    else
        if vendorSettings.completedDrop[itemID] then return true end
    end

    if dv.collectionCache[itemID] ~= nil then
        return dv.collectionCache[itemID]
    end

    local decorID = itemData and itemData.decorID
    if not decorID then
        dv.collectionCache[itemID] = false
        return false
    end

    local info = C_HousingCatalog.GetCatalogEntryInfoByRecordID(1, decorID, true)
    local isCollected = false

    if info then
        if noxp then
            -- ONLY these rules for NOXP
            if info.quantity > 0 or info.remainingRedeemable > 0 or info.numPlaced > 0 then
                isCollected = true
            end
        else
            -- ONLY this rule for normal items
            if info.firstAcquisitionBonus == 0 then
                isCollected = true
            end
        end
    end

    if isCollected then
        if noxp then
            vendorSettings.completedDropNoXP[itemID] = true
        else
            vendorSettings.completedDrop[itemID] = true
        end

        dv.collectionCache[itemID] = true
        return true
    end

    dv.collectionCache[itemID] = false
    return false
end

function dv.CountProfessionItems(profession)
    local total = 0
    local completed = 0

    for _, item in ipairs(profession.items or {}) do
        total = total + 1

        local learned = false
        if item.spell then
            learned = IsSpellKnown(item.spell) or IsPlayerSpell(item.spell)
        end

        local collected = false
        if item.id and dv.IsItemCollected then
            collected = dv.IsItemCollected(item.id)
        end

        if learned or collected then
            completed = completed + 1
        end
    end

    return completed, total
end

 function dv.IsAchievementComplete(achievementID)
    if not achievementID then return false end

    if vendorSettings.completedAchievs[achievementID] then
        return true
    end

    local _, _, _, completed = GetAchievementInfo(achievementID)
    if completed then
        vendorSettings.completedAchievs[achievementID] = true
    end

    return completed or false
end

-- ============================================================
-- Tab scroll frames helper
-- ============================================================
 function dv.CreateTabScrollFrame(tabFrame)
    local scroll = CreateFrame("ScrollFrame", nil, tabFrame, "UIPanelScrollFrameTemplate")
    scroll:SetPoint("TOPLEFT", 0, -26)
    scroll:SetPoint("BOTTOMRIGHT", -20, 0)

    local child = CreateFrame("Frame", nil, scroll)
    child:SetWidth(1)
    child:SetHeight(1)
    scroll:SetScrollChild(child)

    scroll:SetScript("OnSizeChanged", function(self, width)
        child:SetWidth(width)
    end)

    return scroll, child
end
