local _, ns = ...

local ButtonWidgets = {}
ns.UIButtonWidgets = ButtonWidgets

local BACKDROP_TEMPLATE = BackdropTemplateMixin and "BackdropTemplate" or nil

local UIData = ns.UIData or {}
local PREMIUM = UIData.PREMIUM or {}
local THEME = UIData.THEME or {}

local function createLabel(parent, fontObject, justify)
    local text = parent:CreateFontString(nil, "OVERLAY", fontObject)
    text:SetJustifyH(justify or "LEFT")
    text:SetJustifyV("MIDDLE")
    return text
end

local function setTextureColor(texture, color, alpha)
    if not texture or type(color) ~= "table" then
        return
    end

    texture:SetVertexColor(color[1], color[2], color[3], alpha == nil and 1 or alpha)
end

local function getTextWidth(fontString)
    if not fontString then
        return 0
    end

    if fontString.GetUnboundedStringWidth then
        local width = fontString:GetUnboundedStringWidth()
        if width and width > 0 then
            return width
        end
    end

    return fontString:GetStringWidth() or 0
end

local function createMiniActionButton(parent, text, width)
    local button = CreateFrame("Button", nil, parent, BACKDROP_TEMPLATE)
    local buttonWidth = width or 24
    button:SetSize(buttonWidth, 22)

    if button.SetBackdrop then
        button:SetBackdrop({
            bgFile = "Interface\\Buttons\\WHITE8X8",
            edgeFile = "Interface\\Buttons\\WHITE8X8",
            tile = false,
            edgeSize = 1,
            insets = { left = 1, right = 1, top = 1, bottom = 1 },
        })
        button:SetBackdropColor(THEME.metal[1], THEME.metal[2], THEME.metal[3], 0.92)
        button:SetBackdropBorderColor(THEME.goldDim[1], THEME.goldDim[2], THEME.goldDim[3], 0.70)
    end

    button.bg = button:CreateTexture(nil, "BACKGROUND")
    button.bg:SetAllPoints()
    button.bg:SetTexture(PREMIUM.buttonNormal)
    setTextureColor(button.bg, { 1, 1, 1 }, 0.96)

    button.hover = button:CreateTexture(nil, "BACKGROUND", nil, 1)
    button.hover:SetAllPoints()
    button.hover:SetTexture(PREMIUM.buttonHover)
    setTextureColor(button.hover, { 1, 1, 1 }, 1)
    button.hover:SetAlpha(0)

    button.innerShade = button:CreateTexture(nil, "BACKGROUND", nil, 2)
    button.innerShade:SetPoint("TOPLEFT", 1, -1)
    button.innerShade:SetPoint("BOTTOMRIGHT", -1, 1)
    button.innerShade:SetTexture("Interface\\Buttons\\WHITE8X8")
    button.innerShade:SetColorTexture(THEME.shadow[1], THEME.shadow[2], THEME.shadow[3], 0.08)

    button.topEdge = button:CreateTexture(nil, "BORDER")
    button.topEdge:SetPoint("TOPLEFT", 8, -4)
    button.topEdge:SetPoint("TOPRIGHT", -8, -4)
    button.topEdge:SetHeight(1)
    button.topEdge:SetTexture("Interface\\Buttons\\WHITE8X8")
    button.topEdge:SetAlpha(0)

    button.label = createLabel(button, "GameFontNormalSmall", "CENTER")
    if buttonWidth <= 28 then
        button.label:SetPoint("CENTER", 0, 0)
        button.label:SetWidth(math.max(10, buttonWidth - 4))
    else
        button.label:SetPoint("LEFT", 8, 0)
        button.label:SetPoint("RIGHT", -8, 0)
    end
    if button.label.SetWordWrap then
        button.label:SetWordWrap(false)
    end
    if button.label.SetNonSpaceWrap then
        button.label:SetNonSpaceWrap(false)
    end
    button.label:SetText(text or "")
    button.label:SetTextColor(THEME.gold[1], THEME.gold[2], THEME.gold[3])

    button.measureLabel = button:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    button.measureLabel:Hide()

    function button:SetButtonText(labelText, minWidth, maxWidth)
        if self.glyphIcon then
            self.glyphIcon:Hide()
        end
        self.label:SetText(labelText or "")
        self.measureLabel:SetText(labelText or "")
        local desiredWidth = math.ceil(getTextWidth(self.measureLabel) + 20)
        local targetWidth = math.max(minWidth or buttonWidth, desiredWidth)
        if maxWidth then
            targetWidth = math.min(maxWidth, targetWidth)
        end
        self.vlDesiredWidth = targetWidth
        self:SetWidth(targetWidth)
        return targetWidth
    end

    button.glyphIcon = button:CreateTexture(nil, "ARTWORK")
    button.glyphIcon:SetSize(14, 14)
    button.glyphIcon:SetPoint("CENTER", 0, 0)
    button.glyphIcon:Hide()

    function button:SetButtonIcon(texture, iconSize, minWidth, maxWidth)
        local targetWidth = self:SetButtonText("", minWidth or buttonWidth, maxWidth)
        if texture and texture ~= "" then
            local size = iconSize or 12
            self.glyphIcon:SetTexture(texture)
            self.glyphIcon:SetSize(size, size)
            self.glyphIcon:ClearAllPoints()
            self.glyphIcon:SetPoint("CENTER", 0, 0)
            self.glyphIcon:SetVertexColor(1, 1, 1, 1)
            self.glyphIcon:Show()
        else
            self.glyphIcon:Hide()
        end
        return targetWidth
    end

    button:SetScript("OnEnter", function(self)
        if self.SetBackdropBorderColor then
            self:SetBackdropBorderColor(THEME.gold[1], THEME.gold[2], THEME.gold[3], 0.92)
        end
        self.hover:SetAlpha(1)
    end)
    button:SetScript("OnLeave", function(self)
        if self.SetBackdropBorderColor then
            if self.vlActive then
                self:SetBackdropBorderColor(THEME.gold[1], THEME.gold[2], THEME.gold[3], 0.88)
            else
                self:SetBackdropBorderColor(THEME.goldDim[1], THEME.goldDim[2], THEME.goldDim[3], 0.70)
            end
        end
        self.hover:SetAlpha(self.vlActive and 0.55 or 0)
    end)

    return button
