-- RareTruePortrait.lua - Portrait exclusivo para detección de raros
setfenv(1, VoiceOver)
RareTruePortrait = {
    rareQueue = {}, -- Cola de raros detectados
    currentIndex = 1, -- Índice actual en la cola
    lastActivityTime = 0, -- Última vez que hubo actividad (captura de rare)
    fadeTimer = nil, -- Timer para el desvanecimiento
    isFadedOut = false -- Estado de desvanecimiento
}

local FADE_TIMEOUT = 40 -- Segundos de inactividad antes de desvanecer

local FRAME_WIDTH = 740
local FRAME_HEIGHT = 370
local PORTRAIT_ATLAS_SIZE = 512

-- Configuración de posiciones por defecto (ajustadas para raros)
RareTruePortraitDefaults = {
    title = { x = 55, y = 22 },
    desc = { x = 94, y = -48 },
    icon = { x = -62, y = -6 },
    loot = { x = 88, y = -38 },
    pagination = { x = 202, y = -55 },
    model = { x = -229, y = 1, size = 136 }
}

-- Helper function to get the current atlas texture path
local function GetAtlasTexturePath()
    local atlasIndex = Addon.db.profile.SoundQueueUI.PortraitFrameAtlas or 0
    local atlasPath = [[Interface\AddOns\AI_VoiceOver\Textures\PortraitFrameAtlas]]
    if atlasIndex > 0 then
        atlasPath = atlasPath .. atlasIndex
    end
    return atlasPath
end

-- Función auxiliar para subcadena UTF-8 (para el efecto de máquina de escribir)
local function utf8sub(str, start, numChars)
    local startIndex = 1
    while start > 1 do
        local byte = string.byte(str, startIndex)
        if not byte then break end
        if byte < 128 then startIndex = startIndex + 1
        elseif byte < 224 then startIndex = startIndex + 2
        elseif byte < 240 then startIndex = startIndex + 3
        else startIndex = startIndex + 4 end
        start = start - 1
    end
    local currentIndex = startIndex
    while numChars > 0 do
        local byte = string.byte(str, currentIndex)
        if not byte then break end
        if byte < 128 then currentIndex = currentIndex + 1
        elseif byte < 224 then currentIndex = currentIndex + 2
        elseif byte < 240 then currentIndex = currentIndex + 3
        else currentIndex = currentIndex + 4 end
        numChars = numChars - 1
    end
    return string.sub(str, startIndex, currentIndex - 1)
end

