VoiceOver = VoiceOver or {}
setfenv(1, VoiceOver)

-- Mensaje de inicialización
print("|cFF00FF00[AI_VoiceOver]|r ItemSoundManager está cargando...")

-- NPC ID predeterminado para items
local DEFAULT_CREATURE_ID = 233596

-- Crear un frame para manejar eventos
local eventFrame = CreateFrame("Frame")

-- Tabla para almacenar información de recolección reciente
local lastCastSpellID = nil
local lastGatheredItems = {}

-- Tabla para almacenar los IDs de los ítems que ya se han reproducido en la sesión actual
local playedItemsThisSession = {}

-- Función para extraer el itemID de un itemLink
local function GetItemIDFromLink(itemLink)
    if not itemLink then return nil end
    
    -- El patrón más fiable para extraer el itemID de un itemLink
    local itemID = itemLink:match("item:(%d+):")
    if not itemID then
        itemID = itemLink:match("item:(%d+)")
    end
    
    return tonumber(itemID)
end

-- Función para imprimir mensajes de depuración directamente
local function DirectDebugPrint(message)
    print("|cFF00FFFF[ItemSoundManager]|r " .. message)
end

-- Mensaje inicial
DirectDebugPrint("Módulo inicializado")

-- Función para obtener los datos de sonido de un item
local function GetItemSoundData(itemID)
    if not itemID then 
        DirectDebugPrint("GetItemSoundData: itemID es nil")
        return nil 
    end
    
    DirectDebugPrint("Buscando datos para item ID: " .. itemID)
    
    -- Construir el nombre del archivo (sin extensión)
    local fileName = itemID .. "-item"
    
    -- Buscar en todos los módulos de datos
    for _, module in DataModules:GetModules() do
        -- Primero intentamos encontrar en el SoundLengthLookupByFileName
        if module and module.SoundLengthLookupByFileName then
            local data = module.SoundLengthLookupByFileName
            if data and data[fileName] then
                DirectDebugPrint("Item ID encontrado en SoundLengthLookupByFileName: " .. itemID)
                
                -- Construir la ruta completa del archivo
                local filePath = string.format("Interface/AddOns/%s/generated/sounds/items/%s.mp3", 
                    module.METADATA.AddonName, 
                    fileName)
                
                DirectDebugPrint("Ruta del archivo: " .. filePath)
                
                return {
                    fileName = fileName,
                    duration = data[fileName],
                    creatureID = DEFAULT_CREATURE_ID,
                    filePath = filePath,
                    module = module,
                    description = ""
                }
            end
        end
        
        -- Si no se encuentra en el lookup, intentar encontrar el archivo directamente
        local filePath = string.format("Interface/AddOns/%s/generated/sounds/items/%s.mp3", 
            module.METADATA.AddonName, 
            fileName)
            
        DirectDebugPrint("Buscando archivo en: " .. filePath)
        
        -- Asumir que el archivo existe si estamos en el módulo correcto
        if module.METADATA.AddonName:find("WarWithin_es$") then
            DirectDebugPrint("Archivo encontrado en módulo WarWithin_es: " .. filePath)
            
            return {
                fileName = fileName,
                duration = 5, -- Duración predeterminada de 5 segundos
                creatureID = DEFAULT_CREATURE_ID,
                filePath = filePath,
                module = module,
                description = ""
            }
        end
    end
    
    DirectDebugPrint("Item ID no encontrado: " .. itemID)
    return nil
end

