local ADDON_NAME = ...

QuickCompare = QuickCompare or {}

local DEFAULTS = {
    enabled = true,
}

local hooksInstalled = false
local optionsPanel = nil

local function EnsureDB()
    if type(QuickCompareDB) ~= "table" then
        QuickCompareDB = {}
    end

    for key, value in pairs(DEFAULTS) do
        if QuickCompareDB[key] == nil then
            QuickCompareDB[key] = value
        end
    end
end

local function IsEnabled()
    return QuickCompareDB and QuickCompareDB.enabled ~= false
end

local function GetFrameName(frame)
    if frame and frame.GetName then
        return frame:GetName()
    end
end

local function ShouldSuppressCompare()
    if IsControlKeyDown() then
        return true
    end

    local frameName = GetFrameName(GetMouseFocus()) or ""
    return strfind(frameName, "^Character.*Slot$")
        or strfind(frameName, "^TempEnchant%d+$")
        or strfind(frameName, "^TM_Button")
        or strfind(frameName, "^TrinketMenu")
end

local function GetCompareTooltip(prefix, index)
    if not prefix or prefix == "ShoppingTooltip" then
        return _G["ShoppingTooltip" .. index]
    end

    return _G[prefix .. index]
end

local function HideCompareTooltips(prefix)
    for index = 1, 2 do
        local tooltip = GetCompareTooltip(prefix, index)
        if tooltip then
            tooltip:Hide()
        end
    end
end

local function PositionCompareTooltips(tooltip, link, prefix)
    local anchor = "TOPLEFT"
    local align = "TOPRIGHT"
    local scale = tooltip:GetScale() or 1
    local effectiveScale = tooltip:GetEffectiveScale() or scale
    local leftPos = tooltip:GetLeft() or 0
    local rightPos = tooltip:GetRight() or 0
    local rightDist = GetScreenWidth() - rightPos
    local totalWidth = 0
    local visibleTips = {}

    if leftPos > 0 and rightDist < leftPos then
        anchor, align = "TOPRIGHT", "TOPLEFT"
    end

    for index = 1, 2 do
        local compareTooltip = GetCompareTooltip(prefix, index)
        if compareTooltip and compareTooltip:SetHyperlinkCompareItem(link, index) then
            totalWidth = totalWidth + compareTooltip:GetWidth()
            table.insert(visibleTips, { tooltip = compareTooltip, index = index })
        elseif compareTooltip then
            compareTooltip:Hide()
        end
    end

    if #visibleTips == 0 then
        return
    end

    local cursorX = GetCursorPosition()
    local realRightPos = rightPos * effectiveScale
    local realLeftPos = leftPos * effectiveScale

    if anchor == "TOPLEFT" and cursorX > realRightPos then
        anchor, align = "TOPRIGHT", "TOPLEFT"
    elseif anchor == "TOPRIGHT" and cursorX < realLeftPos then
        anchor, align = "TOPLEFT", "TOPRIGHT"
    end

    if anchor == "TOPRIGHT" and totalWidth > leftPos * effectiveScale then
        anchor, align = "TOPLEFT", "TOPRIGHT"
    elseif anchor == "TOPLEFT" and (rightPos * effectiveScale + totalWidth) > (GetScreenWidth() * effectiveScale) then
        anchor, align = "TOPRIGHT", "TOPLEFT"
    end

    if tooltip.GetAnchorType and tooltip:GetAnchorType() then
        if anchor == "TOPRIGHT" and totalWidth > leftPos then
            tooltip:SetAnchorType(tooltip:GetAnchorType(), totalWidth - leftPos, 0)
        elseif anchor == "TOPLEFT" and (rightPos + totalWidth) > GetScreenWidth() then
            tooltip:SetAnchorType(tooltip:GetAnchorType(), -((rightPos + totalWidth) - GetScreenWidth()), 0)
        end
    end

    local anchorFrame = tooltip
    local dy = 0

    for _, entry in ipairs(visibleTips) do
        local compareTooltip = entry.tooltip
        compareTooltip:SetOwner(tooltip, "ANCHOR_NONE")
        compareTooltip:SetHyperlinkCompareItem(link, entry.index)
        compareTooltip:ClearAllPoints()

        local text = _G[compareTooltip:GetName() .. "TextLeft1"]
        if text then
            text:SetText("|cffE0E0E0[" .. CURRENTLY_EQUIPPED .. "]|r")
        end

        local bottom = compareTooltip:GetBottom()
        local uiBottom = UIParent:GetBottom()
        if bottom and bottom * scale - 10 <= uiBottom then
            dy = uiBottom - bottom + (10 * scale)
        end

        compareTooltip:SetPoint(anchor, anchorFrame, align, 0, dy)
        compareTooltip:SetScale(scale)
        compareTooltip:Show()
        anchorFrame = compareTooltip
        dy = 0
    end
