local PT = AhUI
if not PT or not PT.InfoPanel then return end

local IP       = PT.InfoPanel
local Tooltip  = PT.Tooltip
local Dropdown = PT.Dropdown
local L        = PT.L

IP:RegisterElementInfo("gold", {
    name  = L["GOLD"] or "Gold",
    order = 20,
})

IP:RegisterElementInfo("gold_s_c", {
    name  = L["GOLD_S_C"] or "Gold + S + C",
    order = 21,
})

local function GetGoldDB()
    AhUI_DB = AhUI_DB or {}
    AhUI_DB.gold = AhUI_DB.gold or {}
    local realm = GetNormalizedRealmName()
    AhUI_DB.gold[realm] = AhUI_DB.gold[realm] or {}
    return AhUI_DB.gold[realm]
end

local function GetAllGoldDB()
    AhUI_DB = AhUI_DB or {}
    AhUI_DB.gold = AhUI_DB.gold or {}
    return AhUI_DB.gold
end

local function GetSortedRealms()
    local allDB = GetAllGoldDB()
    local realms = {}
    for realm in pairs(allDB) do
        table.insert(realms, realm)
    end
    table.sort(realms)
    return realms
end

local function GetSortedChars(realmData)
    local chars = {}
    for char, money in pairs(realmData) do
        if type(char) == "string"
           and type(money) == "number"
           and not char:match("^__") then
            table.insert(chars, char)
        end
    end
    table.sort(chars)
    return chars
end

local function FormatGold(amount)
    local g = math.floor((amount or 0) / 10000)
    return BreakUpLargeNumbers(g)
end

local function FormatFullMoney(amount)
    return GetCoinTextureString(amount or 0, 12)
end

local function Colorize(v)
    if v > 0 then
        return "|cff00ff00+" .. FormatGold(v) .. "|r"
    elseif v < 0 then
        return "|cffff4040" .. FormatGold(v) .. "|r"
    end
    return FormatGold(0)
end

local function ShowGoldEditDropdown(owner)
    if not Dropdown or not owner then return end

    local allDB = GetAllGoldDB()
    local items = {
        { text = L["GOLD_EDIT_TITLE"], header = true },
    }

    local realms = GetSortedRealms()

    for _, realm in ipairs(realms) do
        local realmData = allDB[realm]
        local chars = GetSortedChars(realmData)

        for _, char in ipairs(chars) do
            local money = realmData[char]

            table.insert(items, {
                text   = string.format("%s - %s", realm, char),
                amount = FormatGold(money),
                onClick = function()
                    realmData[char] = nil
                    ShowGoldEditDropdown(owner)
                end,
            })
        end
    end

    table.insert(items, {
        text = L["GOLD_REMOVE_ALL"],
        onClick = function()
            AhUI_DB.gold = {}
            Dropdown:Hide()
        end,
    })

    Dropdown:Show({
        owner    = owner,
        items    = items,
        keepOpen = true,
    })
end

local function ShowTooltip(self)
    if not Tooltip then return end

    local allDB = GetAllGoldDB()
    local total = 0

    local warbandMoney = 0
    if C_Bank and C_Bank.FetchDepositedMoney and Enum and Enum.BankType then
        warbandMoney = C_Bank.FetchDepositedMoney(Enum.BankType.Account) or 0
    end

    local useAlt = self.mode ~= "gold_s_c" and IsAltKeyDown()

    Tooltip:Clear()
    Tooltip:AddLine(L["GOLD_TITLE"], 14, 1, 1, 1)
    Tooltip:AddLine(" ")

    local realms = GetSortedRealms()

    for _, realm in ipairs(realms) do
        local realmData = allDB[realm]
        local chars = GetSortedChars(realmData)

        for _, char in ipairs(chars) do
            local money = realmData[char]
            total = total + money

            local moneyStr = useAlt
                and FormatFullMoney(money)
                or  FormatGold(money)

            Tooltip:AddLine(
                string.format("%s - %s — %s", realm, char, moneyStr),
                12, 1, 1, 1
            )
        end
    end

    Tooltip:AddLine(" ")

    if warbandMoney > 0 then
        local warbandStr = useAlt
            and FormatFullMoney(warbandMoney)
            or  FormatGold(warbandMoney)

        Tooltip:AddLine(
            string.format(L["GOLD_WARBAND_BANK"], warbandStr),
            12, 0.8, 1, 1
        )

        total = total + warbandMoney
        Tooltip:AddLine(" ")
    end

    local totalStr = useAlt
        and FormatFullMoney(total)
        or  FormatGold(total)

    Tooltip:AddLine(
        string.format(L["GOLD_TOTAL"], totalStr),
        12, 0.8, 0.8, 0.8
    )

    local realm = GetNormalizedRealmName()
    local realmData = allDB[realm]

    if realmData and realmData.__sessionStart then
        local now = realmData[UnitName("player")] or 0
        local delta = now - realmData.__sessionStart

        local sessionStr = Colorize(delta)
        if useAlt and delta ~= 0 then
            sessionStr =
                (delta > 0 and "|cff00ff00+" or "|cffff4040")
                .. FormatFullMoney(math.abs(delta))
                .. "|r"
        end

        Tooltip:AddLine(" ")
        Tooltip:AddLine(
            string.format(L["GOLD_SESSION"], sessionStr),
            12, 1, 1, 1
        )
    end

    Tooltip:AddLine(" ")
    Tooltip:AddLine(L["GOLD_HINT_BAGS"], 11, 0.7, 0.7, 0.7)
    Tooltip:AddLine(L["GOLD_EDIT_HINT"], 11, 0.7, 0.7, 0.7)
    Tooltip:AddLine(L["GOLD_HINT_ALT"], 11, 0.7, 0.7, 0.7)

    Tooltip:ShowSmart(self)