function RareTruePortrait:Initialize()
    -- Crear el frame principal
    self.frame = CreateFrame("Frame", "VoiceOverRareTruePortrait", UIParent)
    self.frame:SetSize(FRAME_WIDTH, FRAME_HEIGHT)
    self.frame:SetPoint("CENTER", UIParent, "CENTER", 0, -150)
    self.frame:SetFrameStrata("HIGH")
    self.frame:SetFrameLevel(50)

    -- Imagen de fondo
    -- (Eliminado el fondo directo del frame principal para usar un overlay más adelante)

    -- Hacer arrastrable (siempre permitido para raros)
    self.frame:EnableMouse(true)
    self.frame:SetMovable(true)
    self.frame:RegisterForDrag("LeftButton")
    self.frame:SetScript("OnDragStart", function(f)
        f:StartMoving()
    end)
    self.frame:SetScript("OnDragStop", function(f)
        f:StopMovingOrSizing()
        -- Guardar posición
        local point, _, relPoint, x, y = f:GetPoint()
        Addon.db.profile.RareTruePortrait = Addon.db.profile.RareTruePortrait or {}
        Addon.db.profile.RareTruePortrait.position = {
            point = point,
            relPoint = relPoint,
            x = x,
            y = y
        }
    end)

    -- Clic derecho deshabilitado - solo se cierra con la X
    -- self.frame:SetScript("OnMouseDown", function(f, button)
    --     if button == "RightButton" then
    --         RareTruePortrait:Hide()
    --     end
    -- end)



    local defaults = RareTruePortraitDefaults

    -- TEXTO 1: Nombre del NPC (Movible con Shift)
    self.frame.titleFrame = CreateFrame("Frame", nil, self.frame)
    self.frame.titleFrame:SetSize(330, 60)
    self.frame.titleFrame:SetPoint("CENTER", self.frame, "CENTER", defaults.title.x, defaults.title.y)
    self.frame.titleFrame:SetFrameLevel(self.frame:GetFrameLevel() + 20)
    self.frame.titleFrame:EnableMouse(true)
    self.frame.titleFrame:SetMovable(true)
    self.frame.titleFrame:RegisterForDrag("LeftButton")
    self.frame.titleFrame:SetScript("OnDragStart", function(f)
        if IsShiftKeyDown() then f:StartMoving() end
    end)
    self.frame.titleFrame:SetScript("OnDragStop", function(f)
        f:StopMovingOrSizing()
        local parentX, parentY = self.frame:GetCenter()
        local selfX, selfY = f:GetCenter()
        local offsetX = math.floor(selfX - parentX)
        local offsetY = math.floor(selfY - parentY)
        Addon.db.profile.RareTruePortrait = Addon.db.profile.RareTruePortrait or {}
        Addon.db.profile.RareTruePortrait.titlePosition = { x = offsetX, y = offsetY }
    end)

    self.frame.title = self.frame.titleFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    self.frame.title:SetPoint("TOPLEFT", self.frame.titleFrame, "TOPLEFT", 0, 0)
    self.frame.title:SetWidth(450)
    self.frame.title:SetWordWrap(false)
    self.frame.title:SetJustifyH("LEFT")
    self.frame.title:SetJustifyV("TOP")
    self.frame.title:SetFont("Fonts\\FRIZQT__.TTF", 24, "OUTLINE")
    self.frame.title:SetTextColor(1, 1, 1) -- Blanco
    self.frame.title:SetText("Nombre del NPC")

    -- TEXTO 2: Título de la misión (Movible con Shift)
    self.frame.descFrame = CreateFrame("Frame", nil, self.frame)
    self.frame.descFrame:SetSize(350, 120)
    self.frame.descFrame:SetPoint("CENTER", self.frame, "CENTER", defaults.desc.x, defaults.desc.y)
    self.frame.descFrame:SetFrameLevel(self.frame:GetFrameLevel() + 20)
    self.frame.descFrame:EnableMouse(true)
    self.frame.descFrame:SetMovable(true)
    self.frame.descFrame:RegisterForDrag("LeftButton")
    self.frame.descFrame:SetScript("OnDragStart", function(f)
        if IsShiftKeyDown() then f:StartMoving() end
    end)
    self.frame.descFrame:SetScript("OnDragStop", function(f)
        f:StopMovingOrSizing()
        local parentX, parentY = self.frame:GetCenter()
        local selfX, selfY = f:GetCenter()
        local offsetX = math.floor(selfX - parentX)
        local offsetY = math.floor(selfY - parentY)
        Addon.db.profile.RareTruePortrait = Addon.db.profile.RareTruePortrait or {}
        Addon.db.profile.RareTruePortrait.descPosition = { x = offsetX, y = offsetY }
    end)

    self.frame.description = self.frame.descFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    self.frame.description:SetPoint("TOPLEFT", self.frame.descFrame, "TOPLEFT", 0, 0)
    self.frame.description:SetWidth(350)
    self.frame.description:SetWordWrap(true)
    self.frame.description:SetJustifyH("LEFT")
    self.frame.description:SetJustifyV("TOP")
    self.frame.description:SetFont("Fonts\\FRIZQT__.TTF", 16, "OUTLINE")
    self.frame.description:SetTextColor(1, 0.82, 0) -- Dorado
    self.frame.description:SetText("Título de la Misión")

    -- CONTENEDOR DE ICONOS DE LOOT (Movible con Shift)
    self.frame.lootFrame = CreateFrame("Frame", nil, self.frame)
    self.frame.lootFrame:SetSize(280, 50)
    self.frame.lootFrame:SetPoint("CENTER", self.frame, "CENTER", defaults.loot.x, defaults.loot.y)
    self.frame.lootFrame:SetFrameLevel(self.frame:GetFrameLevel() + 21)
    self.frame.lootFrame:EnableMouse(true)
    self.frame.lootFrame:SetMovable(true)
    self.frame.lootFrame:RegisterForDrag("LeftButton")
    self.frame.lootFrame:SetScript("OnDragStart", function(f)
        if IsShiftKeyDown() then f:StartMoving() end
    end)
    self.frame.lootFrame:SetScript("OnDragStop", function(f)
        f:StopMovingOrSizing()
        local parentX, parentY = self.frame:GetCenter()
        local selfX, selfY = f:GetCenter()
        local offsetX = math.floor(selfX - parentX)
        local offsetY = math.floor(selfY - parentY)
        Addon.db.profile.RareTruePortrait = Addon.db.profile.RareTruePortrait or {}
        Addon.db.profile.RareTruePortrait.lootPosition = { x = offsetX, y = offsetY }
    end)
    self.frame.lootFrame:Hide()
    self.frame.lootIcons = {}

    -- ICONO DE MISION (Movible con Shift)
    self.frame.iconFrame = CreateFrame("Frame", nil, self.frame)
    self.frame.iconFrame:SetSize(26, 26)
    self.frame.iconFrame:SetPoint("CENTER", self.frame, "CENTER", defaults.icon.x, defaults.icon.y)
    self.frame.iconFrame:SetFrameLevel(self.frame:GetFrameLevel() + 25)
    self.frame.iconFrame:EnableMouse(true)
    self.frame.iconFrame:SetMovable(true)
    self.frame.iconFrame:RegisterForDrag("LeftButton")
    self.frame.iconFrame:SetScript("OnDragStart", function(f)
        if IsShiftKeyDown() then f:StartMoving() end
    end)
    self.frame.iconFrame:SetScript("OnDragStop", function(f)
        f:StopMovingOrSizing()
        local parentX, parentY = self.frame:GetCenter()
        local selfX, selfY = f:GetCenter()
        local offsetX = math.floor(selfX - parentX)
        local offsetY = math.floor(selfY - parentY)
        Addon.db.profile.RareTruePortrait = Addon.db.profile.RareTruePortrait or {}
        Addon.db.profile.RareTruePortrait.iconPosition = { x = offsetX, y = offsetY }
    end)

    self.frame.questIcon = self.frame.iconFrame:CreateTexture(nil, "OVERLAY")
    self.frame.questIcon:SetTexture("Interface\\AddOns\\AI_VoiceOver\\Textures\\quest-campaign-available.blp")
    self.frame.questIcon:SetAllPoints(self.frame.iconFrame)

    -- LOGO (Fijo)
    self.frame.logoFrame = CreateFrame("Frame", nil, self.frame)
    self.frame.logoFrame:SetSize(126, 126)
    self.frame.logoFrame:SetPoint("CENTER", self.frame, "CENTER", -234, -71)
    self.frame.logoFrame:SetFrameLevel(self.frame:GetFrameLevel() + 20)

    self.frame.logo = self.frame.logoFrame:CreateTexture(nil, "OVERLAY")
    self.frame.logo:SetTexture("Interface\\AddOns\\AI_VoiceOver\\Textures\\LOGO.blp")
    self.frame.logo:SetAllPoints(self.frame.logoFrame)

    -- FONDO FIJO (CAPA MÁS BAJA)
    self.frame.bgFrame = CreateFrame("Frame", nil, self.frame)
    self.frame.bgFrame:SetSize(150, 150)
    self.frame.bgFrame:SetPoint("CENTER", self.frame, "CENTER", -229, 0)
    self.frame.bgFrame:SetFrameLevel(self.frame:GetFrameLevel() + 1)

    self.frame.modelBackground = self.frame.bgFrame:CreateTexture(nil, "BACKGROUND")
    self.frame.modelBackground:SetTexture("Interface\\AddOns\\AI_VoiceOver\\Textures\\PortraitFrameBackground1")
    self.frame.modelBackground:SetAllPoints(self.frame.bgFrame)

    -- MODELO 3D (Arrastrable)
    self.frame.modelFrame = CreateFrame("Frame", nil, self.frame)
    self.frame.modelFrame:SetSize(defaults.model.size, defaults.model.size)
    self.frame.modelFrame:SetPoint("CENTER", self.frame, "CENTER", defaults.model.x, defaults.model.y)
    self.frame.modelFrame:SetFrameLevel(self.frame:GetFrameLevel() + 5)
    self.frame.modelFrame:EnableMouse(true)
    self.frame.modelFrame:SetMovable(true)
    self.frame.modelFrame:RegisterForDrag("LeftButton")

    -- Crear el modelo 3D
    self.frame.model = CreateFrame("DressUpModel", nil, self.frame.modelFrame)
    self.frame.model:SetAllPoints(self.frame.modelFrame)
    self.frame.model:SetCreature(15608)
    self.frame.model:SetCustomCamera(0)

    -- OnUpdate para cámaras Y animaciones (usa ModelCameraConfig de SoundQueueUI)
    self.frame.model:HookScript("OnUpdate", function(model, elapsed)
        local modelID = model:GetModelFileID()
        if not modelID then return end

        -- Aplicar cámaras usando la configuración global
        if tContains(ModelCameraConfig.uniqueModelIDs, modelID) then
            model:SetCustomCamera(1)
            model:SetRotation(0.5)
            model:SetCameraDistance(1.10)
            model:SetCameraFacing(0)
        elseif tContains(ModelCameraConfig.specialModelIDs, modelID) then
            model:SetCustomCamera(1)
            model:SetPosition(0, -0.2, -0.1)
            model:SetScale(0.85)
            model:SetRotation(0.5)
        elseif tContains(ModelCameraConfig.fullBodyModelIDs, modelID) then
            model:SetCustomCamera(1)
            model:SetPosition(0, 0, -0.6)
            model:SetCameraDistance(0.6)
            model:SetRotation(0.5)
        else
            model:SetCustomCamera(0)
        end

        -- Animación idle para raros (sin hablar)
        if not model.animSet then
            model:SetAnimation(0) -- Stand/idle
            model.animSet = true
        end
    end)

    -- MARCO CINEMATICO (ENCIMA DEL MODELO)
    self.frame.overlayFrame = CreateFrame("Frame", nil, self.frame)
    self.frame.overlayFrame:SetAllPoints(self.frame)
    self.frame.overlayFrame:SetFrameLevel(self.frame:GetFrameLevel() + 10)
    self.frame.overlayFrame:EnableMouse(false) -- Ignorar clicks para que pasen al modelo

    self.frame.background = self.frame.overlayFrame:CreateTexture(nil, "OVERLAY")
    self.frame.background:SetTexture("Interface\\AddOns\\AI_VoiceOver\\Textures\\RETRATONUEVO.blp")
    self.frame.background:SetAllPoints(self.frame.overlayFrame)

    -- Arrastrar el modelFrame
    self.frame.modelFrame:SetScript("OnDragStart", function(f)
        f:StartMoving()
    end)
    self.frame.modelFrame:SetScript("OnDragStop", function(f)
        f:StopMovingOrSizing()
        local parentX, parentY = self.frame:GetCenter()
        local selfX, selfY = f:GetCenter()
        local offsetX = selfX - parentX
        local offsetY = selfY - parentY
        Addon.db.profile.RareTruePortrait = Addon.db.profile.RareTruePortrait or {}
        Addon.db.profile.RareTruePortrait.modelPosition = { x = offsetX, y = offsetY }
    end)

    -- (Botón de pausa eliminado - no necesario para raros)

    -- BOTON DE CIERRE (X) - Fijo
    self.frame.closeButton = CreateFrame("Button", nil, self.frame)
    self.frame.closeButton:SetSize(40, 40)
    self.frame.closeButton:SetPoint("CENTER", self.frame, "CENTER", 243, 60)
    self.frame.closeButton:SetFrameLevel(self.frame:GetFrameLevel() + 35)

    self.frame.closeButton:SetNormalTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Up")
    self.frame.closeButton:SetPushedTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Down")
    self.frame.closeButton:SetHighlightTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Highlight", "ADD")

    self.frame.closeButton:SetScript("OnClick", function()
        PlaySound(SOUNDKIT.U_CHAT_SCROLL_BUTTON)
        RareTruePortrait:Hide()
    end)

    -- BOTÓN "VER RARE PORTÁTIL" - Aparece cuando el frame está desvanecido
    self.showButton = CreateFrame("Button", "VoiceOverRareShowButton", UIParent)
    self.showButton:SetSize(120, 28)
    self.showButton:SetPoint("BOTTOM", UIParent, "BOTTOM", 0, 100)
    self.showButton:SetFrameStrata("HIGH")
    self.showButton:SetFrameLevel(100)
    self.showButton:EnableMouse(true)
    self.showButton:SetMovable(true)
    self.showButton:RegisterForDrag("LeftButton")
    self.showButton:SetClampedToScreen(true)

    -- Fondo del botón
    self.showButton.bg = self.showButton:CreateTexture(nil, "BACKGROUND")
    self.showButton.bg:SetAllPoints()
    self.showButton.bg:SetColorTexture(0.1, 0.1, 0.1, 0.9)

    -- Borde del botón
    self.showButton.border = CreateFrame("Frame", nil, self.showButton, "BackdropTemplate")
    self.showButton.border:SetAllPoints()
    self.showButton.border:SetBackdrop({
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        edgeSize = 12,
    })
    self.showButton.border:SetBackdropBorderColor(0.6, 0.4, 0.1, 1)

    -- Texto del botón
    self.showButton.text = self.showButton:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    self.showButton.text:SetPoint("CENTER", 0, 0)
    self.showButton.text:SetText("|cFFFFD100Show Rare Panel|r")

    -- Contador de raros pendientes
    self.showButton.countBadge = self.showButton:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    self.showButton.countBadge:SetPoint("TOPRIGHT", self.showButton, "TOPRIGHT", 5, 5)
    self.showButton.countBadge:SetFont("Fonts\\FRIZQT__.TTF", 10, "OUTLINE")
    self.showButton.countBadge:SetTextColor(1, 0.3, 0.3)
    self.showButton.countBadge:SetText("")

    -- Highlight al pasar mouse
    self.showButton:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight", "ADD")

    -- Arrastrar el botón
    self.showButton:SetScript("OnDragStart", function(f)
        f:StartMoving()
    end)
    self.showButton:SetScript("OnDragStop", function(f)
        f:StopMovingOrSizing()
        local point, _, relPoint, x, y = f:GetPoint()
        Addon.db.profile.RareTruePortrait = Addon.db.profile.RareTruePortrait or {}
        Addon.db.profile.RareTruePortrait.showButtonPosition = {
            point = point,
            relPoint = relPoint,
            x = x,
            y = y
        }
    end)

    -- Click para mostrar el frame de raros
    self.showButton:SetScript("OnClick", function()
        PlaySound(SOUNDKIT.IG_QUEST_LOG_OPEN)
        RareTruePortrait:ShowFromButton()
    end)

    -- Tooltip
    self.showButton:SetScript("OnEnter", function(btn)
        GameTooltip:SetOwner(btn, "ANCHOR_TOP")
        GameTooltip:SetText("Detected Rares", 1, 0.82, 0)
        GameTooltip:AddLine("Click to show the rare panel", 1, 1, 1)
        GameTooltip:AddLine("Drag to move this button", 0.5, 0.5, 0.5)
        GameTooltip:AddLine(" ")
        GameTooltip:AddLine("To disable Rare Announce, go to", 0.7, 0.7, 0.7)
        GameTooltip:AddLine("VoiceOver Options > Rare Announce", 0.7, 0.7, 0.7)
        GameTooltip:Show()
    end)
    self.showButton:SetScript("OnLeave", function()
        GameTooltip:Hide()
    end)

    -- Ocultar por defecto
    self.showButton:Hide()

    -- Restaurar posición del botón si existe
    if Addon.db.profile.RareTruePortrait and Addon.db.profile.RareTruePortrait.showButtonPosition then
        local pos = Addon.db.profile.RareTruePortrait.showButtonPosition
        self.showButton:ClearAllPoints()
        self.showButton:SetPoint(pos.point, UIParent, pos.relPoint, pos.x, pos.y)
    end

    -- BOTÓN DE TARGET (encima del paginador)
    self.frame.targetButton = CreateFrame("Button", "VoiceOverRareTargetButton", self.frame, "SecureActionButtonTemplate")
    self.frame.targetButton:SetSize(80, 20)
    self.frame.targetButton:SetPoint("CENTER", self.frame, "CENTER", defaults.pagination.x, defaults.pagination.y + 25)
    self.frame.targetButton:SetFrameStrata("HIGH") -- Mismo nivel que el frame principal
    self.frame.targetButton:SetFrameLevel(self.frame:GetFrameLevel() + 40)
    self.frame.targetButton:EnableMouse(true)
    self.frame.targetButton:RegisterForClicks("AnyUp", "AnyDown")
    self.frame.targetButton:SetAttribute("type", "macro")

    -- Fondo del botón
    self.frame.targetButton.bg = self.frame.targetButton:CreateTexture(nil, "BACKGROUND")
    self.frame.targetButton.bg:SetAllPoints()
    self.frame.targetButton.bg:SetColorTexture(0.2, 0.2, 0.2, 0.8)

    -- Texto del botón
    self.frame.targetButton.text = self.frame.targetButton:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    self.frame.targetButton.text:SetPoint("CENTER", 0, 0)
    self.frame.targetButton.text:SetText("Seleccionar")
    self.frame.targetButton.text:SetTextColor(1, 0.82, 0)

    -- Highlight al pasar mouse
    self.frame.targetButton:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight", "ADD")

    -- Tooltip
    self.frame.targetButton:SetScript("OnEnter", function(btn)
        GameTooltip:SetOwner(btn, "ANCHOR_TOP")
        GameTooltip:SetText("Clic para seleccionar este objetivo", 1, 1, 1)
        GameTooltip:Show()
    end)
    self.frame.targetButton:SetScript("OnLeave", function()
        GameTooltip:Hide()
    end)

    -- Callback para verificar clicks (debug removido)

    -- CONTADOR Y BOTONES DE NAVEGACIÓN (Esquina inferior derecha)
    -- Frame contenedor para la paginación (arrastrable con Shift)
    self.frame.paginationFrame = CreateFrame("Frame", nil, self.frame)
    self.frame.paginationFrame:SetSize(80, 30)
    self.frame.paginationFrame:SetPoint("CENTER", self.frame, "CENTER", defaults.pagination.x, defaults.pagination.y)
    self.frame.paginationFrame:SetFrameLevel(self.frame:GetFrameLevel() + 35)
    self.frame.paginationFrame:EnableMouse(true)
    self.frame.paginationFrame:SetMovable(true)
    self.frame.paginationFrame:RegisterForDrag("LeftButton")

    -- Arrastrar solo con Shift
    self.frame.paginationFrame:SetScript("OnDragStart", function(f)
        if IsShiftKeyDown() then
            f:StartMoving()
        end
    end)

    self.frame.paginationFrame:SetScript("OnDragStop", function(f)
        f:StopMovingOrSizing()
        local parentX, parentY = self.frame:GetCenter()
        local selfX, selfY = f:GetCenter()
        local offsetX = math.floor(selfX - parentX)
        local offsetY = math.floor(selfY - parentY)
        Addon.db.profile.RareTruePortrait = Addon.db.profile.RareTruePortrait or {}
        Addon.db.profile.RareTruePortrait.paginationPosition = { x = offsetX, y = offsetY }
    end)

    -- Botón anterior (<)
    self.frame.prevButton = CreateFrame("Button", nil, self.frame.paginationFrame)
    self.frame.prevButton:SetSize(22, 22)
    self.frame.prevButton:SetPoint("LEFT", self.frame.paginationFrame, "LEFT", 0, 0)
    self.frame.prevButton:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-PrevPage-Up")
    self.frame.prevButton:SetPushedTexture("Interface\\Buttons\\UI-SpellbookIcon-PrevPage-Down")
    self.frame.prevButton:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight", "ADD")
    self.frame.prevButton:SetScript("OnClick", function()
        PlaySound(SOUNDKIT.IG_QUEST_LOG_OPEN)
        RareTruePortrait:NavigatePrevious()
    end)

    -- Contador (1/3)
    self.frame.counter = self.frame.paginationFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    self.frame.counter:SetPoint("CENTER", self.frame.paginationFrame, "CENTER", 0, 0)
    self.frame.counter:SetFont("Fonts\\FRIZQT__.TTF", 10, "OUTLINE")
    self.frame.counter:SetTextColor(1, 1, 1)
    self.frame.counter:SetText("1/1")

    -- Botón siguiente (>)
    self.frame.nextButton = CreateFrame("Button", nil, self.frame.paginationFrame)
    self.frame.nextButton:SetSize(22, 22)
    self.frame.nextButton:SetPoint("RIGHT", self.frame.paginationFrame, "RIGHT", 0, 0)
    self.frame.nextButton:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up")
    self.frame.nextButton:SetPushedTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Down")
    self.frame.nextButton:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight", "ADD")
    self.frame.nextButton:SetScript("OnClick", function()
        PlaySound(SOUNDKIT.IG_QUEST_LOG_OPEN)
        RareTruePortrait:NavigateNext()
    end)

    -- SCRIPT DE ACTUALIZACIÓN PARA EL EFECTO DE MÁQUINA DE ESCRIBIR
    self.frame:SetScript("OnUpdate", function(f, elapsed)
        if f.targetTitle and f.charIndexTitle < strlenutf8(f.targetTitle) then
            f.nextCharTimer = (f.nextCharTimer or 0) + elapsed
            -- Velocidad para el nombre del NPC (un poco más lento)
            if f.nextCharTimer >= 0.05 then
                f.nextCharTimer = 0
                f.charIndexTitle = f.charIndexTitle + 1
                f.title:SetText(utf8sub(f.targetTitle, 1, f.charIndexTitle))
            end
        elseif f.targetDesc and f.charIndexDesc < strlenutf8(f.targetDesc) then
            f.nextCharTimer = (f.nextCharTimer or 0) + elapsed
            -- Velocidad para el título de la misión (un poco más rápido)
            if f.nextCharTimer >= 0.03 then
                f.nextCharTimer = 0
                f.charIndexDesc = f.charIndexDesc + 1
                f.description:SetText(utf8sub(f.targetDesc, 1, f.charIndexDesc))
            end
        end
    end)

    -- Ocultar por defecto
    self.frame:Hide()

    -- Restaurar posición guardada
    self:RestorePosition()
    self:RestoreModelPosition()

    -- Aplicar escala guardada
    if Addon.db.profile.RareTruePortrait and Addon.db.profile.RareTruePortrait.frameScale then
        self.frame:SetScale(Addon.db.profile.RareTruePortrait.frameScale)
    end

    -- Aplicar estado del logo (visible por defecto)
    if Addon.db.profile.RareTruePortrait and Addon.db.profile.RareTruePortrait.showLogo == false then
        if self.frame.logoFrame then
            self.frame.logoFrame:Hide()
        end
    end
