local _, addon = ...
local HLY = addon.HLY

local _G = _G
local gsub = gsub
local ipairs = ipairs
local strlower = strlower
local strtrim = strtrim

local C_TooltipInfo = C_TooltipInfo
local C_Item_IsBoundToAccountUntilEquip = C_Item and C_Item.IsBoundToAccountUntilEquip
local GetItemInfo = (C_Item and C_Item.GetItemInfo) or _G.GetItemInfo
local ItemLocation = _G.ItemLocation

local BOE_COLOR = { r = 1, g = 1, b = 1 }
local WUE_COLOR = { r = 0.55, g = 0.8, b = 1 }
local BOE_TEXT = "BoE"
local WUE_TEXT = "WuE"

local function SafeIsBoundToAccountUntilEquip(itemLocation, bagID, slotID)
    if not C_Item_IsBoundToAccountUntilEquip or not ItemLocation then
        return false
    end

    local location = itemLocation
    local ok, result

    if location then
        ok, result = pcall(C_Item_IsBoundToAccountUntilEquip, location)
        if ok then
            return result and true or false
        end
    end

    bagID = tonumber(bagID)
    slotID = tonumber(slotID)
    if not bagID or not slotID or slotID < 1 then
        return false
    end

    ok, location = pcall(ItemLocation.CreateFromBagAndSlot, ItemLocation, bagID, slotID)
    if not ok or not location then
        return false
    end

    ok, result = pcall(C_Item_IsBoundToAccountUntilEquip, location)
    if ok then
        return result and true or false
    end

    return false
end

local function NormalizeText(text)
    if not text then
        return ""
    end

    local cleaned = gsub(text, "|c%x%x%x%x%x%x%x%x", "")
    cleaned = gsub(cleaned, "|r", "")
    cleaned = gsub(cleaned, "|T.-|t", "")
    cleaned = gsub(cleaned, "%s+", " ")
    return strlower(strtrim(cleaned))
end