end

local function Create(uid, mode)
    local parent = (IP.frame and IP.frame.content) or UIParent
    local height = (IP.config and IP.config.appearance and IP.config.appearance.height) or 24

    local f = CreateFrame("Button", nil, parent)
    f:SetHeight(height)

    local s = math.max(16, height - 2)

    local icon = f:CreateTexture(nil, "ARTWORK")
    icon:SetTexture("Interface\\AddOns\\AhUI\\media\\icons\\ahui_gold.tga")
    icon:SetSize(s, s)
    icon:SetPoint("LEFT", 2, 0)

    local text = f:CreateFontString(nil, "OVERLAY")
    text:SetPoint("LEFT", icon, "RIGHT", 2, 0)
    text:SetFontObject(PT.fonts.normal)
    text:SetTextColor(1, 1, 1)

    f.icon = icon
    f.text = text
    f.mode = mode
    f.lastAltState = false

    f.UpdateTooltipAlt = function(self)
        if self.mode == "gold_s_c" then return end
        local isAlt = IsAltKeyDown()
        if isAlt ~= self.lastAltState then
            self.lastAltState = isAlt
            ShowTooltip(self)
        end
    end

    f:SetScript("OnEnter", function(self)
        self.lastAltState = IsAltKeyDown()
        ShowTooltip(self)
        self:SetScript("OnUpdate", self.UpdateTooltipAlt)
    end)

    f:SetScript("OnLeave", function(self)
        self:SetScript("OnUpdate", nil)
        if Tooltip then Tooltip:Clear() end
    end)

    f:RegisterForClicks("AnyUp")
    f:SetScript("OnClick", function(self, btn)
        if btn == "LeftButton" then
            ToggleAllBags()
        elseif btn == "RightButton" then
            ShowGoldEditDropdown(self)
        end
    end)

    local element = {
        _type = mode == "gold_s_c" and "GoldSC" or "Gold",
        id    = uid,
        frame = f,
        icon  = icon,
        text  = text,
        width = 60,
        mode  = mode,
    }

    if IP.EnableDrag then
        IP:EnableDrag(element)
    end

    function element:Update()
        local money = GetMoney() or 0

        if self.mode == "gold_s_c" then
            self.text:SetText(FormatFullMoney(money))
        else
            self.text:SetText(FormatGold(money))
        end

        local db = GetGoldDB()
        local name = UnitName("player")
        db[name] = money
        if not db.__sessionStart then
            db.__sessionStart = money
        end

        local w = self.icon:GetWidth()
            + (self.text:GetUnboundedStringWidth() or 0)
            + 8

        self.width = w
        self.frame:SetWidth(w)
    end

    function element:ApplyHeight(h)
        local s = math.max(16, h - 2)
        local fontSize = math.max(10, h - 8)
        self.icon:SetSize(s, s)
        self.text:SetFont(PT.FONT, fontSize, "")
    end

    element:Update()
    return element
end

IP:RegisterElementType("gold", function(uid)
    return Create(uid, "gold")
end)

IP:RegisterElementType("gold_s_c", function(uid)
    return Create(uid, "gold_s_c")
end)

local ev = CreateFrame("Frame")
ev:RegisterEvent("PLAYER_LOGIN")
ev:RegisterEvent("PLAYER_MONEY")
ev:SetScript("OnEvent", function()
    for _, element in pairs(IP.elements or {}) do
        if element and (element._type == "Gold" or element._type == "GoldSC") and element.Update then
            element:Update()
        end
    end
end)