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("spec", {
    name  = "Spec",
    order = 20,
})

local function GetCurrentSpecData()
    local idx = GetSpecialization()
    if not idx then
        local _, className = UnitClass("player")
        return {
            id    = nil,
            name  = "—",
            icon  = 134400,
            class = className,
        }
    end

    local id, name, _, icon = GetSpecializationInfo(idx)
    local _, className = UnitClass("player")

    return {
        id    = id,
        name  = name,
        icon  = icon or 134400,
        class = className,
    }
end

local function GetLootSpecData()
    local lootID = GetLootSpecialization() or 0

    if lootID == 0 then
        return {
            id   = 0,
            name = L["SPEC_CURRENT"],
        }
    end

    local name = select(2, GetSpecializationInfoByID(lootID))

    return {
        id   = lootID,
        name = name or ("ID " .. lootID),
    }
end

local function OpenTalents()
    if not PlayerSpellsFrame then
        UIParentLoadAddOn("Blizzard_PlayerSpells")
    end

    if PlayerSpellsFrame then
        if PlayerSpellsFrame:IsShown() then
            PlayerSpellsFrame:Hide()
        else
            PlayerSpellsFrame:Show()
        end
    end
end
local function ShowSpecDropdown(element)
    local items = {
    {
        text = L["SPEC_TITLE"],
        header = true,
    },
}
    local curr = GetSpecialization()

    for i = 1, (GetNumSpecializations() or 0) do
        local id, name, _, icon = GetSpecializationInfo(i)
        if id then
            table.insert(items, {
                text = name,
                icon = icon,
                checked = (i == curr),
                onClick = function()
                    if i ~= curr then
                        C_SpecializationInfo.SetSpecialization(i)
                        element:Update()
                    end
                end,
            })
        end
    end

    Dropdown:Show({
        owner = element.frame,
        items = items,
    })
end
local function ShowLootSpecDropdown(element)
    local items = {
    {
        text = L["SPEC_LOOT"],
        header = true,
    },
}

    local currLoot = GetLootSpecialization() or 0

local currentSpec = GetCurrentSpecData()

table.insert(items, {
    text = L["SPEC_CURRENT"],
    icon = currentSpec.icon,
    checked = (currLoot == 0),
    onClick = function()
        SetLootSpecialization(0)
        element:Update()
    end,
})

    for i = 1, (GetNumSpecializations() or 0) do
        local specID, name, _, icon = GetSpecializationInfo(i)
        if specID then
            table.insert(items, {
                text = name,
                icon = icon,
                checked = (currLoot == specID),
                onClick = function()
                    SetLootSpecialization(specID)
                    element:Update()
                end,
            })
        end
    end

    Dropdown:Show({
        owner = element.frame,
        items = items,
    })
end
local function GetSpecHoverZone(frame)
    local x = GetCursorPosition()
    local scale = frame:GetEffectiveScale()
    x = x / scale

    local left = frame:GetLeft()
    if not left then return nil end

    local relX = x - left

    local specW = frame.icon:GetWidth()
    local dividerW = frame.divider:GetStringWidth() + 4
    local lootStart = specW + dividerW

    if relX <= specW then
        return "spec"
    elseif relX >= lootStart then
        return "loot"
    end

    return "center"
end