local function BuildMatchList(values)
    local list = {}
    for _, value in ipairs(values) do
        if value and value ~= "" then
            list[#list + 1] = NormalizeText(value)
        end
    end
    return list
end

local BOE_STRINGS = BuildMatchList({
    _G.ITEM_BIND_ON_EQUIP,
    "Binds when equipped",
    "Wird beim Anlegen gebunden",
})

local WUE_STRINGS = BuildMatchList({
    _G.ITEM_BIND_TO_WARBOUND_UNTIL_EQUIPPED,
    _G.ITEM_BIND_TO_BNETACCOUNT_UNTIL_EQUIPPED,
    _G.ITEM_BIND_TO_ACCOUNT_UNTIL_EQUIPPED,
    "Warbound until equipped",
    "Kriegsgebunden bis angelegt",
    "Kriegsgebunden bis zum Anlegen",
    "Kriegsgebunden (bis zum Anlegen)",
    "Kriegsgebunden (bis angelegt)",
    "Kriegsgebunden bis Ausruesten",
    "Warbound",
    "Kriegsgebunden",
})

local function MatchesAny(normalized, list)
    if normalized == "" then
        return false
    end

    for _, candidate in ipairs(list) do
        if candidate ~= "" and (normalized == candidate or normalized:find(candidate, 1, true)) then
            return true
        end
    end

    return false
end

local function ExtractBindStatus(tooltipData)
    if not tooltipData or not tooltipData.lines then
        return nil
    end

    for _, line in ipairs(tooltipData.lines) do
        local normalizedLeft = NormalizeText(line.leftText)
        local normalizedRight = NormalizeText(line.rightText)

        if MatchesAny(normalizedLeft, WUE_STRINGS) or MatchesAny(normalizedRight, WUE_STRINGS) then
            return "wue"
        end
        if MatchesAny(normalizedLeft, BOE_STRINGS) or MatchesAny(normalizedRight, BOE_STRINGS) then
            return "boe"
        end
    end

    return nil
end

function HLY:GetBindStatusForBagSlot(bag, slot)
    if not C_TooltipInfo or not C_TooltipInfo.GetBagItem then
        return nil
    end

    return ExtractBindStatus(C_TooltipInfo.GetBagItem(bag, slot))
end

function HLY:ApplyBindTextStyle(text)
    local db = self.db.boeText
    self:ApplyFont(text, db.font, db.fontSize, "SHADOWOUTLINE")
    self:SetPoint(text, db.anchor, db.xOffset, db.yOffset)
end

function HLY:UpdateSlotBindText(slot, bagID, slotID)
    if not slot then
        return
    end

    if not slot.hlyBindText then
        slot.hlyBindText = slot:CreateFontString(nil, "OVERLAY")
    end

    if not self.db or not self.db.boeText or not self.db.boeText.enabled then
        slot.hlyBindText:Hide()
        return
    end

    self:ApplyBindTextStyle(slot.hlyBindText)

    local itemLink = slot.itemLink or self:GetBagItemLink(bagID, slotID)
    if not itemLink or slot.isBound then
        slot.hlyBindText:SetText("")
        slot.hlyBindText:Hide()
        return
    end

    self.bindCache = self.bindCache or {}
    local cacheKey = self:GetBagCacheKey(bagID, slotID)
    local cached = self.bindCache[cacheKey]

    local status
    if cached and cached.itemLink == itemLink and cached.isBound == slot.isBound then
        status = cached.status
    else
        if GetItemInfo then
            local _, _, _, _, _, _, _, _, _, _, _, _, _, bindType = GetItemInfo(itemLink)
            if bindType == 2 then
                local isWuE = SafeIsBoundToAccountUntilEquip(slot.itemLocation, bagID, slotID)
                status = isWuE and "wue" or "boe"
            end
        end

        if not status then
            status = self:GetBindStatusForBagSlot(bagID, slotID)
        end

        self.bindCache[cacheKey] = {
            itemLink = itemLink,
            isBound = slot.isBound,
            status = status,
        }
    end

    if status then
        local isWuE = status == "wue"
        slot.hlyBindText:SetText(isWuE and WUE_TEXT or BOE_TEXT)
        slot.hlyBindText:Show()

        local color = isWuE and WUE_COLOR or BOE_COLOR
        slot.hlyBindText:SetTextColor(color.r, color.g, color.b)
    else
        slot.hlyBindText:SetText("")
        slot.hlyBindText:Hide()
    end
end

function HLY:RefreshBindSlots()
    self:ForEachBagSlot(function(slot, bagID, slotID)
        self:UpdateSlotBindText(slot, bagID, slotID)
    end)
end

function HLY:SetupBindHooks()
    if self.bindHooksSet then
        return
    end

    self.bindHooksSet = true
end

-- LibHLYUI options pane (v2) ------------------------------------------------
local BW_ANCHORS = { "TOPLEFT", "TOP", "TOPRIGHT", "LEFT", "CENTER", "RIGHT", "BOTTOMLEFT", "BOTTOM", "BOTTOMRIGHT" }

function HLY:BuildBoEWuEOptions(tab)
    tab:Note("Zeigt den BoE/WuE-Bindungsstatus auf Taschen-Itemslots an.")
    tab:Checkbox({
        label = "Enable",
        get = function() return self.db.boeText.enabled end,
        set = function(v) self.db.boeText.enabled = v self:RefreshBindSlots() end,
    })
    tab:Dropdown({ label = "Anchor", values = BW_ANCHORS, get = function() return self.db.boeText.anchor end, set = function(v) self.db.boeText.anchor = v self:RefreshBindSlots() end })
    tab:Row({
        function(c) c:Slider({ label = "X Offset", min = -30, max = 30, step = 1, labelWidth = 90, get = function() return self.db.boeText.xOffset end, set = function(v) self.db.boeText.xOffset = v self:RefreshBindSlots() end }) end,
        function(c) c:Slider({ label = "Y Offset", min = -30, max = 30, step = 1, labelWidth = 90, get = function() return self.db.boeText.yOffset end, set = function(v) self.db.boeText.yOffset = v self:RefreshBindSlots() end }) end,
    })
    tab:Dropdown({ label = "Font", fontPreview = true, values = function() return self:GetFontList() end, get = function() return self.db.boeText.font end, set = function(v) self.db.boeText.font = v self:RefreshBindSlots() end })
    tab:Slider({ label = "Font Size", min = 6, max = 24, step = 1, get = function() return self.db.boeText.fontSize end, set = function(v) self.db.boeText.fontSize = v self:RefreshBindSlots() end })
end

addon.options = addon.options or {}
addon.options[#addon.options + 1] = {
    parent = "UI", parentOrder = 100, group = "Gear", groupOrder = 1, name = "BoE / WuE", order = 2,
    build = "BuildBoEWuEOptions",
}