-- Función para reproducir el sonido de un item por ID
local function PlayItemSoundByID(itemID)
    if not itemID then 
        DirectDebugPrint("PlayItemSoundByID: itemID es nil")
        return 
    end
    
    DirectDebugPrint("Intentando reproducir item ID: " .. itemID)
    
    -- Verificar si el ítem ya se ha reproducido en esta sesión
    if playedItemsThisSession[itemID] then
        DirectDebugPrint("El item ID: " .. itemID .. " ya se ha reproducido en esta sesión. Omitiendo reproducción.")
        return
    end
    
    local soundData = GetItemSoundData(itemID)
    if not soundData then 
        DirectDebugPrint("No se encontraron datos de sonido para item ID: " .. itemID)
        return 
    end
    
    -- Obtener información del item y su tooltip
    local itemName, itemLink = GetItemInfo(itemID)
    local tooltipText = ""
    
    if itemLink then
        -- Crear tooltip para obtener la descripción
        local tooltip = _G["ItemSoundManagerTooltip"] or CreateFrame("GameTooltip", "ItemSoundManagerTooltip", nil, "GameTooltipTemplate")
        tooltip:SetOwner(WorldFrame, "ANCHOR_NONE")
        tooltip:SetHyperlink(itemLink)
        
        -- Obtener texto de las líneas del tooltip
        for i = 2, tooltip:NumLines() do  -- Empezar desde 2 para omitir el nombre del item
            local line = _G["ItemSoundManagerTooltipTextLeft" .. i]
            if line and line:GetText() then
                local text = line:GetText()
                -- Filtrar líneas con información de debug como ItemID, IconID, SpellID
                if not text:match("ItemID") and not text:match("IconID") and not text:match("SpellID") then
                    if tooltipText ~= "" then tooltipText = tooltipText .. "\n" end
                    tooltipText = tooltipText .. text
                end
            end
        end
    end
    
    -- Crear el objeto de datos de sonido para la cola
    local queueData = {
        event = Enums.SoundEvent.ItemReceived,
        fileName = soundData.fileName,  -- Sin extensión
        filePath = soundData.filePath,  -- Con extensión
        length = soundData.duration,
        title = format("|cFFFF8800Item %s|r", itemID),
        --title = tooltipText ~= "" and format("|cFFFF8800%s|r", tooltipText) or "Item " .. itemID,
        name = format("|cFF00FF00%s|r\n%s", itemName or "Objeto Encontrado", soundData.description or ""),
        unitGUID = string.format("Creature-0-0-0-0-%d", soundData.creatureID),
        module = soundData.module,
        
        addedCallback = function(sd)
            DirectDebugPrint("Sonido añadido a la cola: " .. sd.fileName)
            if SoundQueueUI and SoundQueueUI.UpdateSoundQueueDisplay then
                SoundQueueUI:UpdateSoundQueueDisplay()
            end
        end,
        
        startCallback = function(sd)
            DirectDebugPrint("Sonido comenzó a reproducirse: " .. sd.fileName)
            if SoundQueueUI and SoundQueueUI.frame and SoundQueueUI.frame.portrait then
                SoundQueueUI.frame.portrait:Configure(sd)
            end
        end,
        
        stopCallback = function(sd)
            DirectDebugPrint("Sonido detenido: " .. sd.fileName)
            if SoundQueueUI and SoundQueueUI.frame and SoundQueueUI.frame.portrait then
                SoundQueueUI.frame.portrait:Configure(nil)
            end
        end
    }
    
    -- Verificar si SoundQueue está disponible y añadir el sonido a la cola
    if SoundQueue and SoundQueue.AddSoundToQueue then
        DirectDebugPrint("Preparando sonido para item ID: " .. itemID)
        
        -- Verificar si el archivo existe físicamente
        DirectDebugPrint("Verificando archivo: " .. queueData.filePath)
        
        -- Asegurarse de que el archivo de sonido exista y esté preparado
        local soundExists = DataModules:PrepareSound(queueData)
        if soundExists then
            DirectDebugPrint("Añadiendo sonido a la cola para item ID: " .. itemID)
            SoundQueue:AddSoundToQueue(queueData)
            
            -- Marcar este ítem como reproducido en esta sesión
            playedItemsThisSession[itemID] = true
            DirectDebugPrint("Item ID: " .. itemID .. " marcado como reproducido en esta sesión")
        else
            DirectDebugPrint("Error: No se encontró el sonido para el item: " .. itemID)
            DirectDebugPrint("Ruta buscada: " .. queueData.filePath)
            
            -- Intenta reproducir directamente con PlaySoundFile como último recurso
            DirectDebugPrint("Intentando reproducir directamente con PlaySoundFile...")
            PlaySoundFile(queueData.filePath, "Master")
            
            -- Marcar este ítem como reproducido en esta sesión
            playedItemsThisSession[itemID] = true
            DirectDebugPrint("Item ID: " .. itemID .. " marcado como reproducido en esta sesión")
        end
    else
        DirectDebugPrint("Error: SoundQueue no está disponible")
    end
end

