setfenv(1, VoiceOver)

GameObjectAdapter = {}

local isActive = false
local playedObjects = {}

-- Función para obtener las coordenadas actuales del jugador
local function GetPlayerCoordinates()
    local mapID = C_Map.GetBestMapForUnit("player")
    if not mapID then
        return nil, nil
    end

    -- Usar RunScript para evitar error de Vector2DMixin en WoW 11.0+
    RunScript('_TEMP_POSITION = C_Map.GetPlayerMapPosition(' .. mapID .. ', "player")')

    local position = _G._TEMP_POSITION
    _G._TEMP_POSITION = nil

    if not position then
        return nil, nil
    end

    local x = position.x
    local y = position.y

    if not x or not y then
        return nil, nil
    end

    -- Convertir a porcentaje (0-100) y formatear con 1 decimal
    x = x * 100
    y = y * 100

    return x, y
end

-- Función para generar hash determinístico de 8 caracteres (FNV-1a)
-- Debe ser idéntico al de GameObjectOnlyFrame
local function GenerateHash(text)
    local FNV_OFFSET = 2166136261
    local FNV_PRIME = 16777619

    local hash = FNV_OFFSET
    for i = 1, #text do
        hash = bit.bxor(hash, string.byte(text, i))
        hash = (hash * FNV_PRIME) % 4294967296
    end

    return string.format("%08x", hash)
end

-- Función para obtener la ubicación actual del jugador como mapID y coordenadas
local function GetPlayerLocation()
    local mapID = C_Map.GetBestMapForUnit("player")
    if not mapID then
        return nil, nil
    end

    local x, y = GetPlayerCoordinates()
    if not x or not y then
        return nil, nil
    end

    -- Formato de coordenadas: "X.X,Y.Y" con 1 decimal
    local coords = string.format("%.1f,%.1f", x, y)

    return mapID, coords
end

-- Función para manejar ITEM_TEXT_READY
local function OnItemTextReady()
    if not isActive then
        Debug:Print(Utils:ColorizeText("Adapter is not active", RED_FONT_COLOR_CODE), "GameObject")
        return
    end

    local title = ItemTextGetItem()
    local mapID, coords = GetPlayerLocation()

    Debug:Print("ITEM_TEXT_READY triggered - Title: " .. tostring(title) .. " MapID: " .. tostring(mapID) .. " Coords: " .. tostring(coords), "GameObject")

    if not title or not mapID or not coords then
        Debug:Print(Utils:ColorizeText("Missing data - Title: " .. tostring(title) .. " MapID: " .. tostring(mapID) .. " Coords: " .. tostring(coords), RED_FONT_COLOR_CODE), "GameObject")
        return
    end

    -- Crear clave única para evitar duplicados
    local uniqueKey = title .. "|" .. mapID .. "|" .. coords

    if playedObjects[uniqueKey] then
        Debug:Print(Utils:ColorizeText("Already played: " .. uniqueKey, YELLOW_FONT_COLOR_CODE), "GameObject")
        return -- Ya reproducido
    end

    -- 1. Intentar buscar en la base de datos de proximidad (oficial)
    local hash = DataModules:GetGameObjectHash(title, mapID, coords)

    -- 2. Si falla, intentar generar el hash directamente (para objetos convertidos manualmente)
    if not hash then
        local hashInput = title .. "|" .. mapID .. "|" .. coords
        local generatedHash = GenerateHash(hashInput)

        -- Verificar si este hash generado existe en algún módulo cargado
        if DataModules:GetSoundLength(generatedHash) then
            hash = generatedHash
            Debug:Print(Utils:ColorizeText("Match found via generated hash: " .. hash, CYAN_FONT_COLOR_CODE), "GameObject")
        end
    else
        Debug:Print("Match found in database: " .. hash, "GameObject")
    end

    if not hash then
        local hashInput = title .. "|" .. mapID .. "|" .. coords
        local generatedHash = GenerateHash(hashInput)
        Debug:Print(Utils:ColorizeText("No match found. Title: " .. title .. " MapID: " .. tostring(mapID) .. " Coords: " .. coords, RED_FONT_COLOR_CODE), "GameObject")
        Debug:Print(Utils:ColorizeText("Expected Hash: " .. generatedHash, RED_FONT_COLOR_CODE), "GameObject")
        return
    end

    -- Obtener duración del sonido
    local duration = DataModules:GetSoundLength(hash)
    local isManualFile = false

    if not duration then
        duration = 30 -- Duración por defecto para archivos manuales (más larga para asegurar que se escuche)
        isManualFile = true
        Debug:Print(Utils:ColorizeText("Using manual mode for hash: " .. hash, YELLOW_FONT_COLOR_CODE), "GameObject")
    else
        Debug:Print("Sound duration found: " .. tostring(duration), "GameObject")
    end

    -- Crear soundData completo
    local soundData = {
        event = Enums.SoundEvent.GameObject,
        title = title,
        name = title,
        fileName = hash,
        filePath = format([[Interface\AddOns\AI_VoiceOverData_Midnight_esMX\generated\sounds\gameobjects\%s.mp3]], hash),
        length = duration,
    }

    -- Si es un archivo manual, intentamos registrarlo mínimamente para que SoundQueue no lo rechace
    if isManualFile then
        soundData.module = { METADATA = { AddonName = "AI_VoiceOverData_Midnight_esMX" } }
        SoundQueue:AddSoundToQueue(soundData)
        playedObjects[uniqueKey] = true
        Debug:Print("Manual sound added to queue", "GameObject")
    else
        -- Preparar y encolar el sonido (vía oficial)
        if DataModules:PrepareSound(soundData) then
            Debug:Print("Sound prepared, adding to queue", "GameObject")
            SoundQueue:AddSoundToQueue(soundData)
            playedObjects[uniqueKey] = true
        else
            Debug:Print(Utils:ColorizeText("Failed to prepare sound (not in tables?)", RED_FONT_COLOR_CODE), "GameObject")
        end
    end
end

-- Frame para eventos
local frame = CreateFrame("Frame")
frame:RegisterEvent("ITEM_TEXT_READY")

frame:SetScript("OnEvent", function(self, event, ...)
    if event == "ITEM_TEXT_READY" then
        OnItemTextReady()
    end
end)

-- Funciones de activación/desactivación
function GameObjectAdapter:Activate()
    isActive = true
end

function GameObjectAdapter:Deactivate()
    isActive = false
end

function GameObjectAdapter:Reset()
    playedObjects = {}
end
