-- Shop tab logic — methods added to TaskBoardController
local confirmBox = nil

--  Server data handler 

function TaskBoardController:onShopData(items)
    local parsed = {}
    for _, raw in ipairs(items or {}) do
        table.insert(parsed, self:parseShopItem(raw))
    end
    self.shopItems = parsed
end

function TaskBoardController:onShopResult(itemId, result)
    if result == 0 then
        -- Success — server will send updated shop data
        return
    end
    local errorMessages = {
        [SHOP_ERR_NOT_FOUND] = "Item not found.",
        [SHOP_ERR_ALREADY_BOUGHT] = "Already purchased.",
        [SHOP_ERR_NO_POINTS] = "Not enough Hunting Task Points.",
        [SHOP_ERR_NEED_BASE] = "You need the base outfit first.",
        [SHOP_ERR_STORE_INBOX] = "Store inbox error."
    }
    local msg = errorMessages[result] or ("Purchase failed (code " .. result .. ").")
    local errBox
    local function close()
        if errBox then
            errBox:destroy();
            errBox = nil
        end
    end
    errBox = displayGeneralBox(tr('Purchase Failed'), msg, {{
        text = tr('Ok'),
        callback = close
    }}, close, close)
end

--  Actions 

function TaskBoardController:buyItem(itemId)
    local item = nil
    local itemIndex = nil
    for index, it in ipairs(self.shopItems or {}) do
        if it.id == tonumber(itemId) then
            item = it
            itemIndex = index
            break
        end
    end
    if not item then
        return
    end
    local msg = tr("Do you really want to buy '%s' for %s Hunting Task Points?", item.title, comma_value(item.price))
    local function yes()
        g_game.taskHuntingShopPurchase(item.id)
        if confirmBox then
            confirmBox:destroy();
            confirmBox = nil
        end
    end
    local function cancel()
        if confirmBox then
            confirmBox:destroy();
            confirmBox = nil
        end
    end
    confirmBox = displayGeneralBox(tr('Confirm Purchase'), msg, {{
        text = tr('Yes'),
        callback = yes
    }, {
        text = tr('Cancel'),
        callback = cancel
    }}, yes, cancel)
end

function TaskBoardController:updateShopBalance(balance)
    balance = tonumber(balance) or 0
    self.shopBalance = balance
    -- shopItems canAfford field needs to be updated
    for i, item in ipairs(self.shopItems or {}) do
        self.shopItems[i].canAfford = balance >= item.price
    end
    self.shopItems = self.shopItems
end

--  Item parser 

function TaskBoardController:parseShopItem(raw)
    local offerType = tonumber(raw.offerType) or SHOP_OFFER_TYPE_ITEM
    local data = {
        id = tonumber(raw.id) or 0,
        title = raw.title or "",
        description = raw.description or "",
        price = tonumber(raw.price) or 0,
        bought = (tonumber(raw.bought) or 0) == 1,
        offerType = offerType,
        backdrop = SHOP_BACKDROP_IMAGES[offerType] or SHOP_BACKDROP_IMAGES[SHOP_OFFER_TYPE_ITEM],
        canAfford = false,
        lookMount = 0,
        previewType = nil
    }

    if offerType == SHOP_OFFER_TYPE_OUTFIT then
        local parsedLookType = tonumber(raw.lookType) or 0
        if parsedLookType > 0 then
            data.lookType = parsedLookType
        else
            g_logger.warning(string.format("[TaskBoard][Shop] Outfit without lookType (id=%s, title=%s)",
                tostring(data.id), tostring(data.title)))
        end
        data.lookHead = tonumber(raw.lookHead) or 0
        data.lookBody = tonumber(raw.lookBody) or 0
        data.lookLegs = tonumber(raw.lookLegs) or 0
        data.lookFeet = tonumber(raw.lookFeet) or 0
        data.lookAddons = tonumber(raw.lookAddons) or 0
        data.lookMount = 0
        data.isOutfit = parsedLookType > 0
        data.isCreaturePreview = data.isOutfit
        data.previewType = data.isCreaturePreview and 'creature' or nil
    elseif offerType == SHOP_OFFER_TYPE_MOUNT then
        local parsedMountType = tonumber(raw.lookType) or 0
        if parsedMountType > 0 then
            data.lookMount = parsedMountType
        else
            g_logger.warning(string.format("[TaskBoard][Shop] Mount without lookType (id=%s, title=%s)",
                tostring(data.id), tostring(data.title)))
        end
        data.lookType = 128
        data.lookHead = 95
        data.lookBody = 114
        data.lookLegs = 95
        data.lookFeet = 114
        data.lookAddons = 0
        data.isMount = parsedMountType > 0
        data.isCreaturePreview = data.isMount
        data.previewType = data.isCreaturePreview and 'creature' or nil
    elseif offerType == SHOP_OFFER_TYPE_ITEM or offerType == SHOP_OFFER_TYPE_ITEM_DOUBLE then
        data.itemId = tonumber(raw.itemId) or 0
        data.lookMount = 0
        data.isItem = (data.itemId > 0)
        data.previewType = data.isItem and 'item' or nil
    elseif offerType == SHOP_OFFER_TYPE_BONUS_PROMOTION then
        local defaults = SHOP_BONUS_DEFAULTS[SHOP_OFFER_TYPE_BONUS_PROMOTION] or {}
        data.title = defaults.title or data.title
        data.description = defaults.description or data.description
        data.imageSource = defaults.image or ""
        data.maxPurchases = tonumber(raw.maxPurchases) or 0
        data.currentPurchases = tonumber(raw.currentPurchases) or 0
        data.nextCost = tonumber(raw.nextCost) or 0
        data.price = data.nextCost
        data.description = string.format(data.description, data.currentPurchases)
        data.lookMount = 0
        data.isBonus = true
        data.previewType = 'icon'
    end

    local balance = tonumber(self.shopBalance)
    if not balance or balance <= 0 then
        local player = g_game.getLocalPlayer()
        balance = player and player:getResourceBalance(ResourceTypes.TASK_HUNTING) or balance or 0
    end

    data.canAfford = balance >= data.price
    data.displayPrice = comma_value(data.price)

    return data
end