-- Manejador de evento para cuando se obtiene un item
local function OnItemReceived(self, event, ...)
    DirectDebugPrint("Evento recibido: " .. event)
    
    if event == "PLAYER_ENTERING_WORLD" then
        DirectDebugPrint("Jugador entrando al mundo - ItemSoundManager activo")
        return
    end
    
    if event == "LOOT_OPENED" then
        DirectDebugPrint("Procesando apertura de loot")
        
        -- Obtener el número de objetos en el loot
        local numLootItems = GetNumLootItems()
        if numLootItems <= 0 then return end
        
        for i = 1, numLootItems do
            local itemLink = GetLootSlotLink(i)
            if itemLink then
                local lootSource = GetLootSourceInfo(i)
                DirectDebugPrint("Item en loot: " .. itemLink .. ", Fuente: " .. (lootSource or "desconocida"))
                
                -- Determinar el tipo de evento
                local eventType = "LOOT"
                if lastCastSpellID then
                    local spellName = GetSpellInfo(lastCastSpellID)
                    if spellName then
                        if spellName:find("Herborismo") or spellName:find("Herbalism") then
                            eventType = "HERB"
                        elseif spellName:find("Minería") or spellName:find("Mining") then
                            eventType = "MINE"
                        elseif spellName:find("Desuello") or spellName:find("Skinning") then
                            eventType = "SKIN"
                        elseif spellName:find("Pesca") or spellName:find("Fishing") then
                            eventType = "FISH"
                        end
                    end
                end
                
                -- Guardar el item para relacionarlo con eventos futuros
                table.insert(lastGatheredItems, {
                    itemLink = itemLink,
                    eventType = eventType,
                    timestamp = GetTime()
                })
                
                -- Obtener el itemID del itemLink
                local itemID = GetItemIDFromLink(itemLink)
                
                if itemID then
                    DirectDebugPrint("[LOOT_OPENED] Item detectado: " .. itemID)
                    
                    -- Mostrar información detallada del item
                    local itemName, _, itemRarity, itemLevel, _, itemType, 
                          itemSubType = GetItemInfo(itemID)
                    
                    if itemName then
                        print("|cFFFF0000[ItemSoundManager]|r |cFF00FF00¡Item detectado!|r")
                        print("|cFFFFFF00Nombre:|r |cFF00FF00" .. itemName .. "|r")
                        print("|cFFFFFF00ID:|r |cFF00FFFF" .. itemID .. "|r")
                        print("|cFFFFFF00Tipo:|r |cFF00FFFF" .. (itemType or "?") .. " - " .. (itemSubType or "?") .. "|r")
                    end
                    
                    -- Intentar reproducir el sonido del item
                    PlayItemSoundByID(itemID)
                end
            end
        end
    elseif event == "UNIT_SPELLCAST_SUCCEEDED" then
        local unit, _, spellID = ...
        if unit == "player" then
            local spellName = GetSpellInfo(spellID)
            DirectDebugPrint("Lanzamiento de hechizo: " .. (spellName or "desconocido") .. " (" .. spellID .. ")")
            
            -- Guardar el último spellID para relacionarlo con el loot
            lastCastSpellID = spellID
            
            -- Limpiar items antiguos (más de 60 segundos)
            local now = GetTime()
            for i = #lastGatheredItems, 1, -1 do
                if now - lastGatheredItems[i].timestamp > 60 then
                    table.remove(lastGatheredItems, i)
                end
            end
        end
    elseif event == "CHAT_MSG_LOOT" then
        local message, _, _, _, player = ...
        DirectDebugPrint("Mensaje de loot: " .. message)
        
        -- Verificar si el mensaje de loot es para el jugador actual
        local playerName = UnitName("player")
        if not message:find(playerName) then 
            DirectDebugPrint("El mensaje no es para el jugador actual")
            return 
        end
        
        -- Extraer el itemLink del mensaje
        local itemLink = message:match("|H(item:[^|]+)|h")
        if not itemLink then
            itemLink = message:match("|H([^|]+)|h")
        end
        
        if not itemLink then
            DirectDebugPrint("No se encontró itemLink en el mensaje")
            return
        end
        
        -- Agregar el prefijo "item:" si no existe
        if not itemLink:find("^item:") then
            itemLink = "item:" .. itemLink
        end
        
        -- Relacionar con un evento de recolección reciente
        local eventType = "LOOT"
        for i = #lastGatheredItems, 1, -1 do
            local gatheredItem = lastGatheredItems[i]
            local gatheredItemID = GetItemIDFromLink(gatheredItem.itemLink)
            local messageItemID = GetItemIDFromLink(itemLink)
            
            if gatheredItemID == messageItemID then
                eventType = gatheredItem.eventType
                break
            end
        end
        
        -- Obtener el itemID del itemLink
        local itemID = GetItemIDFromLink(itemLink)
        
        if itemID then
            DirectDebugPrint("[LOOT] Item detectado: " .. itemID .. " - Tipo: " .. eventType)
            
            -- Mostrar información detallada del item
            local itemName, _, itemRarity, itemLevel, _, itemType, 
                  itemSubType = GetItemInfo(itemID)
            
            if itemName then
                -- Obtener el texto del tooltip del item
                local tooltipText = ""
                local tooltip = _G["ItemSoundManagerTooltip"] or CreateFrame("GameTooltip", "ItemSoundManagerTooltip", nil, "GameTooltipTemplate")
                tooltip:SetOwner(WorldFrame, "ANCHOR_NONE")
                tooltip:SetHyperlink("item:" .. itemID)
                
                -- Obtener texto de las líneas del tooltip
                for i = 2, tooltip:NumLines() do  -- Empezar desde 2 para omitir el nombre del item
                    local line = _G["ItemSoundManagerTooltipTextLeft" .. i]
                    if line and line:GetText() then
                        local text = line:GetText()
                        -- Filtrar líneas con información de debug como ItemID, IconID, SpellID
                        if not text:match("ItemID") and not text:match("IconID") and not text:match("SpellID") then
                            if tooltipText ~= "" then tooltipText = tooltipText .. "\n" end
                            tooltipText = tooltipText .. text
                        end
                    end
                end
                
                -- Imprimir información básica
                print("|cFFFF0000[ItemSoundManager]|r |cFF00FF00¡Item detectado!|r")
                print("|cFFFFFF00Nombre:|r |cFF00FF00" .. itemName .. "|r")
                print("|cFFFFFF00ID:|r |cFF00FFFF" .. itemID .. "|r")
                print("|cFFFFFF00Tipo:|r |cFF00FFFF" .. (itemType or "?") .. " - " .. (itemSubType or "?") .. "|r")
            end
            
            -- Intentar reproducir el sonido del item
            PlayItemSoundByID(itemID)
        else
            DirectDebugPrint("No se pudo extraer el itemID del itemLink: " .. itemLink)
        end
    elseif event == "ITEM_PUSH" then
        local bagID, slotID = ...
        DirectDebugPrint("Item push en bolsa " .. tostring(bagID) .. ", slot " .. tostring(slotID))
        
        -- En The War Within, slotID puede ser el iconID en lugar del slot real
        -- Vamos a intentar obtener el itemID directamente del evento
        if bagID and slotID then
            -- Intentar obtener el itemID usando C_Container (War Within)
            local itemID
            
            -- Método 1: Usar C_Container.GetContainerItemID
            if C_Container and C_Container.GetContainerItemID then
                itemID = C_Container.GetContainerItemID(bagID, slotID)
                if itemID then
                    DirectDebugPrint("ItemID obtenido con C_Container.GetContainerItemID: " .. itemID)
                end
            end
            
            -- Método 2: Usar C_Container.GetContainerItemInfo
            if not itemID and C_Container and C_Container.GetContainerItemInfo then
                local itemInfo = C_Container.GetContainerItemInfo(bagID, slotID)
                if itemInfo and itemInfo.itemID then
                    itemID = itemInfo.itemID
                    DirectDebugPrint("ItemID obtenido con C_Container.GetContainerItemInfo: " .. itemID)
                end
            end
            
            -- Método 3: Buscar el item en todas las bolsas (último recurso)
            if not itemID then
                DirectDebugPrint("Buscando item en todas las bolsas...")
                local numBags = NUM_BAG_SLOTS or 4
                for bag = 0, numBags do
                    local numSlots = C_Container and C_Container.GetContainerNumSlots and C_Container.GetContainerNumSlots(bag) or GetContainerNumSlots(bag)
                    for slot = 1, numSlots do
                        local itemInfoFunc = C_Container and C_Container.GetContainerItemInfo or GetContainerItemInfo
                        local itemInfoResult = C_Container and C_Container.GetContainerItemInfo and C_Container.GetContainerItemInfo(bag, slot)
                        
                        if itemInfoResult then
                            local texture = itemInfoResult.iconFileID
                            if texture == slotID then
                                itemID = itemInfoResult.itemID
                                DirectDebugPrint("¡Encontrado! El slotID " .. slotID .. " es el iconFileID del item " .. itemID)
                                break
                            end
                        end
                    end
                    if itemID then break end
                end
            end
            
            if itemID then
                DirectDebugPrint("[PUSH] Recibido item ID: " .. itemID .. " en bolsa " .. bagID .. ", slot " .. slotID)
                
                -- Mostrar información detallada del item en rojo
                local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, 
                      itemSubType, itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = GetItemInfo(itemID)
                
                if itemName then
                    -- Obtener el texto del tooltip del item
                    local tooltipText = ""
                    local tooltip = _G["ItemSoundManagerTooltip"] or CreateFrame("GameTooltip", "ItemSoundManagerTooltip", nil, "GameTooltipTemplate")
                    tooltip:SetOwner(WorldFrame, "ANCHOR_NONE")
                    tooltip:SetHyperlink(itemLink)
                    
                    -- Obtener texto de las líneas del tooltip
                    for i = 2, tooltip:NumLines() do  -- Empezar desde 2 para omitir el nombre del item
                        local line = _G["ItemSoundManagerTooltipTextLeft" .. i]
                        if line and line:GetText() then
                            local text = line:GetText()
                            -- Filtrar líneas con información de debug como ItemID, IconID, SpellID
                            if not text:match("ItemID") and not text:match("IconID") and not text:match("SpellID") then
                                if tooltipText ~= "" then tooltipText = tooltipText .. "\n" end
                                tooltipText = tooltipText .. text
                            end
                        end
                    end
                    
                    -- Imprimir toda la información en rojo
                    print("|cFFFF0000===== INFORMACIÓN DETALLADA DEL ITEM (PUSH) =====|r")
                    print("|cFFFF0000Nombre:|r " .. itemName)
                    print("|cFFFF0000ID:|r " .. itemID)
                    print("|cFFFF0000Tipo:|r " .. (itemType or "Desconocido") .. " - " .. (itemSubType or ""))
                    print("|cFFFF0000Nivel:|r " .. (itemLevel or "N/A"))
                    print("|cFFFF0000Texto:|r " .. tooltipText)
                    print("|cFFFF0000Link:|r " .. (itemLink or "N/A"))
                    print("|cFFFF0000Textura:|r " .. (itemTexture or "N/A"))
                    print("|cFFFF0000BagID:|r " .. bagID .. " |cFFFF0000Slot:|r " .. slotID)
                    print("|cFFFF0000=====================================|r")
                end
                
                -- Intentar reproducir el sonido del item
                PlayItemSoundByID(itemID)
            else
                DirectDebugPrint("No se pudo obtener itemID para bagID: " .. bagID .. ", slot: " .. slotID)
                DirectDebugPrint("NOTA: En The War Within, el slotID " .. slotID .. " podría ser el iconFileID del item")
            end
        else
            DirectDebugPrint("bagID o slot son nil")
        end
    end