end

function RareTruePortrait:RestoreModelPosition()
    if not self.frame then return end

    if Addon.db and Addon.db.profile and Addon.db.profile.RareTruePortrait then
        local config = Addon.db.profile.RareTruePortrait

        -- Restaurar posición del modelo
        if self.frame.modelFrame and config.modelPosition then
            self.frame.modelFrame:ClearAllPoints()
            self.frame.modelFrame:SetPoint("CENTER", self.frame, "CENTER", config.modelPosition.x, config.modelPosition.y)
        end

        -- Restaurar tamaño del modelo
        if self.frame.modelFrame and config.modelSize then
            self.frame.modelFrame:SetSize(config.modelSize, config.modelSize)
        end

        -- Restaurar posición del título (NPC name)
        if self.frame.titleFrame and config.titlePosition then
            self.frame.titleFrame:ClearAllPoints()
            self.frame.titleFrame:SetPoint("CENTER", self.frame, "CENTER", config.titlePosition.x, config.titlePosition.y)
        end

        -- Restaurar posición de la descripción (quest title)
        if self.frame.descFrame and config.descPosition then
            self.frame.descFrame:ClearAllPoints()
            self.frame.descFrame:SetPoint("CENTER", self.frame, "CENTER", config.descPosition.x, config.descPosition.y)
        end

        -- Restaurar posición del icono
        if self.frame.iconFrame and config.iconPosition then
            self.frame.iconFrame:ClearAllPoints()
            self.frame.iconFrame:SetPoint("CENTER", self.frame, "CENTER", config.iconPosition.x, config.iconPosition.y)
        end

        -- Restaurar posición del logo
        if self.frame.logoFrame and config.logoPosition then
            self.frame.logoFrame:ClearAllPoints()
            self.frame.logoFrame:SetPoint("CENTER", self.frame, "CENTER", config.logoPosition.x, config.logoPosition.y)
        end

        -- Restaurar posición del fondo
        if self.frame.bgFrame and config.bgPosition then
            self.frame.bgFrame:ClearAllPoints()
            self.frame.bgFrame:SetPoint("CENTER", self.frame, "CENTER", config.bgPosition.x, config.bgPosition.y)
        end

        -- Restaurar tamaño del fondo
        if self.frame.bgFrame and config.bgSize then
            self.frame.bgFrame:SetSize(config.bgSize, config.bgSize)
        end

        -- Restaurar posición del loot
        if self.frame.lootFrame and config.lootPosition then
            self.frame.lootFrame:ClearAllPoints()
            self.frame.lootFrame:SetPoint("CENTER", self.frame, "CENTER", config.lootPosition.x, config.lootPosition.y)
        end

        -- Restaurar posición de la paginación
        if self.frame.paginationFrame and config.paginationPosition then
            self.frame.paginationFrame:ClearAllPoints()
            self.frame.paginationFrame:SetPoint("CENTER", self.frame, "CENTER", config.paginationPosition.x, config.paginationPosition.y)
        end
    end
