-- Core/ProfessionGuides/ProfessionGuides_Shopping.lua
local PT = AhUI
if not PT then return end

PT.ProfessionGuides_Shopping = {}
local S = PT.ProfessionGuides_Shopping
S._pendingPurchase = nil
local ADDON_ID  = "AhUI ProfessionGuide"
local LIST_NAME = "AhUI: Profession Guide"
S.OnShoppingDataChanged = nil

-- =====================================================
-- Utils
-- =====================================================

local function IsAuctionatorAvailable()
    return Auctionator
       and Auctionator.API
       and Auctionator.API.v1
       and Auctionator.API.v1.CreateShoppingList
       and Auctionator.API.v1.ConvertToSearchString
end

-- =====================================================
-- Open Shopping tab
-- =====================================================

function S:OpenShoppingTab()
    -- открыть аукцион если закрыт
    if not AuctionHouseFrame or not AuctionHouseFrame:IsShown() then
        Auctionator.AH.Open()
    end

    -- Auctionator UI создаётся лениво
    C_Timer.After(0, function()
        if Auctionator
           and Auctionator.Shopping
           and Auctionator.Shopping.Tab
           and Auctionator.Shopping.Tab.Show
        then
            Auctionator.Shopping.Tab:Show()
        end
    end)
end

-- =====================================================
-- Create shopping list
-- =====================================================
function S:CreateShoppingList(materials)
    return self:CreateShoppingListAndOpen(materials)
end

local function EnsureItemInfoLoaded(materials, onReady)
    if not C_Item or not C_Item.RequestLoadItemDataByID then
        onReady()
        return
    end

    local pending = {}

    for itemID in pairs(materials) do
        if materials[itemID] and materials[itemID] > 0 then
            local name = GetItemInfo(itemID)
            if not name then
                pending[itemID] = true
                C_Item.RequestLoadItemDataByID(itemID)
            end
        end
    end

    if not next(pending) then
        onReady()
        return
    end

    local tries = 0
    local function Poll()
        tries = tries + 1

        for itemID in pairs(pending) do
            if GetItemInfo(itemID) then
                pending[itemID] = nil
            end
        end

        if not next(pending) then
            onReady()
            return
        end

        if tries >= 20 then
            -- не ждём вечно, просто пойдём как есть
            onReady()
            return
        end

        C_Timer.After(0.1, Poll)
    end

    Poll()
end

-- =====================================================
-- Public helper
-- =====================================================

function S:IsAvailable()
    return IsAuctionatorAvailable()
end
-- =====================================================
-- Create list + force open UI
-- =====================================================

function S:CreateShoppingListAndOpen(materials)
    if not materials or not next(materials) then
        return false, "empty"
    end

    if not IsAuctionatorAvailable() then
        return false, "no_auctionator"
    end

    EnsureItemInfoLoaded(materials, function()
        local searchStrings = {}

        for itemID, needCount in pairs(materials) do
            if needCount > 0 then
                local itemName = GetItemInfo(itemID)
                if itemName then
                    local s = Auctionator.API.v1.ConvertToSearchString(
                        ADDON_ID,
                        {
                            searchString = itemName,
                            quantity     = needCount,
                            isExact      = true,
                        }
                    )
                    table.insert(searchStrings, s)
                end
            end
        end

        if #searchStrings == 0 then
            -- если совсем ничего не прогрузилось — это уже реально проблема
            print("AhUI: не удалось получить названия предметов (кеш не прогружен)")
            return
        end

        Auctionator.API.v1.CreateShoppingList(ADDON_ID, LIST_NAME, searchStrings)

        if not AuctionHouseFrame or not AuctionHouseFrame:IsShown() then
            Auctionator.AH.Open()
        end
    end)

    return true
end

-- =====================================================
-- Auction house state
-- =====================================================

S.isAuctionHouseOpen = false

local f = CreateFrame("Frame")
f:RegisterEvent("AUCTION_HOUSE_SHOW")
f:RegisterEvent("AUCTION_HOUSE_CLOSED")

f:SetScript("OnEvent", function(_, event)
    S.isAuctionHouseOpen = (event == "AUCTION_HOUSE_SHOW")

    if S.OnAuctionStateChanged then
        S:OnAuctionStateChanged(S.isAuctionHouseOpen)
    end
end)

function S:CanBuy(skillLineID)
    return skillLineID ~= nil
       and self.isAuctionHouseOpen
       and IsAuctionatorAvailable()
end

function S:BuyForSkillLine(skillLineID)
    if not self:CanBuy(skillLineID) then
        return false, "unavailable"
    end

    local G = PT.ProfessionGuides
    local mats = G:BuildShoppingList(skillLineID)

    if not mats or not next(mats) then
        return false, "nothing_to_buy"
    end

    return self:CreateShoppingListAndOpen(mats)
end

hooksecurefunc(C_AuctionHouse, "ConfirmCommoditiesPurchase", function(itemID, quantity)
    S._pendingPurchase = {
        itemID = itemID,
        quantity = quantity,
    }
end)

function S:UpdateShoppingListAfterPurchase()
    if not self._pendingPurchase then return end
    if not IsAuctionatorAvailable() then return end

    local itemID   = self._pendingPurchase.itemID
    local bought   = self._pendingPurchase.quantity
    self._pendingPurchase = nil

    local items =
        Auctionator.API.v1.GetShoppingListItems(
            ADDON_ID,
            LIST_NAME
        )

    if not items then return end

    local itemName = GetItemInfo(itemID)
    if not itemName then return end

    for _, searchString in ipairs(items) do
        local terms =
            Auctionator.API.v1.ConvertFromSearchString(
                ADDON_ID,
                searchString
            )

        if terms and terms.searchString == itemName then
            local newQty = (terms.quantity or 0) - bought

            if newQty > 0 then
                local newSearch =
                    Auctionator.API.v1.ConvertToSearchString(
                        ADDON_ID,
                        {
                            searchString = itemName,
                            quantity     = newQty,
                            isExact      = true,
                        }
                    )

                Auctionator.API.v1.AlterShoppingListItem(
                    ADDON_ID,
                    LIST_NAME,
                    searchString,
                    newSearch
                )
            else
                Auctionator.API.v1.DeleteShoppingListItem(
                    ADDON_ID,
                    LIST_NAME,
                    searchString
                )
            end

            break
        end
    end
end

local ahWatcher = CreateFrame("Frame")
ahWatcher:RegisterEvent("COMMODITY_PURCHASE_SUCCEEDED")

ahWatcher:SetScript("OnEvent", function()
    S:UpdateShoppingListAfterPurchase()
end)