end

local function setMiniActionButtonActive(button, isActive)
    if not button then
        return
    end

    button.vlActive = isActive == true
    button.hover:SetAlpha(button.vlActive and 0.55 or 0)
    button:SetAlpha(button.vlActive and 1 or 0.86)

    if button.SetBackdropBorderColor then
        if button.vlActive then
            button:SetBackdropBorderColor(THEME.gold[1], THEME.gold[2], THEME.gold[3], 0.88)
        else
            button:SetBackdropBorderColor(THEME.goldDim[1], THEME.goldDim[2], THEME.goldDim[3], 0.70)
        end
    end
end

local function createTabButton(parent, label, width, height, fontObject, style)
    local button = CreateFrame("Button", nil, parent, BACKDROP_TEMPLATE)
    button.style = style or "sub"
    button.active = false

    local buttonHeight = height or (button.style == "main" and 26 or 24)
    button:SetSize(width or 128, buttonHeight)

    if button.SetBackdrop then
        button:SetBackdrop({
            bgFile = "Interface\\Buttons\\WHITE8X8",
            edgeFile = "Interface\\Buttons\\WHITE8X8",
            tile = false,
            edgeSize = 1,
            insets = { left = 1, right = 1, top = 1, bottom = 1 },
        })
        button:SetBackdropColor(THEME.metalDeep[1], THEME.metalDeep[2], THEME.metalDeep[3], 0.96)
        button:SetBackdropBorderColor(THEME.goldDim[1], THEME.goldDim[2], THEME.goldDim[3], 0.46)
    end

    button.bg = button:CreateTexture(nil, "BACKGROUND")
    button.bg:SetAllPoints()
    button.bg:SetTexture(PREMIUM.tabNormal)
    setTextureColor(button.bg, { 1, 1, 1 }, 0.98)

    button.hover = button:CreateTexture(nil, "BACKGROUND", nil, 1)
    button.hover:SetAllPoints()
    button.hover:SetTexture(PREMIUM.tabHover)
    setTextureColor(button.hover, { 1, 1, 1 }, 1)
    button.hover:SetAlpha(0)

    button.activeFill = button:CreateTexture(nil, "BACKGROUND", nil, 2)
    button.activeFill:SetAllPoints()
    button.activeFill:SetTexture(PREMIUM.tabActive)
    setTextureColor(button.activeFill, { 1, 1, 1 }, 1)
    button.activeFill:SetAlpha(0)

    button.innerShade = button:CreateTexture(nil, "BACKGROUND", nil, 3)
    button.innerShade:SetPoint("TOPLEFT", 1, -1)
    button.innerShade:SetPoint("BOTTOMRIGHT", -1, 1)
    button.innerShade:SetTexture("Interface\\Buttons\\WHITE8X8")
    button.innerShade:SetColorTexture(THEME.shadow[1], THEME.shadow[2], THEME.shadow[3], 0.08)

    button.topLine = button:CreateTexture(nil, "BORDER")
    button.topLine:SetPoint("TOPLEFT", 8, -6)
    button.topLine:SetPoint("TOPRIGHT", -8, -6)
    button.topLine:SetHeight(1)
    button.topLine:SetTexture("Interface\\Buttons\\WHITE8X8")
    button.topLine:SetAlpha(0)

    button.bottomLine = button:CreateTexture(nil, "BORDER")
    button.bottomLine:SetPoint("BOTTOMLEFT", 8, 2)
    button.bottomLine:SetPoint("BOTTOMRIGHT", -8, 2)
    button.bottomLine:SetHeight(button.style == "main" and 2 or 1)
    button.bottomLine:SetTexture("Interface\\Buttons\\WHITE8X8")
    setTextureColor(button.bottomLine, THEME.gold, 0)
    button.bottomLine:Hide()

    button.label = createLabel(button, fontObject or "GameFontNormal", "CENTER")
    button.label:ClearAllPoints()
    button.label:SetPoint("LEFT", 12, button.style == "main" and -1 or 0)
    button.label:SetPoint("RIGHT", -12, button.style == "main" and -1 or 0)
    if button.label.SetWordWrap then
        button.label:SetWordWrap(false)
    end
    if button.label.SetNonSpaceWrap then
        button.label:SetNonSpaceWrap(false)
    end
    button.label:SetText(label or "")

    button.measureLabel = button:CreateFontString(nil, "OVERLAY", fontObject or "GameFontNormal")
    button.measureLabel:Hide()

    function button:SetButtonText(text)
        self.label:SetText(text or "")
        self.measureLabel:SetText(text or "")
        local textWidth = math.ceil(getTextWidth(self.measureLabel) + (self.style == "main" and 28 or 24))
        local minWidth = self.style == "main" and 64 or 86
        local targetWidth = math.max(minWidth, textWidth)
        self.vlDesiredWidth = targetWidth
        self:SetWidth(targetWidth)
        return targetWidth
    end

    function button:SetActive(isActive)
        self.active = isActive == true
        if self.active then
            self:Disable()
            if self.SetBackdropBorderColor then
                self:SetBackdropBorderColor(THEME.gold[1], THEME.gold[2], THEME.gold[3], 0.92)
            end
            self.hover:SetAlpha(0)
            self.activeFill:SetAlpha(1)
            self.bottomLine:SetAlpha(0)
            self.label:SetTextColor(THEME.gold[1], THEME.gold[2], THEME.gold[3])
        else
            self:Enable()
            if self.SetBackdropBorderColor then
                self:SetBackdropBorderColor(THEME.goldDim[1], THEME.goldDim[2], THEME.goldDim[3], 0.46)
            end
            self.activeFill:SetAlpha(0)
            self.bottomLine:SetAlpha(0)
            self.label:SetTextColor(THEME.parchment[1], THEME.parchment[2], THEME.parchment[3], 0.88)
        end
    end

    button:SetScript("OnEnter", function(self)
        if not self.active then
            if self.SetBackdropBorderColor then
                self:SetBackdropBorderColor(THEME.goldSoft[1], THEME.goldSoft[2], THEME.goldSoft[3], 0.82)
            end
            self.hover:SetAlpha(1)
        end
    end)

    button:SetScript("OnLeave", function(self)
        if not self.active then
            if self.SetBackdropBorderColor then
                self:SetBackdropBorderColor(THEME.goldDim[1], THEME.goldDim[2], THEME.goldDim[3], 0.46)
            end
            self.hover:SetAlpha(0)
        end
    end)

    return button
end

local function createMainTab(parent, index, text)
    local button = createTabButton(parent, text, 140, 28, "GameFontNormal", "main")
    button:SetID(index)
    button:SetButtonText(text)
    return button
end

local function createSubTab(parent, text, width)
    local button = createTabButton(parent, text, width or 140, 24, "GameFontNormalSmall", "sub")
    button:SetButtonText(text)
    return button
end

local function createVerticalSubTab(parent, text, width)
    local button = createTabButton(parent, text, width or 142, 34, "GameFontNormalSmall", "sub")
    button:SetButtonText(text)
    return button
end

ButtonWidgets.CreateMiniActionButton = createMiniActionButton
ButtonWidgets.SetMiniActionButtonActive = setMiniActionButtonActive
ButtonWidgets.CreateMainTab = createMainTab
ButtonWidgets.CreateSubTab = createSubTab
ButtonWidgets.CreateVerticalSubTab = createVerticalSubTab