end

function RareTruePortrait:RestorePosition()
    if Addon.db and Addon.db.profile and Addon.db.profile.RareTruePortrait and Addon.db.profile.RareTruePortrait.position then
        local pos = Addon.db.profile.RareTruePortrait.position
        self.frame:ClearAllPoints()
        self.frame:SetPoint(pos.point, UIParent, pos.relPoint, pos.x, pos.y)
    end
end

function RareTruePortrait:Show(soundData)
    if not self.frame then
        self:Initialize()
    end

    if soundData then
        -- Añadir el nuevo raro a la cola
        table.insert(self.rareQueue, soundData)

        -- Actualizar tiempo de actividad y reiniciar timer de desvanecimiento
        self:ResetFadeTimer()

        -- Si ya está reproduciendo algo, actualizar la visualización al nuevo raro
        if self.isPlaying then
            self.currentIndex = #self.rareQueue
            self:UpdateDisplay()
            self:UpdateShowButtonCount()
            return
        end

        -- Verificar si AlternativePortrait está activo
        if AlternativePortrait and AlternativePortrait:IsShown() then
            -- Marcar que hay un raro pendiente y retornar
            self.pendingShow = true
            return
        end

        -- Si estaba desvanecido, mostrar de nuevo
        if self.isFadedOut then
            self.isFadedOut = false
            if self.showButton then
                self.showButton:Hide()
            end
        end

        -- Reproducir el primer raro de la cola
        self:PlayNextInQueue()
    end

    self.frame:Show()