end

-- Registrar eventos para capturar cuando se obtienen items
local function RegisterEvents()
    DirectDebugPrint("Registrando eventos...")
    
    -- Registrar eventos
    eventFrame:RegisterEvent("LOOT_OPENED")
    eventFrame:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
    eventFrame:RegisterEvent("CHAT_MSG_LOOT")
    eventFrame:RegisterEvent("ITEM_PUSH")
    eventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
    eventFrame:SetScript("OnEvent", OnItemReceived)
    
    DirectDebugPrint("Eventos registrados correctamente")
end

-- Inicializar el sistema al cargar
RegisterEvents()

-- Función para probar manualmente el sistema
local function TestItemSound(itemID)
    itemID = itemID or 263366 -- ID de ejemplo si no se proporciona uno
    DirectDebugPrint("Probando sonido para item ID: " .. itemID)
    
    -- Para pruebas, permitimos reproducir el ítem incluso si ya se ha reproducido
    -- Eliminamos el ítem de la lista de reproducidos si existe
    if playedItemsThisSession[itemID] then
        playedItemsThisSession[itemID] = nil
        DirectDebugPrint("Eliminando item ID: " .. itemID .. " de la lista de reproducidos para prueba")
    end
    
    PlayItemSoundByID(itemID)
end

-- Función para reiniciar la lista de ítems reproducidos
local function ResetPlayedItems()
    playedItemsThisSession = {}
    DirectDebugPrint("Lista de ítems reproducidos reiniciada")
end

-- Exponer las funciones necesarias
VoiceOver.ItemSoundManager = {
    GetItemSoundData = GetItemSoundData,
    PlayItemSoundByID = PlayItemSoundByID,
    TestItemSound = TestItemSound,
    ResetPlayedItems = ResetPlayedItems
}

-- Mensaje final
print("|cFF00FF00[AI_VoiceOver]|r ItemSoundManager cargado correctamente. Usa /run VoiceOver.ItemSoundManager.TestItemSound(ID) para probar.")

return VoiceOver.ItemSoundManager