end

local function ShowCompareForTooltip(tooltip, prefix)
    HideCompareTooltips(prefix)

    if not tooltip or not IsEnabled() or ShouldSuppressCompare() then
        return
    end

    local _, link = tooltip:GetItem()
    if not link then
        return
    end

    PositionCompareTooltips(tooltip, link, prefix)
end

local function RefreshGameTooltipCompare()
    if GameTooltip and GameTooltip:IsShown() then
        ShowCompareForTooltip(GameTooltip, "ShoppingTooltip")
    else
        HideCompareTooltips("ShoppingTooltip")
    end
end

local function RefreshItemRefCompare()
    if ItemRefTooltip and ItemRefTooltip:IsShown() then
        ShowCompareForTooltip(ItemRefTooltip, "ItemRefCompareTooltip")
    else
        HideCompareTooltips("ItemRefCompareTooltip")
    end
end

local function SetEnabled(enabled)
    QuickCompareDB.enabled = enabled and true or false
    RefreshGameTooltipCompare()
    RefreshItemRefCompare()
end

function QuickCompare_Toggle(enabled)
    EnsureDB()
    SetEnabled(enabled)
end

local function OpenOptionsPanel()
    if not optionsPanel or type(InterfaceOptionsFrame_OpenToCategory) ~= "function" then
        return false
    end

    InterfaceOptionsFrame_OpenToCategory(optionsPanel)
    InterfaceOptionsFrame_OpenToCategory(optionsPanel)

    if InterfaceOptionsFrame and InterfaceOptionsFrame.Raise then
        InterfaceOptionsFrame:Raise()
    end

    return InterfaceOptionsFrame and InterfaceOptionsFrame:IsShown()
end

QuickCompare.OpenOptions = OpenOptionsPanel
QuickCompare.Toggle = QuickCompare_Toggle

local function CreateOptionsPanel()
    if optionsPanel then
        return
    end

    optionsPanel = CreateFrame("Frame", "QuickCompareOptionsPanel", UIParent)
    optionsPanel.name = "QuickCompare"

    local title = optionsPanel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    title:SetPoint("TOPLEFT", 16, -16)
    title:SetText("QuickCompare")

    local subtitle = optionsPanel:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
    subtitle:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -8)
    subtitle:SetPoint("RIGHT", optionsPanel, -32, 0)
    subtitle:SetHeight(40)
    subtitle:SetJustifyH("LEFT")
    subtitle:SetJustifyV("TOP")
    subtitle:SetText("Automatically compare hovered items with your equipped gear. Hold Ctrl to suppress comparison on the current tooltip.")

    local checkbox = CreateFrame("CheckButton", "QuickCompareOptionsEnable", optionsPanel, "InterfaceOptionsCheckButtonTemplate")
    checkbox:SetPoint("TOPLEFT", subtitle, "BOTTOMLEFT", -2, -12)
    _G[checkbox:GetName() .. "Text"]:SetText("Enable automatic equipment comparison")
    checkbox:SetScript("OnClick", function(self)
        SetEnabled(self:GetChecked())
    end)

    optionsPanel:SetScript("OnShow", function()
        checkbox:SetChecked(IsEnabled())
    end)

    InterfaceOptions_AddCategory(optionsPanel)
end

local function InstallHooks()
    if hooksInstalled then
        return
    end

    GameTooltip:HookScript("OnTooltipSetItem", RefreshGameTooltipCompare)
    GameTooltip:HookScript("OnShow", RefreshGameTooltipCompare)
    GameTooltip:HookScript("OnHide", function()
        HideCompareTooltips("ShoppingTooltip")
    end)

    if ItemRefTooltip then
        ItemRefTooltip:HookScript("OnTooltipSetItem", RefreshItemRefCompare)
        ItemRefTooltip:HookScript("OnShow", RefreshItemRefCompare)
        ItemRefTooltip:HookScript("OnHide", function()
            HideCompareTooltips("ItemRefCompareTooltip")
        end)
    end

    hooksecurefunc("SetItemRef", RefreshItemRefCompare)

    hooksInstalled = true
end

local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("PLAYER_LOGIN")
eventFrame:SetScript("OnEvent", function()
    EnsureDB()
    CreateOptionsPanel()
    InstallHooks()

    SLASH_QUICKCOMPARE1 = "/quickcompare"
    SLASH_QUICKCOMPARE2 = "/qcompare"
    SlashCmdList["QUICKCOMPARE"] = function(msg)
        msg = string.lower((msg or ""))
        if msg == "toggle" then
            SetEnabled(not IsEnabled())
            DEFAULT_CHAT_FRAME:AddMessage("QuickCompare: " .. (IsEnabled() and "enabled" or "disabled"))
            return
        end

        OpenOptionsPanel()
    end
end)