end

-- Reiniciar el timer de desvanecimiento
function RareTruePortrait:ResetFadeTimer()
    self.lastActivityTime = GetTime()
    self.isFadedOut = false

    -- Cancelar timer anterior si existe
    if self.fadeTimer then
        self.fadeTimer:Cancel()
        self.fadeTimer = nil
    end

    -- Iniciar nuevo timer
    self.fadeTimer = C_Timer.NewTimer(FADE_TIMEOUT, function()
        RareTruePortrait:FadeOut()
    end)
end

-- Desvanecer el frame y mostrar el botón
function RareTruePortrait:FadeOut()
    if not self.frame or not self.frame:IsShown() then
        return
    end

    -- Solo desvanecer si no hay reproducción activa
    if self.isPlaying then
        -- Reintentar más tarde
        self.fadeTimer = C_Timer.NewTimer(5, function()
            RareTruePortrait:FadeOut()
        end)
        return
    end

    self.isFadedOut = true

    -- Ocultar el frame principal
    self.frame:Hide()

    -- Mostrar el botón "Ver Rare Portátil" si hay raros en la cola
    if #self.rareQueue > 0 and self.showButton then
        self:UpdateShowButtonCount()
        self.showButton:Show()
    end
end

-- Actualizar el contador en el botón
function RareTruePortrait:UpdateShowButtonCount()
    if self.showButton and self.showButton.countBadge then
        local count = #self.rareQueue
        if count > 0 then
            self.showButton.countBadge:SetText("(" .. count .. ")")
        else
            self.showButton.countBadge:SetText("")
        end
    end
end

-- Mostrar desde el botón (sin reiniciar la cola)
function RareTruePortrait:ShowFromButton()
    if not self.frame then
        self:Initialize()
    end

    self.isFadedOut = false

    -- Ocultar el botón
    if self.showButton then
        self.showButton:Hide()
    end

    -- Reiniciar el timer de desvanecimiento
    self:ResetFadeTimer()

    -- Mostrar el frame
    self.frame:Show()

    -- Actualizar la visualización con el índice actual
    if #self.rareQueue > 0 then
        self:UpdateDisplay()
    end
end

-- Reproducir el siguiente raro en la cola
function RareTruePortrait:PlayNextInQueue()
    if #self.rareQueue == 0 then
        self.isPlaying = false
        -- Iniciar timer de desvanecimiento al terminar la cola
        self:ResetFadeTimer()
        return
    end

    -- Buscar el siguiente raro no reproducido
    local nextIndex = nil
    for i, data in ipairs(self.rareQueue) do
        if not data.played then
            nextIndex = i
            break
        end
    end

    if not nextIndex then
        -- Todos los raros ya fueron reproducidos
        self.isPlaying = false
        -- Iniciar timer de desvanecimiento cuando todos los raros terminaron
        self:ResetFadeTimer()
        return
    end

    self.isPlaying = true
    self.currentIndex = nextIndex

    -- Reiniciar el timer de desvanecimiento (hubo actividad)
    self:ResetFadeTimer()

    -- Actualizar la visualización
    self:UpdateDisplay()

    -- Reproducir el sonido
    local soundData = self.rareQueue[self.currentIndex]
    if soundData and soundData.filePath then
        Utils:PlaySound(soundData)
        soundData.played = true

        -- Programar la reproducción del siguiente cuando termine este
        local duration = (soundData.length or 5) + 1
        C_Timer.After(duration, function()
            self:PlayNextInQueue()
        end)
    else
        -- Si no hay sonido, pasar al siguiente inmediatamente
        self:PlayNextInQueue()
    end

    -- Mostrar el frame
    if self.frame then
        self.frame:Show()
    end
end

-- Callback llamado cuando AlternativePortrait se oculta
function RareTruePortrait:OnAlternativePortraitHidden()
    -- Si hay un raro pendiente de mostrar
    if self.pendingShow and #self.rareQueue > 0 then
        self.pendingShow = false

        -- Iniciar la reproducción de la cola
        self:PlayNextInQueue()
    end
end

function RareTruePortrait:Hide()
    -- Limpiar estados de reproducción
    self.pendingShow = false
    self.isPlaying = false

    -- Cancelar timer de desvanecimiento
    if self.fadeTimer then
        self.fadeTimer:Cancel()
        self.fadeTimer = nil
    end

    -- Ocultar el frame principal
    if self.frame then
        self.frame:Hide()
    end

    -- Mostrar el botón flotante si hay raros en la cola
    if #self.rareQueue > 0 and self.showButton then
        self.isFadedOut = true
        self:UpdateShowButtonCount()
        self.showButton:Show()
    else
        self.isFadedOut = false
        if self.showButton then
            self.showButton:Hide()
        end
    end
end