local function Create(uid)
    local parent = (IP.frame and IP.frame.content) or UIParent
    local height = IP.config.appearance.height or 24
    local s = math.max(14, height - 6)
    local f = CreateFrame("Button", nil, parent)
    f:SetHeight(height)

    local icon = f:CreateTexture(nil, "ARTWORK", nil, 1)
    icon:SetSize(s, s)
    icon:SetPoint("LEFT", 2, 0)
    icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
    f.icon = icon

    local iconMask = f:CreateMaskTexture(nil, "ARTWORK")
    iconMask:SetAllPoints(icon)
    iconMask:SetTexture("Interface\\CHARACTERFRAME\\TempPortraitAlphaMask", "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE")
    icon:AddMaskTexture(iconMask)

    local divider = f:CreateFontString(nil, "OVERLAY")
    divider:SetFont(IP.font or "GameFontNormal", s - 2, "")
    divider:SetPoint("LEFT", icon, "RIGHT", 4, 0)
    divider:SetText("|")
    divider:SetTextColor(0.6, 0.6, 0.6)
    f.divider = divider

    local lootIcon = f:CreateTexture(nil, "ARTWORK", nil, 1)
    lootIcon:SetSize(s, s)
    lootIcon:SetPoint("LEFT", divider, "RIGHT", 2, 0)
    lootIcon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
    f.lootIcon = lootIcon

    local lootMask = f:CreateMaskTexture(nil, "ARTWORK")
    lootMask:SetAllPoints(lootIcon)
    lootMask:SetTexture("Interface\\CHARACTERFRAME\\TempPortraitAlphaMask", "CLAMPTOBLACKADDITIVE", "CLAMPTOBLACKADDITIVE")
    lootIcon:AddMaskTexture(lootMask)

    local element = {
        _type = "spec",
        id = uid,
        frame = f,
        icon = icon,
        lootIcon = lootIcon,
        divider = divider,
        width = s,
    }
    if IP.EnableDrag then
        IP:EnableDrag(element)
    end

    f._onUpdateTooltip = function(self)
        if not Tooltip then return end
        local zone = GetSpecHoverZone(self)
        if zone == self._hoverZone then return end
        self._hoverZone = zone
        local spec = GetCurrentSpecData()
        local loot = GetLootSpecData()
        Tooltip:Clear()
        if zone == "spec" then
            Tooltip:AddLine(L["SPEC_TITLE"], 14, 1, 1, 1)
            Tooltip:AddLine(" ")
            Tooltip:AddLine(L["SPEC_ACTIVE"], 12, 0.8, 0.8, 0.8)
            Tooltip:AddLine(spec.name or L["SPEC_EMPTY"], 12, 1, 1, 1)
            Tooltip:AddLine(" ")
            Tooltip:AddLine(L["SPEC_HINT_SPEC"], 11, 0.7, 0.7, 0.7)
            Tooltip:AddLine(L["SPEC_HINT_TALENTS"], 11, 0.7, 0.7, 0.7)
        elseif zone == "loot" then
            Tooltip:AddLine(L["SPEC_LOOT"], 14, 1, 1, 1)
            Tooltip:AddLine(" ")
            Tooltip:AddLine(loot.name or L["SPEC_EMPTY"], 12, 1, 1, 1)
            Tooltip:AddLine(" ")
            Tooltip:AddLine(L["SPEC_HINT_LOOT"], 11, 0.7, 0.7, 0.7)
        else
            Tooltip:AddLine(L["SPEC_TITLE"], 14, 1, 1, 1)
            Tooltip:AddLine(" ")
            Tooltip:AddLine(spec.name or L["SPEC_EMPTY"], 12, 1, 1, 1)
            Tooltip:AddLine(loot.name or L["SPEC_EMPTY"], 12, 0.8, 0.8, 0.8)
        end
        Tooltip:ShowSmart(self)
    end
    f:SetScript("OnEnter", function(self)
        self._hoverZone = nil
        self:SetScript("OnUpdate", self._onUpdateTooltip)
    end)
    f:SetScript("OnLeave", function(self)
        self:SetScript("OnUpdate", nil)
        self._hoverZone = nil
        if Tooltip then Tooltip:Clear() end
    end)

    f:RegisterForClicks("AnyUp")
    f:SetScript("OnClick", function(self, btn)
        if btn ~= "LeftButton" and btn ~= "RightButton" then return end
        if btn == "LeftButton" and IsShiftKeyDown() then
            OpenTalents()
            return
        end
        local x = GetCursorPosition()
        local scale = self:GetEffectiveScale()
        x = x / scale
        local left = self:GetLeft()
        if not left then return end
        local relX = x - left
        local specW = self.icon:GetWidth()
        local dividerW = self.divider:GetStringWidth() + 4
        local lootStart = specW + dividerW
        if relX <= specW then
            ShowSpecDropdown(element)
        elseif relX >= lootStart then
            ShowLootSpecDropdown(element)
        end
    end)

    function element:Update()
        local spec = GetCurrentSpecData()
        local loot = GetLootSpecData()
        self.icon:SetTexture(spec.icon)
        if loot.id and loot.id ~= 0 then
            local _, _, _, tex = GetSpecializationInfoByID(loot.id)
            self.lootIcon:SetTexture(tex or spec.icon)
        else
            self.lootIcon:SetTexture(spec.icon)
        end
        local w =
            self.icon:GetWidth()
            + self.divider:GetStringWidth()
            + self.lootIcon:GetWidth()
            + 12
        self.width = w
        self.frame:SetWidth(w)
    end
    element:Update()

    function element:ApplyHeight(h)
        local s = math.max(14, h - 6)
        self.icon:SetSize(s, s)
        self.lootIcon:SetSize(s, s)
        self.divider:SetFont(IP.font or PT.FONT, s - 2, "")
    end

    return element
end

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

local ev = CreateFrame("Frame")
ev:RegisterEvent("PLAYER_LOGIN")
ev:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED")
ev:RegisterEvent("PLAYER_LOOT_SPEC_UPDATED")

ev:SetScript("OnEvent", function()
    for _, el in pairs(IP.elements or {}) do
        if el and el._type == "spec" and el.Update then
            el:Update()
        end
    end
end)