-- Cerrar completamente (limpia todo, incluyendo la cola)
function RareTruePortrait:HideCompletely()
    self.pendingShow = false
    self.isPlaying = false
    self.isFadedOut = false

    if self.fadeTimer then
        self.fadeTimer:Cancel()
        self.fadeTimer = nil
    end

    -- Limpiar la cola
    self.rareQueue = {}
    self.currentIndex = 1

    if self.frame then
        self.frame:Hide()
    end

    if self.showButton then
        self.showButton:Hide()
    end
end

function RareTruePortrait:IsShown()
    return self.frame and self.frame:IsShown()
end

-- Navegar al raro anterior
function RareTruePortrait:NavigatePrevious()
    if #self.rareQueue == 0 then return end

    self.currentIndex = self.currentIndex - 1
    if self.currentIndex < 1 then
        self.currentIndex = #self.rareQueue
    end

    self:UpdateDisplay()
end

-- Navegar al raro siguiente
function RareTruePortrait:NavigateNext()
    if #self.rareQueue == 0 then return end

    self.currentIndex = self.currentIndex + 1
    if self.currentIndex > #self.rareQueue then
        self.currentIndex = 1
    end

    self:UpdateDisplay()
end

-- Actualizar la visualización con el raro actual
function RareTruePortrait:UpdateDisplay()
    if #self.rareQueue == 0 then return end

    local soundData = self.rareQueue[self.currentIndex]
    if soundData then
        self:Update(soundData)

        -- Actualizar contador
        if self.frame and self.frame.counter then
            self.frame.counter:SetText(self.currentIndex .. "/" .. #self.rareQueue)
        end
    end
end

-- Actualizar con datos del soundData actual
function RareTruePortrait:Update(soundData)
    if not soundData then return end

    -- Guardar el nombre para poder hacer /tar al clickear el botón
    self.currentTargetName = soundData.name

    -- Mostrar/ocultar botón de target según si es GameObject o Creature
    if self.frame.targetButton then
        if soundData.isGameObject then
            -- GameObjects no se pueden targetear
            self.frame.targetButton:Hide()
        else
            -- Criaturas sí se pueden targetear
            self.frame.targetButton:Show()
            if soundData.name then
                local macroText = "/tar " .. soundData.name
                self.frame.targetButton:SetAttribute("macrotext", macroText)
            end
        end
    end

    -- Inicializar el efecto de máquina de escribir (título limitado a 29 caracteres)
    local rawTitle = soundData.name or ""
    if strlenutf8(rawTitle) > 29 then
        rawTitle = utf8sub(rawTitle, 1, 29) .. "..."
    end
    self.frame.targetTitle = rawTitle
    self.frame.targetDesc = soundData.title or ""
    self.frame.charIndexTitle = 0
    self.frame.charIndexDesc = 0
    self.frame.nextCharTimer = 0

    self.frame.title:SetText("")
    self.frame.description:SetText("")

    -- Limpiar y ocultar iconos de loot anteriores
    if self.frame.lootFrame then
        self.frame.lootFrame:Hide()
        for _, icon in ipairs(self.frame.lootIcons) do
            icon:Hide()
        end
    end

    -- Mostrar iconos de loot si es un rare con lootItems
    if soundData.lootItems and #soundData.lootItems > 0 then
        self:UpdateLootIcons(soundData.lootItems)
    end

    -- Actualizar el icono de misión según el evento
    if Enums.SoundEvent:IsQuestEvent(soundData.event) then
        self.frame.iconFrame:Show()
        if soundData.event == Enums.SoundEvent.QuestComplete then
            self.frame.questIcon:SetTexture("Interface\\AddOns\\AI_VoiceOver\\Textures\\quest-campaign-turnin.blp")
        else
            self.frame.questIcon:SetTexture("Interface\\AddOns\\AI_VoiceOver\\Textures\\quest-campaign-available.blp")
        end
    else
        self.frame.iconFrame:Hide()
    end

    -- Actualizar modelo 3D o Icono
    if self.frame.model then
        local model = self.frame.model

        -- Si hay iconID, mostrar textura en lugar de modelo 3D
        if soundData.iconID then
            model:Hide()
            if not self.frame.iconTexture then
                self.frame.iconTexture = self.frame.modelFrame:CreateTexture(nil, "ARTWORK")
                self.frame.iconTexture:SetAllPoints()
                self.frame.iconTexture:SetTexCoord(0.08, 0.92, 0.08, 0.92) -- Zoom ligero para quitar bordes
            end
            self.frame.iconTexture:SetTexture(soundData.iconID)
            self.frame.iconTexture:Show()
        else
            if self.frame.iconTexture then
                self.frame.iconTexture:Hide()
            end
            model:Show()

            local modelSource = "desconocido"
            if soundData.displayID then
                model:SetDisplayInfo(soundData.displayID)
                modelSource = "displayID: " .. soundData.displayID
            elseif soundData.creatureID then
                model:SetCreature(soundData.creatureID)
                modelSource = "creatureID: " .. soundData.creatureID
            elseif soundData.unitGUID then
                local creatureID = Utils:GetIDFromGUID(soundData.unitGUID)
                if creatureID then
                    model:SetCreature(creatureID)
                    modelSource = "unitGUID -> creatureID: " .. creatureID
                end
            elseif soundData.id then
                model:SetCreature(soundData.id)
                modelSource = "id: " .. soundData.id
            else
                model:SetCreature(15608) -- Libro por defecto
            end
        end

        -- La configuración de cámara se maneja en el OnUpdate del modelo
        -- Resetear flag para que OnUpdate aplique idle
        model.animSet = false
    end
end

-- Función para crear/actualizar iconos de loot
function RareTruePortrait:UpdateLootIcons(lootItems)
    if not self.frame or not self.frame.lootFrame then return end

    local ICON_SIZE = 36
    local ICON_SPACING = 12 -- Más espacio entre iconos
    local MAX_ICONS_PER_ROW = 5 -- Menos iconos por fila por el espacio extra
    local self = self -- Capturar self para el callback

    -- Ocultar iconos existentes
    for _, icon in ipairs(self.frame.lootIcons) do
        icon:Hide()
    end

    -- Pre-cargar todos los items y luego procesar
    local itemsLoaded = 0
    local totalItems = #lootItems

    local function OnAllItemsLoaded()
        -- Separar items buenos de basura (calidad 0 = gris, calidad 1 = blanco)
        local goodItems = {}
        local trashItems = {} -- Lista de items basura con sus datos
        local trashTotalGold = 0

        for _, itemID in ipairs(lootItems) do
            local itemName, _, itemRarity, _, _, _, _, _, _, _, sellPrice = GetItemInfo(itemID)

            -- Basura = calidad 0 (gris) o calidad 1 (blanco)
            if itemRarity and itemRarity <= 1 then
                -- Item basura - guardar datos completos
                table.insert(trashItems, {
                    itemID = itemID,
                    name = itemName or "Item",
                    sellPrice = sellPrice or 0
                })
                trashTotalGold = trashTotalGold + (sellPrice or 0)
            else
                -- Item bueno (verde o mejor)
                table.insert(goodItems, itemID)
            end
        end

        -- Lista final de items a mostrar
        local displayItems = {}
        for _, itemID in ipairs(goodItems) do
            table.insert(displayItems, {itemID = itemID, isTrash = false})
        end

        -- Agregar icono de basura consolidado si hay items basura
        if #trashItems > 0 then
            -- Usar el icono del primer item basura
            local firstTrashIcon = trashItems[1].itemID
            table.insert(displayItems, {
                itemID = firstTrashIcon,
                isTrash = true,
                trashCount = #trashItems,
                trashGold = trashTotalGold,
                trashItems = trashItems -- Lista completa para el tooltip
            })
        end

        -- Llamar a la función que dibuja los iconos
        RareTruePortrait:DrawLootIcons(displayItems, ICON_SIZE, ICON_SPACING, MAX_ICONS_PER_ROW)
    end

    -- Cargar cada item
    for _, itemID in ipairs(lootItems) do
        local item = Item:CreateFromItemID(itemID)
        item:ContinueOnItemLoad(function()
            itemsLoaded = itemsLoaded + 1
            if itemsLoaded >= totalItems then
                OnAllItemsLoaded()
            end
        end)
    end

    -- Si no hay items, no hacer nada
    if totalItems == 0 then
        return
    end
end

-- Función auxiliar para dibujar los iconos de loot
function RareTruePortrait:DrawLootIcons(displayItems, ICON_SIZE, ICON_SPACING, MAX_ICONS_PER_ROW)
    if not self.frame or not self.frame.lootFrame then return end

    -- Crear/actualizar iconos
    for i, itemData in ipairs(displayItems) do
        local icon = self.frame.lootIcons[i]
        local itemID = itemData.itemID

        if not icon then
            -- Crear nuevo icono
            icon = CreateFrame("Button", nil, self.frame.lootFrame)
            icon:SetSize(ICON_SIZE, ICON_SIZE)
            icon:SetFrameLevel(self.frame.lootFrame:GetFrameLevel() + 1)

            icon.texture = icon:CreateTexture(nil, "ARTWORK")
            icon.texture:SetAllPoints()
            icon.texture:SetTexCoord(0.08, 0.92, 0.08, 0.92) -- Quitar bordes

            -- Borde del icono
            icon.border = icon:CreateTexture(nil, "OVERLAY")
            icon.border:SetPoint("TOPLEFT", icon, "TOPLEFT", -16, 16)
            icon.border:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", 16, -16)
            icon.border:SetTexture("Interface\\Buttons\\UI-ActionButton-Border")
            icon.border:SetBlendMode("ADD")
            icon.border:SetAlpha(0.8)

            -- Glow para items épicos
            icon.glow = icon:CreateTexture(nil, "BACKGROUND")
            icon.glow:SetPoint("TOPLEFT", icon, "TOPLEFT", -20, 20)
            icon.glow:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", 20, -20)
            icon.glow:SetTexture("Interface\\SpellActivationOverlay\\IconAlert")
            icon.glow:SetTexCoord(0.00781250, 0.50781250, 0.27734375, 0.52734375)
            icon.glow:SetBlendMode("ADD")
            icon.glow:SetAlpha(0)
            icon.glow:Hide()

            -- Texto de cantidad (esquina superior derecha)
            icon.countText = icon:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
            icon.countText:SetPoint("TOPRIGHT", icon, "TOPRIGHT", 2, 2)
            icon.countText:SetFont("Fonts\\FRIZQT__.TTF", 12, "OUTLINE")
            icon.countText:SetTextColor(1, 1, 1)
            icon.countText:Hide()

            -- Texto de precio (debajo del icono)
            icon.priceText = icon:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
            icon.priceText:SetPoint("BOTTOM", icon, "BOTTOM", 0, -12)
            icon.priceText:SetFont("Fonts\\FRIZQT__.TTF", 10, "OUTLINE")
            icon.priceText:SetTextColor(1, 1, 1)
            icon.priceText:Hide()

            -- Texto de tipo de item (para épicos, debajo del icono)
            icon.slotText = icon:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
            icon.slotText:SetPoint("BOTTOM", icon, "BOTTOM", 0, -12)
            icon.slotText:SetFont("Fonts\\FRIZQT__.TTF", 9, "OUTLINE")
            icon.slotText:SetTextColor(1, 1, 1) -- Color blanco
            icon.slotText:Hide()

            -- Tooltip al pasar el mouse
            icon:SetScript("OnEnter", function(self)
                GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
                if self.isTrashIcon and self.trashItemsList then
                    GameTooltip:SetText("Vendor Items (" .. self.trashCount .. ")", 0.6, 0.6, 0.6)
                    GameTooltip:AddLine(" ")

                    -- Mostrar cada item basura con icono
                    for _, trashData in ipairs(self.trashItemsList) do
                        local itemName = trashData.name
                        local sellPrice = trashData.sellPrice
                        local itemIcon = GetItemIcon(trashData.itemID)

                        -- Formatear precio con iconos de moneda
                        local gold = math.floor(sellPrice / 10000)
                        local silver = math.floor((sellPrice % 10000) / 100)
                        local copper = sellPrice % 100
                        local priceStr = ""
                        if gold > 0 then priceStr = priceStr .. gold .. "|TInterface\\MoneyFrame\\UI-GoldIcon:0|t " end
                        if silver > 0 then priceStr = priceStr .. silver .. "|TInterface\\MoneyFrame\\UI-SilverIcon:0|t " end
                        if copper > 0 then priceStr = priceStr .. copper .. "|TInterface\\MoneyFrame\\UI-CopperIcon:0|t" end

                        -- Icono del item + nombre
                        local iconStr = ""
                        if itemIcon then
                            iconStr = "|T" .. itemIcon .. ":16|t "
                        end

                        GameTooltip:AddDoubleLine(iconStr .. itemName, priceStr, 0.6, 0.6, 0.6, 1, 1, 1)
                    end

                    -- Línea separadora y total
                    GameTooltip:AddLine(" ")
                    local totalGold = math.floor(self.trashGold / 10000)
                    local totalSilver = math.floor((self.trashGold % 10000) / 100)
                    local totalCopper = self.trashGold % 100
                    local totalStr = ""
                    if totalGold > 0 then totalStr = totalStr .. totalGold .. "|TInterface\\MoneyFrame\\UI-GoldIcon:0|t " end
                    if totalSilver > 0 then totalStr = totalStr .. totalSilver .. "|TInterface\\MoneyFrame\\UI-SilverIcon:0|t " end
                    if totalCopper > 0 then totalStr = totalStr .. totalCopper .. "|TInterface\\MoneyFrame\\UI-CopperIcon:0|t" end
                    GameTooltip:AddDoubleLine("Total:", totalStr, 1, 0.82, 0, 1, 0.82, 0)
                else
                    GameTooltip:SetItemByID(self.itemID)
                end
                GameTooltip:Show()
            end)

            icon:SetScript("OnLeave", function(self)
                GameTooltip:Hide()
            end)

            -- Click para ver item en el chat
            icon:SetScript("OnClick", function(self)
                if not self.isTrashIcon then
                    local _, itemLink = GetItemInfo(self.itemID)
                    if itemLink then
                        ChatFrame1:AddMessage(itemLink)
                    end
                end
            end)

            self.frame.lootIcons[i] = icon
        end

        -- Posicionar icono
        local row = math.floor((i - 1) / MAX_ICONS_PER_ROW)
        local col = (i - 1) % MAX_ICONS_PER_ROW
        icon:ClearAllPoints()
        icon:SetPoint("TOPLEFT", self.frame.lootFrame, "TOPLEFT", col * (ICON_SIZE + ICON_SPACING), -row * (ICON_SIZE + ICON_SPACING))

        -- Resetear estado
        icon.glow:Hide()
        icon.glow:SetAlpha(0)
        icon.priceText:Hide()
        icon.countText:Hide()
        if icon.slotText then icon.slotText:Hide() end
        icon.isTrashIcon = false
        icon.trashCount = 0
        icon.trashGold = 0
        icon.trashItemsList = nil

        -- Asignar item ID
        icon.itemID = itemID

        if itemData.isTrash then
            -- Icono consolidado de basura
            icon.isTrashIcon = true
            icon.trashCount = itemData.trashCount
            icon.trashGold = itemData.trashGold
            icon.trashItemsList = itemData.trashItems -- Lista para el tooltip

            -- Usar el icono del primer item basura
            icon.texture:SetTexture(GetItemIcon(itemData.itemID) or "Interface\\Icons\\INV_Misc_Bag_10")

            -- Borde gris
            local r, g, b = GetItemQualityColor(0)
            icon.border:SetVertexColor(r, g, b)

            -- Mostrar cantidad
            icon.countText:SetText("x" .. itemData.trashCount)
            icon.countText:Show()

            -- Mostrar oro total
            local gold = math.floor(itemData.trashGold / 10000)
            local silver = math.floor((itemData.trashGold % 10000) / 100)
            local copper = itemData.trashGold % 100
            local priceStr = ""
            if gold > 0 then
                priceStr = gold .. "|TInterface\\MoneyFrame\\UI-GoldIcon:0|t"
            elseif silver > 0 then
                priceStr = silver .. "|TInterface\\MoneyFrame\\UI-SilverIcon:0|t"
            else
                priceStr = copper .. "|TInterface\\MoneyFrame\\UI-CopperIcon:0|t"
            end
            icon.priceText:SetText(priceStr)
            icon.priceText:Show()
        else
            -- Item normal
            local itemIcon = GetItemIcon(itemID)
            if itemIcon then
                icon.texture:SetTexture(itemIcon)
            else
                icon.texture:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark")
                local item = Item:CreateFromItemID(itemID)
                item:ContinueOnItemLoad(function()
                    local loadedIcon = GetItemIcon(itemID)
                    if loadedIcon then
                        icon.texture:SetTexture(loadedIcon)
                    end
                end)
            end

            local _, _, itemRarity, _, _, _, _, _, _, _, sellPrice = GetItemInfo(itemID)
            if itemRarity then
                local r, g, b = GetItemQualityColor(itemRarity)
                icon.border:SetVertexColor(r, g, b)

                -- Items verdes - mostrar precio
                if itemRarity == 2 and sellPrice and sellPrice > 0 then
                    local gold = math.floor(sellPrice / 10000)
                    local silver = math.floor((sellPrice % 10000) / 100)
                    local copper = sellPrice % 100
                    local priceStr = ""
                    if gold > 0 then
                        priceStr = gold .. "|TInterface\\MoneyFrame\\UI-GoldIcon:0|t"
                    elseif silver > 0 then
                        priceStr = silver .. "|TInterface\\MoneyFrame\\UI-SilverIcon:0|t"
                    else
                        priceStr = copper .. "|TInterface\\MoneyFrame\\UI-CopperIcon:0|t"
                    end
                    icon.priceText:SetText(priceStr)
                    icon.priceText:Show()
                end

                -- Items épicos - efecto glow y tipo de item
                if itemRarity >= 4 then
                    icon.glow:SetVertexColor(r, g, b)
                    icon.glow:SetAlpha(0.8)
                    icon.glow:Show()

                    -- Mostrar tipo de equipo (Abalorio, Capa, etc.)
                    local _, _, _, _, _, itemType, itemSubType, _, itemEquipLoc = GetItemInfo(itemID)
                    if icon.slotText then
                        local slotName = nil
                        if itemEquipLoc and itemEquipLoc ~= "" then
                            slotName = _G[itemEquipLoc] -- Traduce INVTYPE_TRINKET a "Abalorio", etc.
                        end
                        if slotName then
                            icon.slotText:SetText(slotName)
                            icon.slotText:Show()
                        elseif itemSubType then
                            icon.slotText:SetText(itemSubType)
                            icon.slotText:Show()
                        end
                    end
                end

                -- Items de decoración/vivienda - mostrar icono de casa
                local _, _, _, _, _, itemType2, itemSubType2 = GetItemInfo(itemID)
                if itemSubType2 == "Decoraciones de viviendas" or (itemType2 == "Consumable" and itemSubType2 == "Housing") then
                    if icon.slotText then
                        -- Icono de casa + texto
                        icon.slotText:SetText("|A:housingsystem-placeholder-decor:14:14|a Decor")
                        icon.slotText:Show()
                    end
                end
            else
                icon.border:SetVertexColor(1, 1, 1)
                local item = Item:CreateFromItemID(itemID)
                item:ContinueOnItemLoad(function()
                    local _, _, loadedRarity, _, _, _, _, _, _, _, loadedSellPrice = GetItemInfo(itemID)
                    if loadedRarity then
                        local r, g, b = GetItemQualityColor(loadedRarity)
                        icon.border:SetVertexColor(r, g, b)

                        if loadedRarity == 2 and loadedSellPrice and loadedSellPrice > 0 then
                            local gold = math.floor(loadedSellPrice / 10000)
                            local silver = math.floor((loadedSellPrice % 10000) / 100)
                            local copper = loadedSellPrice % 100
                            local priceStr = ""
                            if gold > 0 then
                                priceStr = gold .. "|TInterface\\MoneyFrame\\UI-GoldIcon:0|t"
                            elseif silver > 0 then
                                priceStr = silver .. "|TInterface\\MoneyFrame\\UI-SilverIcon:0|t"
                            else
                                priceStr = copper .. "|TInterface\\MoneyFrame\\UI-CopperIcon:0|t"
                            end
                            icon.priceText:SetText(priceStr)
                            icon.priceText:Show()
                        end

                        if loadedRarity >= 4 then
                            icon.glow:SetVertexColor(r, g, b)
                            icon.glow:SetAlpha(0.8)
                            icon.glow:Show()

                            -- Mostrar tipo de equipo (Abalorio, Capa, etc.)
                            local _, _, _, _, _, loadedType, loadedSubType, _, loadedEquipLoc = GetItemInfo(itemID)
                            if icon.slotText then
                                local slotName = nil
                                if loadedEquipLoc and loadedEquipLoc ~= "" then
                                    slotName = _G[loadedEquipLoc]
                                end
                                if slotName then
                                    icon.slotText:SetText(slotName)
                                    icon.slotText:Show()
                                elseif loadedSubType then
                                    icon.slotText:SetText(loadedSubType)
                                    icon.slotText:Show()
                                end
                            end
                        end

                        -- Items de decoración/vivienda - mostrar icono de casa
                        local _, _, _, _, _, loadedType2, loadedSubType2 = GetItemInfo(itemID)
                        if loadedSubType2 == "Decoraciones de viviendas" or (loadedType2 == "Consumable" and loadedSubType2 == "Housing") then
                            if icon.slotText then
                                icon.slotText:SetText("|A:housingsystem-placeholder-decor:14:14|a Decor")
                                icon.slotText:Show()
                            end
                        end
                    end
                end)
            end
        end

        icon:Show()
    end

    -- Mostrar el frame de loot
    self.frame.lootFrame:Show()
end

-- RefreshConfig y UpdatePauseDisplay removidos - no son necesarios para raros
