-- === FELLOWKICK: MYTHIC+ COORDINATOR ===
-- Author: Grondy
local MyAddonName, MyAddonTable = ...
local FellowKick = MyAddonTable  -- Alias para compartir datos con InterruptMobs.lua
local PREFIX = "FELLOW_KICK"

-- Helper para localización (función global disponible después de cargar Locales.lua)
local function L(key)
    if FellowKick and FellowKick.L then
        return FellowKick.L(key)
    end
    return key
end


-- Base de Datos por defecto
FellowKickDB = FellowKickDB or {
    position = "TOP", -- TOP, LEFT, RIGHT
    x = 0,
    y = 35,
    scale = 1.2,
    xOffset = 0,
    yOffset = 0,
    -- Posición del marco flotante del grupo
    groupFrame = { x = 300, y = 300 },
    -- Sistema de marcas predefinidas por rol
    predefinedMarks = {
        ["Tank"] = 6,      -- Cuadrado
        ["Healer"] = 4,    -- Triángulo
        ["DPS1"] = 1,      -- Estrella
        ["DPS2"] = 3,      -- Diamante
        ["DPS3"] = 8,      -- Calavera
    },
    myRole = nil,  -- Rol asignado del jugador (Tank, Healer, DPS1, DPS2, DPS3)
}

-- Asegurar que autoMark siempre exista (necesario para actualizar desde versiones anteriores)
if FellowKickDB.autoMark == nil then
    FellowKickDB.autoMark = {
        enabled = true,
        onCombat = true,
        onMouseover = true,
        announceToGroup = false,
    }
end

-- Asegurar que predefinedMarks exista
if FellowKickDB.predefinedMarks == nil then
    FellowKickDB.predefinedMarks = {
        ["Tank"] = 6,      -- Cuadrado
        ["Healer"] = 4,    -- Triángulo
        ["DPS1"] = 1,      -- Estrella
        ["DPS2"] = 3,      -- Diamante
        ["DPS3"] = 8,      -- Calavera
    }
end


-- Tiempos de reutilización base (CDs de interrupción)
local CLASS_INTS = {
    ["ROGUE"] = 15, ["WARRIOR"] = 15, ["MAGE"] = 24, ["DRUID"] = 15,
    ["PALADIN"] = 15, ["DEATHKNIGHT"] = 15, ["SHAMAN"] = 12, ["HUNTER"] = 24,
    ["PRIEST"] = 45, ["MONK"] = 15, ["DEMONHUNTER"] = 15, ["EVOKER"] = 20,
    ["WARLOCK"] = 24
}

-- Mapeo de Spell IDs a su duración de CD (Cortes standard)
local KICK_SPELL_IDS = {
    [1766] = 15,   -- Kick (Rogue)
    [6552] = 15,   -- Pummel (Warrior)
    [2139] = 24,   -- Counterspell (Mage)
    [47528] = 15,  -- Mind Freeze (DK)
    [183752] = 15, -- Disrupt (DH)
    [106839] = 15, -- Skull Bash (Druid Feral/Guardian)
    [78675] = 60,  -- Solar Beam (Druid Balance)
    [96231] = 15,  -- Rebuke (Paladin)
    [57994] = 12,  -- Wind Shear (Shaman)
    [147362] = 24, -- Counter Shot (Hunter BM/MM)
    [187707] = 15, -- Muzzle (Hunter Survival)
    [15487] = 45,  -- Silence (Priest Shadow)
    [116705] = 15, -- Spear Hand Strike (Monk)
    [351338] = 20, -- Quell (Evoker)
    [119910] = 24, -- Spell Lock (Warlock Pet)
    [19647] = 24,  -- Spell Lock (Warlock Base)
    [132409] = 24, -- Spell Lock (Warlock Grimoire)
    [171138] = 24, -- Shadow Lock (Warlock)
    [89766] = 30,  -- Axe Toss (Warlock Demonology - Felguard)
    [119914] = 24  -- Command Demon: Spell Lock (Warlock Pet)
}

-- Ajustar duración de CD según especialización del jugador local
-- Solo afecta al jugador local; cada addon envía su CD real al grupo
local function GetSpecAwareDuration(spellID)
    local baseDuration = KICK_SPELL_IDS[spellID]
    if not baseDuration then return nil end
    
    local _, playerClass = UnitClass("player")
    local specIndex = GetSpecialization()  -- 1-4 según spec activa
    
    -- Shaman Restoration (spec 3): Wind Shear CD = 30s en vez de 12s
    if spellID == 57994 and playerClass == "SHAMAN" and specIndex == 3 then
        return 30
    end
    
    -- Warrior Fury (spec 2) / Protection (spec 3): Pummel CD = 14s en vez de 15s
    -- Arms (spec 1) se queda en 15s
    if spellID == 6552 and playerClass == "WARRIOR" and (specIndex == 2 or specIndex == 3) then
        return 14
    end
    
    
    return baseDuration
end

-- Estado del grupo
local GroupStatus = {}
local isInitialized = false
local myLastBroadcastGUID = nil

-- Helper: Detectar si estamos en CUALQUIER tipo de grupo (home o instancia)
-- IsInGroup() sin argumentos solo detecta "home groups".
-- En M+ puedes estar en un instance group donde IsInGroup() retorna false.
local function IsInAnyGroup()
    return IsInGroup() or IsInGroup(LE_PARTY_CATEGORY_INSTANCE)
end

-- Helper: Obtener el canal correcto para SendAddonMessage / SendChatMessage
local function GetAddonChannel()
    if IsInRaid(LE_PARTY_CATEGORY_INSTANCE) then
        return "INSTANCE_CHAT"
    elseif IsInRaid() then
        return "RAID"
    elseif IsInGroup(LE_PARTY_CATEGORY_INSTANCE) then
        return "INSTANCE_CHAT"
    elseif IsInGroup() then
        return "PARTY"
    end
    return nil
end

-- Forward declarations (funciones definidas más adelante pero usadas en panel de opciones)
local BroadcastMyTarget
local ForceRefresh

-- Helper: Extraer marker de forma segura (maneja secret values)
local function SafeGetMarker(value)
    -- Si es nil o no existe, retorna 0
    if value == nil then return 0 end
    -- Intentar verificar tipo y comparar usando pcall
    local success, result = pcall(function()
        if type(value) == "number" and value >= 1 and value <= 8 then
            return value
        end
        return 0
    end)
    if success then return result end
    return 0
end

-- === 1. SISTEMA VISUAL (WIDGETS) ===

local function CreateUnitWidget(parent)
    local frame = CreateFrame("Frame", nil, parent)
    local size = 24 * (FellowKickDB.scale or 1.2)
    frame:SetSize(size * 2 + 2, size)  -- Doble ancho para icono + marca
    frame:SetFrameStrata("HIGH")

    -- Contenedor del icono de clase (izquierda)
    frame.classContainer = CreateFrame("Frame", nil, frame)
    frame.classContainer:SetSize(size, size)
    frame.classContainer:SetPoint("LEFT", frame, "LEFT", 0, 0)

    -- Fondo del icono de clase
    frame.bg = frame.classContainer:CreateTexture(nil, "BACKGROUND")
    frame.bg:SetAllPoints()
    frame.bg:SetColorTexture(0, 0, 0, 0.9)

    -- Icono de Clase
    frame.icon = frame.classContainer:CreateTexture(nil, "ARTWORK")
    frame.icon:SetPoint("TOPLEFT", 1, -1)
    frame.icon:SetPoint("BOTTOMRIGHT", -1, 1)
    frame.icon:SetTexture("Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Classes")

    -- Texto de Cooldown (sobre el icono de clase)
    frame.cooldownText = frame.classContainer:CreateFontString(nil, "OVERLAY", "GameFontNormalHuge")
    frame.cooldownText:SetPoint("CENTER", 0, 0)
    frame.cooldownText:SetTextColor(1, 0.2, 0.2, 1)

    -- Contenedor del Raid Marker (derecha)
    frame.markerContainer = CreateFrame("Frame", nil, frame)
    frame.markerContainer:SetSize(size, size)
    frame.markerContainer:SetPoint("LEFT", frame.classContainer, "RIGHT", 2, 0)
    frame.markerContainer:Hide()

    -- Fondo del raid marker
    frame.markerBg = frame.markerContainer:CreateTexture(nil, "BACKGROUND")
    frame.markerBg:SetAllPoints()
    frame.markerBg:SetColorTexture(0, 0, 0, 0.7)

    -- Icono de Raid Marker (mismo tamaño que clase)
    frame.raidMarker = frame.markerContainer:CreateTexture(nil, "ARTWORK")
    frame.raidMarker:SetPoint("TOPLEFT", 1, -1)
    frame.raidMarker:SetPoint("BOTTOMRIGHT", -1, 1)

    frame:Hide()
    return frame
end

-- === MARCO FLOTANTE PARA EL GRUPO (Diseño de Tabla) ===

local ROW_HEIGHT = 28
local MARKER_COL_WIDTH = 28
local CLASS_COL_WIDTH = 28
local FRAME_PADDING = 8
local COL_SPACING = 4

local GroupFrame = CreateFrame("Frame", "FellowKickGroupFrame", UIParent, "BackdropTemplate")
GroupFrame:SetSize(MARKER_COL_WIDTH + CLASS_COL_WIDTH + COL_SPACING + FRAME_PADDING * 2, ROW_HEIGHT * 5 + FRAME_PADDING * 2 + 18)
GroupFrame:SetPoint("CENTER", UIParent, "CENTER", FellowKickDB.groupFrame and FellowKickDB.groupFrame.x or 300, FellowKickDB.groupFrame and FellowKickDB.groupFrame.y or 300)
GroupFrame:SetFrameStrata("HIGH")
GroupFrame:SetMovable(true)
GroupFrame:EnableMouse(true)
GroupFrame:RegisterForDrag("LeftButton")
GroupFrame:SetClampedToScreen(true)

-- Backdrop (fondo semi-transparente)
GroupFrame:SetBackdrop({
    bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
    tile = true, tileSize = 16, edgeSize = 12,
    insets = { left = 2, right = 2, top = 2, bottom = 2 }
})
GroupFrame:SetBackdropColor(0, 0, 0, 0.85)
GroupFrame:SetBackdropBorderColor(0.4, 0.8, 0.4, 0.9)

-- Título
GroupFrame.title = GroupFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
GroupFrame.title:SetPoint("TOP", 0, -5)
GroupFrame.title:SetText("|cFF00FF00FellowKick|r")

-- Container para las filas
GroupFrame.rowContainer = CreateFrame("Frame", nil, GroupFrame)
GroupFrame.rowContainer:SetPoint("TOPLEFT", FRAME_PADDING, -22)
GroupFrame.rowContainer:SetPoint("BOTTOMRIGHT", -FRAME_PADDING, FRAME_PADDING)

-- Crear las 5 filas de la tabla
GroupFrame.rows = {}
for i = 1, 5 do
    local row = CreateFrame("Frame", nil, GroupFrame.rowContainer)
    row:SetSize(MARKER_COL_WIDTH + CLASS_COL_WIDTH + COL_SPACING, ROW_HEIGHT - 2)
    row:SetPoint("TOPLEFT", 0, -((i - 1) * ROW_HEIGHT))
    
    -- Columna 1: Marca predefinida
    row.markerFrame = CreateFrame("Frame", nil, row)
    row.markerFrame:SetSize(MARKER_COL_WIDTH - 2, ROW_HEIGHT - 4)
    row.markerFrame:SetPoint("LEFT", 0, 0)
    
    row.markerBg = row.markerFrame:CreateTexture(nil, "BACKGROUND")
    row.markerBg:SetAllPoints()
    row.markerBg:SetColorTexture(0.1, 0.1, 0.1, 0.8)
    
    row.markerIcon = row.markerFrame:CreateTexture(nil, "ARTWORK")
    row.markerIcon:SetPoint("CENTER")
    row.markerIcon:SetSize(MARKER_COL_WIDTH - 6, ROW_HEIGHT - 8)
    -- Textura base de raid markers (requerida para SetRaidTargetIconTexture)
    row.markerIcon:SetTexture("Interface\\TargetingFrame\\UI-RaidTargetingIcons")
    
    -- Columna 2: Icono de clase + CD
    row.classFrame = CreateFrame("Frame", nil, row)
    row.classFrame:SetSize(CLASS_COL_WIDTH - 2, ROW_HEIGHT - 4)
    row.classFrame:SetPoint("LEFT", row.markerFrame, "RIGHT", COL_SPACING, 0)
    
    row.classBg = row.classFrame:CreateTexture(nil, "BACKGROUND")
    row.classBg:SetAllPoints()
    row.classBg:SetColorTexture(0, 0.3, 0, 0.8)
    
    row.classIcon = row.classFrame:CreateTexture(nil, "ARTWORK")
    row.classIcon:SetPoint("TOPLEFT", 2, -2)
    row.classIcon:SetPoint("BOTTOMRIGHT", -2, 2)
    row.classIcon:SetTexture("Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Classes")
    
    row.cdText = row.classFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    row.cdText:SetPoint("CENTER", 0, 0)
    row.cdText:SetTextColor(1, 0.2, 0.2, 1)
    row.cdText:SetFont(row.cdText:GetFont(), 11, "OUTLINE")
    
    row.playerName = nil  -- Se asigna dinámicamente
    row:Hide()
    
    GroupFrame.rows[i] = row
end

-- Scripts de Drag & Drop
GroupFrame:SetScript("OnDragStart", function(self)
    self:StartMoving()
end)

GroupFrame:SetScript("OnDragStop", function(self)
    self:StopMovingOrSizing()
    local centerX, centerY = self:GetCenter()
    local uiCenterX, uiCenterY = UIParent:GetCenter()
    FellowKickDB.groupFrame = FellowKickDB.groupFrame or {}
    FellowKickDB.groupFrame.x = centerX - uiCenterX
    FellowKickDB.groupFrame.y = centerY - uiCenterY
end)

-- Función para actualizar el marco del grupo (Diseño de Tabla)
local function UpdateGroupFrame()
    -- Solo mostrar si estamos en grupo
    if not IsInAnyGroup() then
        GroupFrame:Hide()
        return
    end
    
    local now = GetTime()
    local myName = UnitName("player")
    local rowIndex = 0
    
    -- Primero: Asegurarse de que el jugador local esté en GroupStatus
    if not GroupStatus[myName] then
        local _, c = UnitClass("player")
        GroupStatus[myName] = { class = c, cdExpires = 0 }
    end
    -- Actualizar marca predefinida del jugador local
    if FellowKickDB.myRole and FellowKickDB.predefinedMarks then
        GroupStatus[myName].predefinedMark = FellowKickDB.predefinedMarks[FellowKickDB.myRole] or 0
    end
    
    -- Crear lista ordenada: primero el jugador, luego los demás
    local sortedPlayers = {}
    -- Agregar jugador local primero
    if GroupStatus[myName] then
        table.insert(sortedPlayers, { name = myName, info = GroupStatus[myName], isMe = true })
    end
    -- Agregar resto del grupo
    for playerName, info in pairs(GroupStatus) do
        if playerName ~= myName then
            table.insert(sortedPlayers, { name = playerName, info = info, isMe = false })
        end
    end
    
    -- Actualizar cada fila
    for i, playerData in ipairs(sortedPlayers) do
        if i > 5 then break end  -- Máximo 5 filas
        
        local row = GroupFrame.rows[i]
        local info = playerData.info
        rowIndex = i
        
        -- Columna 1: Marca predefinida
        local marker = SafeGetMarker(info.predefinedMark)
        if marker == 0 then
            marker = SafeGetMarker(info.focusMarker)
        end
        
        -- DEBUG: Imprimir una sola vez por refresh
        if playerData.isMe and FellowKick_DebugOnce then
            print("|cFFFF00FF[FK Debug]|r myRole=" .. tostring(FellowKickDB.myRole) .. 
                  " predefinedMark=" .. tostring(info.predefinedMark) ..
                  " marker=" .. tostring(marker))
            FellowKick_DebugOnce = false
        end
        
        if marker > 0 then
            SetRaidTargetIconTexture(row.markerIcon, marker)
            row.markerIcon:SetAlpha(1)
            row.markerIcon:Show()
            row.markerBg:SetColorTexture(0.15, 0.15, 0.15, 0.9)
        else
            row.markerIcon:Hide()
            row.markerBg:SetColorTexture(0.1, 0.1, 0.1, 0.6)
        end

        
        -- Columna 2: Icono de clase + CD
        local class = info.class or "PRIEST"
        local coords = CLASS_ICON_TCOORDS[class]
        if coords then row.classIcon:SetTexCoord(unpack(coords)) end
        
        local timeLeft = (info.cdExpires or 0) - now
        if timeLeft > 0 then
            row.classIcon:SetDesaturated(true)
            row.classIcon:SetAlpha(0.5)
            row.cdText:SetText(math.ceil(timeLeft))
            row.cdText:Show()
            row.classBg:SetColorTexture(0.5, 0, 0, 0.8)
        else
            row.classIcon:SetDesaturated(false)
            row.classIcon:SetAlpha(1.0)
            row.cdText:Hide()
            row.classBg:SetColorTexture(0, 0.3, 0, 0.8)
        end
        
        -- Resaltar si es el jugador local
        if playerData.isMe then
            row.markerBg:SetColorTexture(0, 0.2, 0.4, 0.9)
        end
        
        row.playerName = playerData.name
        row:Show()
    end
    
    -- Ocultar filas no usadas
    for i = rowIndex + 1, 5 do
        GroupFrame.rows[i]:Hide()
    end
    
    -- Ajustar altura del frame según filas activas
    local activeRows = math.max(rowIndex, 1)
    GroupFrame:SetSize(
        MARKER_COL_WIDTH + CLASS_COL_WIDTH + COL_SPACING + FRAME_PADDING * 2,
        activeRows * ROW_HEIGHT + FRAME_PADDING * 2 + 18
    )
    
    if rowIndex > 0 then
        GroupFrame.title:SetText("|cFF00FF00FellowKick|r")
    else
        GroupFrame.title:SetText("|cFFFFFF00Esperando...|r")
    end
    
    GroupFrame:Show()
end


-- Nueva función: Actualizar widgets usando UnitIsUnit (técnica de Platynator)
local function UpdateNameplateWidget(unitID)
    local plate = C_NamePlate.GetNamePlateForUnit(unitID)
    if not plate then return end
    
    -- Crear container si no existe
    if not plate.FellowKickContainer then
        plate.FellowKickContainer = CreateFrame("Frame", nil, plate)
        plate.FellowKickContainer.portraits = {}
    end
    
    local container = plate.FellowKickContainer
    container:SetSize(40, 40)
    container:ClearAllPoints()
    
    -- Posicionamiento relativo al Nameplate
    local xOff = FellowKickDB.xOffset or 0
    local yOff = FellowKickDB.yOffset or 0
    
    if FellowKickDB.position == "TOP" then
        container:SetPoint("BOTTOM", plate, "TOP", xOff, FellowKickDB.y + yOff)
    elseif FellowKickDB.position == "LEFT" then
        container:SetPoint("RIGHT", plate, "LEFT", -FellowKickDB.x + xOff, yOff)
    elseif FellowKickDB.position == "RIGHT" then
        container:SetPoint("LEFT", plate, "RIGHT", FellowKickDB.x + xOff, yOff)
    end
    
    local now = GetTime()
    local currentSize = 24 * (FellowKickDB.scale or 1.2)
    
    -- Verificar si ESTE nameplate corresponde al focus usando UnitIsUnit (técnica Platynator)
    local isMyFocus = UnitIsUnit("focus", unitID)
    
    -- SOLO mostrar el icono del jugador local en el nameplate
    local myName = UnitName("player")
    local myInfo = GroupStatus[myName]
    
    if isMyFocus and myInfo then
        local widget = container.portraits[1]
        if not widget then
            widget = CreateUnitWidget(container)
            container.portraits[1] = widget
        end

        -- Revertir a lógica simple de tamaño (SetSize al contenedor principal)
        -- Los hijos (classContainer, markerContainer) deben tener tamaños relativos o fijos en CreateUnitWidget
        -- Para evitar errores de cálculo en runtime, simplemente escalamos el widget principal si fuera necesario
        -- O confiamos en que CreateUnitWidget use el tamaño correcto si se recreara, pero como se recicla:
        -- Forzamos el tamaño de los hijos explícitamente pero SIN re-anchoring complejo por ahora
        
        widget:SetSize(currentSize * 2 + 2, currentSize)
        if widget.classContainer then widget.classContainer:SetSize(currentSize, currentSize) end
        if widget.markerContainer then widget.markerContainer:SetSize(currentSize, currentSize) end
        
        widget:Show()
        widget:ClearAllPoints()
        widget:SetPoint("CENTER", container, "CENTER", 0, 0)

        -- Icono de Clase
        local class = myInfo.class or "PRIEST"
        local coords = CLASS_ICON_TCOORDS[class]
        if coords then widget.icon:SetTexCoord(unpack(coords)) end

        -- Estado del Cooldown
        local timeLeft = myInfo.cdExpires - now
        if timeLeft > 0 then
            widget.icon:SetDesaturated(true)
            widget.icon:SetAlpha(0.5)
            widget.cooldownText:SetText(math.ceil(timeLeft))
            widget.cooldownText:Show()
            widget.bg:SetColorTexture(0.5, 0, 0, 0.8)
        else
            widget.icon:SetDesaturated(false)
            widget.icon:SetAlpha(1.0)
            widget.cooldownText:Hide()
            widget.bg:SetColorTexture(0, 0.3, 0, 0.8) -- Verde para disponible
        end
    else
        -- Ocultar widget si no es el focus
        if container.portraits[1] then
            container.portraits[1]:Hide()
        end
    end
end

-- === 2. PANEL DE OPCIONES ===

-- Asignar a la variable forward-declared
ForceRefresh = function()
    -- Actualizar marco flotante del grupo
    UpdateGroupFrame()
    
    -- Actualizar nameplates (solo icono del jugador)
    for _, plate in pairs(C_NamePlate.GetNamePlates()) do
        if plate.UnitFrame and plate.UnitFrame.unit then
            UpdateNameplateWidget(plate.UnitFrame.unit)
        elseif plate.unitToken then
            UpdateNameplateWidget(plate.unitToken)
        end
    end
end

local function InitHelpFrame()
    if FellowKickHelpFrame then 
        FellowKickHelpFrame:Show()
        return 
    end
    
    local frame = CreateFrame("Frame", "FellowKickHelpFrame", UIParent, "BasicFrameTemplateWithInset")
    frame:SetSize(600, 400)
    frame:SetPoint("CENTER")
    frame:SetFrameStrata("DIALOG") -- Para que salga por encima de otras ventanas
    frame:SetToplevel(true)
    frame:SetMovable(true)
    frame:EnableMouse(true)
    frame:RegisterForDrag("LeftButton")
    frame:SetScript("OnDragStart", frame.StartMoving)
    frame:SetScript("OnDragStop", frame.StopMovingOrSizing)
    
    frame.TitleBg:SetHeight(30)
    frame.TitleText:SetText("FellowKick - " .. L("btn_help"))
    
    local scrollFrame = CreateFrame("ScrollFrame", nil, frame, "UIPanelScrollFrameTemplate")
    scrollFrame:SetPoint("TOPLEFT", 10, -30)
    scrollFrame:SetPoint("BOTTOMRIGHT", -30, 10)
    
    local content = CreateFrame("Frame", nil, scrollFrame)
    content:SetSize(550, 600)
    scrollFrame:SetScrollChild(content)
    
    local lblManual = content:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    lblManual:SetPoint("TOPLEFT", 10, -10)
    lblManual:SetText("|cFF00FF00" .. L("howto_title") .. "|r")

    local function CreateManualLine(relativeTo, textKey, yOffset)
        local line = content:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
        line:SetPoint("TOPLEFT", relativeTo, "BOTTOMLEFT", 0, yOffset)
        line:SetWidth(530)
        line:SetJustifyH("LEFT")
        line:SetText(L(textKey))
        return line
    end

    local man1 = CreateManualLine(lblManual, "howto_role", -15)
    local man2 = CreateManualLine(man1, "howto_macro_btn", -10)
    local man3 = CreateManualLine(man2, "howto_macro_use", -10)
    local man4 = CreateManualLine(man3, "howto_note", -15)
    man4:SetTextColor(1, 0.8, 0, 1) -- Amarillo para la nota
    
    -- Exponer para actualizar textos si cambia idioma
    frame.RefreshTexts = function()
        frame.TitleText:SetText("FellowKick - " .. L("btn_help"))
        lblManual:SetText("|cFF00FF00" .. L("howto_title") .. "|r")
        man1:SetText(L("howto_role"))
        man2:SetText(L("howto_macro_btn"))
        man3:SetText(L("howto_macro_use"))
        man4:SetText(L("howto_note"))
    end
end

local function InitOptionsPanel()
    local panel = CreateFrame("Frame", "FellowKickOptions", UIParent)

    -- === Nuevo: Botón de Ayuda (Abre ventana aparte) ===
    local btnHelp = CreateFrame("Button", nil, panel, "UIPanelButtonTemplate")
    btnHelp:SetPoint("TOPRIGHT", -16, -16)
    btnHelp:SetSize(150, 25)
    btnHelp:SetText(L("btn_help"))
    btnHelp:SetScript("OnClick", function()
        InitHelpFrame()
    end)
    
    local title = panel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    title:SetPoint("TOPLEFT", 16, -16)
    title:SetText("FellowKick |cFF00FF00v1.2.2|r")

    local subTitle = panel:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
    subTitle:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -8)
    subTitle:SetText("Author: Grondy. Coordinación de cortes para M+.")

    -- Posición
    local lblPos = panel:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    lblPos:SetPoint("TOPLEFT", subTitle, "BOTTOMLEFT", 0, -20)
    lblPos:SetText("Posición:")

    local function CreateRadio(text, value, x, y)
        local btn = CreateFrame("CheckButton", nil, panel, "UIRadioButtonTemplate")
        btn:SetPoint("TOPLEFT", lblPos, "BOTTOMLEFT", x, y)
        btn.text:SetText(text)
        btn:SetScript("OnClick", function(self)
            FellowKickDB.position = value
            FellowKickDB.x = (value == "TOP") and 0 or 10
            FellowKickDB.y = (value == "TOP") and 35 or 0
            panel.radioTop:SetChecked(value == "TOP")
            panel.radioLeft:SetChecked(value == "LEFT")
            panel.radioRight:SetChecked(value == "RIGHT")
            ForceRefresh()
        end)
        return btn
    end

    panel.radioTop = CreateRadio("Arriba", "TOP", 0, -10)
    panel.radioLeft = CreateRadio("Izquierda", "LEFT", 100, -10)
    panel.radioRight = CreateRadio("Derecha", "RIGHT", 200, -10)

    panel:SetScript("OnShow", function()
        panel.radioTop:SetChecked(FellowKickDB.position == "TOP")
        panel.radioLeft:SetChecked(FellowKickDB.position == "LEFT")
        panel.radioRight:SetChecked(FellowKickDB.position == "RIGHT")
        -- Actualizar dropdown de rol
        if panel.roleDropdown then
            UIDropDownMenu_SetText(panel.roleDropdown, FellowKickDB.myRole or "Ninguno")
        end
    end)

    -- Slider Tamaño de icono en Nameplate
    local lblScale = panel:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    lblScale:SetPoint("TOPLEFT", lblPos, "BOTTOMLEFT", 0, -50)
    lblScale:SetText("Escala del icono (Nameplate):")
    
    local slider = CreateFrame("Slider", "FKScaleSlider", panel, "OptionsSliderTemplate")
    slider:SetPoint("TOPLEFT", lblScale, "BOTTOMLEFT", 0, -15)
    slider:SetWidth(200)
    slider:SetMinMaxValues(0.8, 2.5)
    slider:SetValueStep(0.1)
    slider:SetObeyStepOnDrag(true)
    slider.Low:SetText("0.8")
    slider.High:SetText("2.5")
    slider:SetScript("OnValueChanged", function(self, value)
        local val = math.floor(value * 10 + 0.5) / 10
        FellowKickDB.scale = val
        self.Text:SetText(L("scale") .. " " .. val)
        ForceRefresh()
    end)
    slider:SetValue(FellowKickDB.scale or 1.2)

    -- Sliders de Offset X / Y
    local sliderX = CreateFrame("Slider", "FKOffsetXSlider", panel, "OptionsSliderTemplate")
    sliderX:SetPoint("TOPLEFT", slider, "BOTTOMLEFT", 0, -25)
    sliderX:SetWidth(200)
    sliderX:SetMinMaxValues(-100, 100)
    sliderX:SetValueStep(1)
    sliderX:SetObeyStepOnDrag(true)
    sliderX.Low:SetText("-100")
    sliderX.High:SetText("100")
    sliderX:SetScript("OnValueChanged", function(self, value)
        local val = math.floor(value)
        FellowKickDB.xOffset = val
        self.Text:SetText(L("x_offset") .. " " .. val)
        ForceRefresh()
    end)
    sliderX:SetValue(FellowKickDB.xOffset or 0)

    local sliderY = CreateFrame("Slider", "FKOffsetYSlider", panel, "OptionsSliderTemplate")
    sliderY:SetPoint("TOPLEFT", sliderX, "BOTTOMLEFT", 0, -25)
    sliderY:SetWidth(200)
    sliderY:SetMinMaxValues(-100, 100)
    sliderY:SetValueStep(1)
    sliderY:SetObeyStepOnDrag(true)
    sliderY.Low:SetText("-100")
    sliderY.High:SetText("100")
    sliderY:SetScript("OnValueChanged", function(self, value)
        local val = math.floor(value)
        FellowKickDB.yOffset = val
        self.Text:SetText(L("y_offset") .. " " .. val)
        ForceRefresh()
    end)
    sliderY:SetValue(FellowKickDB.yOffset or 0)

    -- === SECCIÓN: Marco de Grupo ===
    local lblGroupFrame = panel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    lblGroupFrame:SetPoint("TOPLEFT", sliderY, "BOTTOMLEFT", 0, -30)
    lblGroupFrame:SetText("|cFF00FF00Marco de Grupo|r")
    
    -- Slider Escala del marco de grupo
    local lblGroupScale = panel:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    lblGroupScale:SetPoint("TOPLEFT", lblGroupFrame, "BOTTOMLEFT", 0, -10)
    lblGroupScale:SetText("Escala del marco de grupo:")
    
    local sliderGroup = CreateFrame("Slider", "FKGroupScaleSlider", panel, "OptionsSliderTemplate")
    sliderGroup:SetPoint("TOPLEFT", lblGroupScale, "BOTTOMLEFT", 0, -15)
    sliderGroup:SetWidth(200)
    sliderGroup:SetMinMaxValues(0.7, 2.0)
    sliderGroup:SetValueStep(0.1)
    sliderGroup:SetObeyStepOnDrag(true)
    sliderGroup.Low:SetText("0.7")
    sliderGroup.High:SetText("2.0")
    sliderGroup:SetScript("OnValueChanged", function(self, value)
        local val = math.floor(value * 10 + 0.5) / 10
        FellowKickDB.groupFrameScale = val
        self.Text:SetText("Escala: " .. val)
        -- Aplicar escala al marco de grupo
        if GroupFrame then
            GroupFrame:SetScale(val)
        end
    end)
    FellowKickDB.groupFrameScale = FellowKickDB.groupFrameScale or 1.0
    sliderGroup:SetValue(FellowKickDB.groupFrameScale)
    
    -- === SECCIÓN: Rol del Jugador ===
    local lblRole = panel:CreateFontString(nil, "ARTWORK", "GameFontNormal")
    lblRole:SetPoint("TOPLEFT", sliderGroup, "BOTTOMLEFT", 0, -25)
    lblRole:SetText("Tu rol (marca predefinida):")
    
    -- Dropdown para seleccionar rol
    local roleDropdown = CreateFrame("Frame", "FKRoleDropdown", panel, "UIDropDownMenuTemplate")
    roleDropdown:SetPoint("TOPLEFT", lblRole, "BOTTOMLEFT", -15, -5)
    panel.roleDropdown = roleDropdown
    
    local roleOptions = {
        { text = "Tank ", value = "Tank", icon = 6 },
        { text = "Healer ", value = "Healer", icon = 4 },
        { text = "DPS 1 ", value = "DPS1", icon = 1 },
        { text = "DPS 2 ", value = "DPS2", icon = 3 },
        { text = "DPS 3 ", value = "DPS3", icon = 8 },
        { text = "Remove", value = nil, icon = 0 },
    }
    
    local function RoleDropdown_Initialize(self, level)
        for _, option in ipairs(roleOptions) do
            local info = UIDropDownMenu_CreateInfo()
            info.text = option.text
            info.value = option.value
            info.checked = (FellowKickDB.myRole == option.value)
            info.func = function()
                FellowKickDB.myRole = option.value
                UIDropDownMenu_SetText(roleDropdown, option.text)
                -- Transmitir al grupo
                BroadcastMyTarget()
                ForceRefresh()
                print("|cFF00FF00[FellowKick]|r Rol asignado: " .. (option.value or "Ninguno"))
            end
            UIDropDownMenu_AddButton(info, level)
        end
    end
    
    UIDropDownMenu_SetWidth(roleDropdown, 150)
    UIDropDownMenu_SetText(roleDropdown, FellowKickDB.myRole or "Ninguno")
    UIDropDownMenu_Initialize(roleDropdown, RoleDropdown_Initialize)
    
    -- === SECCIÓN: Crear Macros ===
    local lblMacros = panel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    lblMacros:SetPoint("TOPLEFT", roleDropdown, "BOTTOMLEFT", 15, -25)
    lblMacros:SetText("|cFF00FF00Macros de Focus|r")
    
    local lblMacrosDesc = panel:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
    lblMacrosDesc:SetPoint("TOPLEFT", lblMacros, "BOTTOMLEFT", 0, -5)
    lblMacrosDesc:SetText("Crea 5 macros: Focus + Marca para cada rol")
    
    -- Función para crear los macros
    local function CreateFellowKickMacros()
        local macroDefinitions = {
            { name = "FK Tank", icon = "INV_Misc_QuestionMark", marker = 6, 
              body = "#showtooltip\n/focus [@mouseover,exists,harm][@target,exists,harm]\n/tm 6" },
            { name = "FK Healer", icon = "INV_Misc_QuestionMark", marker = 4,
              body = "#showtooltip\n/focus [@mouseover,exists,harm][@target,exists,harm]\n/tm 4" },
            { name = "FK DPS1", icon = "INV_Misc_QuestionMark", marker = 1,
              body = "#showtooltip\n/focus [@mouseover,exists,harm][@target,exists,harm]\n/tm 1" },
            { name = "FK DPS2", icon = "INV_Misc_QuestionMark", marker = 3,
              body = "#showtooltip\n/focus [@mouseover,exists,harm][@target,exists,harm]\n/tm 3" },
            { name = "FK DPS3", icon = "INV_Misc_QuestionMark", marker = 8,
              body = "#showtooltip\n/focus [@mouseover,exists,harm][@target,exists,harm]\n/tm 8" },
            -- Macro de interrupt en focus (reemplazar SPELL con tu habilidad de interrupt)
            { name = "FK Interrupt", icon = "INV_Misc_QuestionMark", marker = 0,
              body = "#showtooltip\n/cast [@focus,exists][] SPELL" },
        }

        
        local created = 0
        local skipped = 0
        
        for _, macroDef in ipairs(macroDefinitions) do
            -- Verificar si el macro ya existe
            local existingIndex = GetMacroIndexByName(macroDef.name)
            if existingIndex == 0 then
                -- No existe, crearlo
                local numAccountMacros, numCharMacros = GetNumMacros()
                if numAccountMacros < MAX_ACCOUNT_MACROS then
                    CreateMacro(macroDef.name, macroDef.icon, macroDef.body, nil)
                    created = created + 1
                else
                    print("|cFFFF0000[FellowKick]|r No hay espacio para macro: " .. macroDef.name)
                end
            else
                skipped = skipped + 1
            end
        end
        
        if created > 0 then
            print("|cFF00FF00[FellowKick]|r Creados " .. created .. " macros nuevos")
        end
        if skipped > 0 then
            print("|cFFFFFF00[FellowKick]|r " .. skipped .. " macros ya existían (omitidos)")
        end
        if created == 0 and skipped == 0 then
            print("|cFFFF0000[FellowKick]|r No se pudieron crear macros")
        end
    end
    
    -- Botón para crear macros
    local btnCreateMacros = CreateFrame("Button", nil, panel, "UIPanelButtonTemplate")
    btnCreateMacros:SetPoint("TOPLEFT", lblMacrosDesc, "BOTTOMLEFT", 0, -10)
    btnCreateMacros:SetSize(180, 25)
    btnCreateMacros:SetText(L("create_macros_btn"))
    btnCreateMacros:SetScript("OnClick", function()
        CreateFellowKickMacros()
    end)
    
    -- Texto informativo sobre los macros
    local lblMacrosInfo = panel:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
    lblMacrosInfo:SetPoint("TOPLEFT", btnCreateMacros, "BOTTOMLEFT", 0, -8)
    lblMacrosInfo:SetText(L("macros_info"))

    -- === SECCIÓN: Idioma ===
    local lblLang = panel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
    lblLang:SetPoint("TOPLEFT", lblMacrosInfo, "BOTTOMLEFT", 0, -25)
    lblLang:SetText("|cFF00FF00" .. L("language") .. "|r")
    
    -- Dropdown para seleccionar idioma
    local langDropdown = CreateFrame("Frame", "FKLanguageDropdown", panel, "UIDropDownMenuTemplate")
    langDropdown:SetPoint("TOPLEFT", lblLang, "BOTTOMLEFT", -15, -5)
    panel.langDropdown = langDropdown
    
    local function GetCurrentLangName()
        local currentCode = FellowKickDB.locale or "en"
        if FellowKick.AvailableLanguages then
            for _, lang in ipairs(FellowKick.AvailableLanguages) do
                if lang.code == currentCode then
                    return lang.name
                end
            end
        end
        return "English"
    end
    
    local function LangDropdown_Initialize(self, level)
        if not FellowKick.AvailableLanguages then return end
        for _, lang in ipairs(FellowKick.AvailableLanguages) do
            local info = UIDropDownMenu_CreateInfo()
            info.text = lang.name
            info.value = lang.code
            info.checked = (FellowKickDB.locale == lang.code)
            info.func = function()
                FellowKickDB.locale = lang.code
                UIDropDownMenu_SetText(langDropdown, lang.name)
                -- Actualizar textos del panel dinámicamente
                if panel.RefreshTexts then
                    panel.RefreshTexts()
                end
                print("|cFF00FF00[FellowKick]|r " .. L("language_changed"))
            end
            UIDropDownMenu_AddButton(info, level)
        end
    end
    
    FellowKickDB.locale = FellowKickDB.locale or "en"
    UIDropDownMenu_SetWidth(langDropdown, 150)
    UIDropDownMenu_SetText(langDropdown, GetCurrentLangName())
    UIDropDownMenu_Initialize(langDropdown, LangDropdown_Initialize)


    
    -- Función para actualizar todos los textos del panel
    panel.RefreshTexts = function()
        title:SetText("FellowKick |cFF00FF00v1.2.2|r")
        subTitle:SetText(L("author") .. ". " .. L("description"))
        lblPos:SetText(L("position"))
        panel.radioTop.text:SetText(L("top"))
        panel.radioLeft.text:SetText(L("left"))
        panel.radioRight.text:SetText(L("right"))
        lblScale:SetText(L("nameplate_scale"))
        slider.Text:SetText(L("scale") .. " " .. (FellowKickDB.scale or 1.2))
        sliderX.Text:SetText(L("x_offset") .. " " .. (FellowKickDB.xOffset or 0))
        sliderY.Text:SetText(L("y_offset") .. " " .. (FellowKickDB.yOffset or 0))
        lblGroupFrame:SetText("|cFF00FF00" .. L("group_frame") .. "|r")
        lblGroupScale:SetText(L("group_scale"))
        lblRole:SetText(L("your_role"))
        lblMacros:SetText("|cFF00FF00" .. L("macros_section") .. "|r")
        lblMacrosDesc:SetText(L("create_macros_desc"))
        btnCreateMacros:SetText(L("create_macros_btn"))
        lblMacrosInfo:SetText(L("macros_info"))
        lblLang:SetText("|cFF00FF00" .. L("language") .. "|r")
        
        btnHelp:SetText(L("btn_help"))
        
        -- Si la ventana de ayuda está abierta, actualizarla también
        if FellowKickHelpFrame and FellowKickHelpFrame.RefreshTexts then
            FellowKickHelpFrame.RefreshTexts()
        end
        
        -- Actualizar dropdown de rol
        UIDropDownMenu_SetText(roleDropdown, FellowKickDB.myRole or L("none"))
    end

    local category = Settings.RegisterCanvasLayoutCategory(panel, "FellowKick")
    Settings.RegisterAddOnCategory(category)
    FellowKickOptions.CategoryID = category:GetID()
end





-- === 3. LÓGICA DE SINCRONIZACIÓN Y COMUNICACIÓN ===

-- Escanear todos los miembros del grupo y agregarlos a GroupStatus
local function ScanGroupMembers()
    local myName = UnitName("player")
    
    -- Agregar al jugador local primero
    if not GroupStatus[myName] then
        local _, c = UnitClass("player")
        GroupStatus[myName] = { class = c, cdExpires = 0 }
    end
    
    -- No escanear si no estamos en grupo
    if not IsInAnyGroup() then
        -- Limpiar otros jugadores si salimos del grupo
        for name, _ in pairs(GroupStatus) do
            if name ~= myName then
                GroupStatus[name] = nil
            end
        end
        return
    end
    
    -- Construir set de miembros ACTUALES del grupo
    local currentMembers = {}
    currentMembers[myName] = true
    
    -- Escanear party members
    for i = 1, 4 do
        local unitID = "party" .. i
        if UnitExists(unitID) then
            local name = UnitName(unitID)
            if name and name ~= myName then
                currentMembers[name] = true
                local _, classToken = UnitClass(unitID)
                if not GroupStatus[name] then
                    GroupStatus[name] = { class = classToken, cdExpires = 0 }
                else
                    -- Siempre actualizar la clase al escanear (corrige iconos del grupo anterior)
                    GroupStatus[name].class = classToken
                end
            end
        end
    end
    
    -- Escanear raid members (si estamos en raid)
    if IsInRaid() then
        for i = 1, 40 do
            local unitID = "raid" .. i
            if UnitExists(unitID) then
                local name = UnitName(unitID)
                if name and name ~= myName then
                    currentMembers[name] = true
                    local _, classToken = UnitClass(unitID)
                    if not GroupStatus[name] then
                        GroupStatus[name] = { class = classToken, cdExpires = 0 }
                    else
                        GroupStatus[name].class = classToken
                    end
                end
            end
        end
    end
    
    -- Eliminar jugadores que ya NO están en el grupo actual
    for name, _ in pairs(GroupStatus) do
        if not currentMembers[name] then
            GroupStatus[name] = nil
        end
    end
end

-- Asignar a la variable forward-declared
BroadcastMyTarget = function()
    -- Escanear grupo primero para tener todos los miembros
    ScanGroupMembers()
    
    local myName = UnitName("player")
    local hasFocus = UnitExists("focus") and not UnitIsDead("focus") and UnitCanAttack("player", "focus")
    
    -- Obtener marca de raid de forma completamente segura
    -- Usamos doble pcall: uno para GetRaidTargetIndex y otro para verificar el resultado
    local focusMarker = 0
    if hasFocus then
        local success, rawResult = pcall(function()
            local mark = GetRaidTargetIndex("focus")
            -- Verificar que es un número válido DENTRO del pcall
            if mark ~= nil and type(mark) == "number" and mark >= 1 and mark <= 8 then
                return mark
            end
            return 0
        end)
        if success and type(rawResult) == "number" then
            focusMarker = rawResult
        end
    end
    
    -- Obtener marca predefinida del rol del jugador
    local predefinedMark = 0
    if FellowKickDB.myRole and FellowKickDB.predefinedMarks then
        predefinedMark = FellowKickDB.predefinedMarks[FellowKickDB.myRole] or 0
    end
    
    if GroupStatus[myName] then
        GroupStatus[myName].hasFocus = hasFocus
        GroupStatus[myName].focusMarker = focusMarker  -- Ahora siempre es un número
        GroupStatus[myName].predefinedMark = predefinedMark
    end
    
    -- Transmitir al grupo
    local channel = GetAddonChannel()
    if channel then
        -- Enviar marca del focus
        C_ChatInfo.SendAddonMessage(PREFIX, "M:" .. focusMarker, channel)
        -- Enviar marca predefinida del rol
        if predefinedMark > 0 then
            C_ChatInfo.SendAddonMessage(PREFIX, "R:" .. predefinedMark, channel)
        end
    end
end





local function TriggerMyKick(spellID)
    local duration = GetSpecAwareDuration(spellID)
    if not duration then return end

    local myName = UnitName("player")
    local now = GetTime()

    if not GroupStatus[myName] then
        local _, c = UnitClass("player")
        GroupStatus[myName] = { class = c, cdExpires = 0, targetGUID = nil }
    end

    GroupStatus[myName].cdExpires = now + duration

    local channel = GetAddonChannel()
    if channel then
        C_ChatInfo.SendAddonMessage(PREFIX, tostring(duration), channel)
    end
end

-- === 4. DETECCIÓN DE INTERRUPCIONES ===

-- Command Demon spell ID (Warlock - ordena a la mascota usar su habilidad)
local COMMAND_DEMON_SPELL_ID = 119898

-- Warlock pet interrupt spell IDs
local WARLOCK_PET_INTERRUPTS = {
    [89766] = 30,   -- Axe Toss (Felguard)
    [119914] = 24,  -- Command Demon: Spell Lock
    [19647] = 24,   -- Spell Lock (Felhunter)
    [119910] = 24,  -- Spell Lock (Pet version)
    [132409] = 24,  -- Spell Lock (Grimoire)
}

-- Estado del cooldown anterior para detectar cambios
local lastWarlockCDState = nil

-- Función para detectar si el jugador es Warlock
local function IsPlayerWarlock()
    local _, playerClass = UnitClass("player")
    return playerClass == "WARLOCK"
end

-- ============================================================
-- NOTA PARA WARLOCKS: 
-- Blizzard ha bloqueado la detección automática de interrupciones de mascota.
-- Usa este macro para que el addon detecte tu interrupción:
--
-- /cast [pet:Felhunter] Spell Lock; [pet:Felguard] Axe Toss
-- /run FellowKick_WarlockKick()
--
-- ============================================================

-- Función global para que Warlocks puedan notificar manualmente su interrupción via macro
function FellowKick_WarlockKick()
    local _, playerClass = UnitClass("player")
    if playerClass ~= "WARLOCK" then return end
    
    -- Determinar qué mascota tiene el Warlock y el CD correspondiente
    local petType = UnitCreatureFamily("pet")
    local spellID, duration
    
    if petType == "Felguard" then
        spellID = 89766  -- Axe Toss
        duration = 30
    else
        spellID = 19647  -- Spell Lock (default para Felhunter y otros)
        duration = 24
    end
    
    if KICK_SPELL_IDS[spellID] then
        TriggerMyKick(spellID)
        ForceRefresh()
    end
end

local function OnSpellCastSucceeded(unit, castGUID, spellID)
    -- Detectar interrupciones del jugador, mascota (Warlock) y vehículos
    if unit ~= "player" and unit ~= "pet" and unit ~= "vehicle" then return end
    
    -- Verificar si el spell es una interrupción conocida
    local duration = KICK_SPELL_IDS[spellID]
    if duration then
        TriggerMyKick(spellID)
        ForceRefresh()
    end
end

-- === 5. MANEJADOR PRINCIPAL DE EVENTOS ===

local f = CreateFrame("Frame")

local function OnEvent(self, event, ...)
    if event == "PLAYER_ENTERING_WORLD" then
        if not isInitialized then
            C_ChatInfo.RegisterAddonMessagePrefix(PREFIX)
            InitOptionsPanel()
            
            -- Asegurar que predefinedMarks exista (después de cargar SavedVariables)
            if FellowKickDB.predefinedMarks == nil then
                FellowKickDB.predefinedMarks = {
                    ["Tank"] = 6,      
                    ["Healer"] = 4,    
                    ["DPS1"] = 1,      
                    ["DPS2"] = 3,      
                    ["DPS3"] = 8,      
                }
                print("|cFF00FF00[FellowKick]|r Inicializadas marcas predefinidas")
            end
            
            -- Aplicar escala del marco de grupo guardada
            FellowKickDB.groupFrameScale = FellowKickDB.groupFrameScale or 1.0
            if GroupFrame then
                GroupFrame:SetScale(FellowKickDB.groupFrameScale)
            end
            
            isInitialized = true
        end

        BroadcastMyTarget()

        
    elseif event == "PLAYER_FOCUS_CHANGED" then
        BroadcastMyTarget()
        ForceRefresh()
    
    elseif event == "GROUP_ROSTER_UPDATE" or event == "PARTY_MEMBERS_CHANGED" then
        -- Escanear grupo cuando alguien entra o sale
        ScanGroupMembers()
        ForceRefresh()
        
    elseif event == "NAME_PLATE_UNIT_ADDED" then
        local unitID = ...
        UpdateNameplateWidget(unitID)
        
    elseif event == "NAME_PLATE_UNIT_REMOVED" then
        local unitID = ...
        local plate = C_NamePlate.GetNamePlateForUnit(unitID)
        if plate and plate.FellowKickContainer then
            for _, widget in pairs(plate.FellowKickContainer.portraits) do
                widget:Hide()
            end
        end
        
    elseif event == "UNIT_SPELLCAST_SUCCEEDED" then
        local unit, castGUID, spellID = ...
        OnSpellCastSucceeded(unit, castGUID, spellID)
        
    elseif event == "CHAT_MSG_ADDON" then
        local prefix, message, channel, sender = ...
        if prefix ~= PREFIX then return end
        
        -- Limpiar nombre del sender
        local cleanName = sender:match("([^-]+)")
        if cleanName == UnitName("player") then return end
        
        -- Función helper para obtener la clase de un miembro del grupo
        -- Usa el segundo valor de UnitClass que siempre es el token en inglés (ej: "DEMONHUNTER")
        local function GetGroupMemberClass(searchName)
            -- Normalizar el nombre (sin realm)
            local cleanSearchName = searchName:match("([^-]+)")
            
            -- Buscar en party
            for i = 1, 4 do
                local unitID = "party" .. i
                if UnitExists(unitID) then
                    local unitName = UnitName(unitID)
                    if unitName then
                        local cleanUnitName = unitName:match("([^-]+)") or unitName
                        if cleanUnitName == cleanSearchName then
                            local _, classToken = UnitClass(unitID)
                            return classToken  -- Siempre en inglés: "WARRIOR", "DEMONHUNTER", etc.
                        end
                    end
                end
            end
            -- Buscar en raid
            for i = 1, 40 do
                local unitID = "raid" .. i
                if UnitExists(unitID) then
                    local unitName = UnitName(unitID)
                    if unitName then
                        local cleanUnitName = unitName:match("([^-]+)") or unitName
                        if cleanUnitName == cleanSearchName then
                            local _, classToken = UnitClass(unitID)
                            return classToken
                        end
                    end
                end
            end
            return "PRIEST"  -- Fallback
        end
        
        -- Mensaje de Target: "T:GUID|NOMBRE" o "T:nil|nil"
        if message:sub(1,2) == "T:" then
            local data = message:sub(3)
            local guid, name = strsplit("|", data)
            if guid == "nil" then guid = nil end
            if name == "nil" then name = nil end
            
            if not GroupStatus[cleanName] then
                GroupStatus[cleanName] = { class = GetGroupMemberClass(cleanName), cdExpires = 0 }
            else
                -- Actualizar clase si aún no la tenemos
                if GroupStatus[cleanName].class == "PRIEST" then
                    GroupStatus[cleanName].class = GetGroupMemberClass(cleanName)
                end
            end
            GroupStatus[cleanName].targetGUID = guid
            GroupStatus[cleanName].targetName = name
        
        -- Mensaje de Raid Marker: "M:MARKER" (0-8)
        elseif message:sub(1,2) == "M:" then
            local marker = tonumber(message:sub(3)) or 0
            if not GroupStatus[cleanName] then
                GroupStatus[cleanName] = { class = GetGroupMemberClass(cleanName), cdExpires = 0 }
            else
                if GroupStatus[cleanName].class == "PRIEST" then
                    GroupStatus[cleanName].class = GetGroupMemberClass(cleanName)
                end
            end
            GroupStatus[cleanName].focusMarker = marker
            GroupStatus[cleanName].hasFocus = (marker > 0)
        
        -- Mensaje de Marca Predefinida: "R:MARKER" (1-8)
        elseif message:sub(1,2) == "R:" then
            local marker = tonumber(message:sub(3)) or 0
            if not GroupStatus[cleanName] then
                GroupStatus[cleanName] = { class = GetGroupMemberClass(cleanName), cdExpires = 0 }
            else
                if GroupStatus[cleanName].class == "PRIEST" then
                    GroupStatus[cleanName].class = GetGroupMemberClass(cleanName)
                end
            end
            GroupStatus[cleanName].predefinedMark = marker
        
        else
            -- Mensaje de Cooldown (número puro)
            local duration = tonumber(message)
            if duration and duration > 0 then
                if not GroupStatus[cleanName] then
                    GroupStatus[cleanName] = { class = GetGroupMemberClass(cleanName), cdExpires = 0, targetGUID = nil }
                else
                    if GroupStatus[cleanName].class == "PRIEST" then
                        GroupStatus[cleanName].class = GetGroupMemberClass(cleanName)
                    end
                end
                GroupStatus[cleanName].cdExpires = GetTime() + duration
            end
        end
        ForceRefresh()
    end
end

f:SetScript("OnEvent", OnEvent)
f:RegisterEvent("PLAYER_ENTERING_WORLD")
f:RegisterEvent("PLAYER_FOCUS_CHANGED")
f:RegisterEvent("GROUP_ROSTER_UPDATE")
f:RegisterEvent("NAME_PLATE_UNIT_ADDED")
f:RegisterEvent("NAME_PLATE_UNIT_REMOVED")
f:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
f:RegisterEvent("CHAT_MSG_ADDON")
f:RegisterEvent("UPDATE_MOUSEOVER_UNIT")
f:RegisterEvent("PLAYER_REGEN_DISABLED")
f:RegisterEvent("PLAYER_REGEN_ENABLED")


-- === AUTO-MARKING SYSTEM ===


-- Track already marked mobs to avoid re-marking
local MarkedMobs = {}

-- Check if player can mark targets (leader or assist)
local function CanMark()
    if not IsInAnyGroup() then return true end
    if UnitIsGroupLeader("player") then return true end
    if UnitIsGroupAssistant("player") then return true end
    return false
end

-- Get NPC ID from GUID (with full protection for secret values)
local function GetNPCIDFromGUID(guid)
    if not guid then return nil end
    -- Use pcall for EVERYTHING - guid could be a secret value
    local success, result = pcall(function()
        if type(guid) ~= "string" then return nil end
        local parts = {strsplit("-", guid)}
        if parts[1] == "Creature" or parts[1] == "Vehicle" then
            return tonumber(parts[6])
        end
        return nil
    end)
    if success then return result end
    return nil
end

-- Buscar NPC por nombre en la base de datos (protected)
local function GetNPCIDFromName(unitName)
    if not unitName or not FellowKick or not FellowKick.InterruptMobs then 
        return nil 
    end
    -- Wrap in pcall because unitName might be a secret value
    local success, npcID, data = pcall(function()
        for id, mobData in pairs(FellowKick.InterruptMobs) do
            if mobData.name == unitName then
                return id, mobData
            end
        end
        return nil, nil
    end)
    if success then return npcID, data end
    return nil
end


-- Get NPC ID using either GUID or name fallback
local function GetNPCIDFromUnit(unitID)
    if not UnitExists(unitID) then return nil end
    
    -- Try GUID first (wrapped in pcall)
    local success, guid = pcall(UnitGUID, unitID)
    if success and guid then
        local npcID = GetNPCIDFromGUID(guid)
        if npcID then return npcID end
    end
    
    -- Fallback: try by name (always works)
    local unitName = UnitName(unitID)
    if unitName then
        local npcID = GetNPCIDFromName(unitName)
        if npcID then return npcID end
    end
    
    return nil
end


-- Try to mark a unit if it's an interrupt mob
local function TryMarkUnit(unitID)
    if not FellowKickDB or not FellowKickDB.autoMark then return end
    if not FellowKickDB.autoMark.enabled then return end
    if not CanMark() then return end
    if not UnitExists(unitID) then return end
    if UnitIsDead(unitID) then return end
    if not UnitCanAttack("player", unitID) then return end
    
    -- Get NPC ID (tries GUID first, then name fallback)
    local npcID = GetNPCIDFromUnit(unitID)
    if not npcID then return end
    
    -- Check against our database
    if not FellowKick or not FellowKick.InterruptMobs then return end
    local mobData = FellowKick.InterruptMobs[npcID]
    if not mobData then return end
    
    -- Use unit name as tracking key (since GUID may be secret)
    local unitName = UnitName(unitID)
    local trackingKey = unitName or tostring(npcID)
    
    -- Already marked this mob?
    if MarkedMobs[trackingKey] then return end
    
    -- Already has a raid marker?
    local existingMark = GetRaidTargetIndex(unitID)
    if existingMark then
        MarkedMobs[trackingKey] = existingMark
        return
    end
    
    -- Get next marker
    local marker = FellowKick.GetNextMarker()
    SetRaidTarget(unitID, marker)
    MarkedMobs[trackingKey] = marker

    
    -- Optional announcement
    local announceChannel = GetAddonChannel()
    if FellowKickDB.autoMark.announceToGroup and announceChannel then
        local markerIcons = {
            [1] = "{star}",
            [2] = "{circle}",
            [3] = "{diamond}",
            [4] = "{triangle}",
            [5] = "{moon}",
            [6] = "{square}",
            [7] = "{cross}",
            [8] = "{skull}",
        }
        local icon = markerIcons[marker] or ""
        local msg = icon .. " " .. mobData.name .. " (Interrupt)"
        SendChatMessage(msg, announceChannel)
    end
end

-- Scan all visible nameplates for interrupt mobs (on combat start)
local function ScanNameplatesForInterruptMobs()
    if not FellowKickDB or not FellowKickDB.autoMark then return end
    if not FellowKickDB.autoMark.enabled then return end
    if not FellowKickDB.autoMark.onCombat then return end
    
    for i = 1, 40 do
        local unitID = "nameplate" .. i
        if UnitExists(unitID) then
            TryMarkUnit(unitID)
        end
    end
end

-- Clear marked mobs when leaving combat
local function ClearMarkedMobs()
    wipe(MarkedMobs)
    if FellowKick and FellowKick.ResetMarkerRotation then
        FellowKick.ResetMarkerRotation()
    end
end

-- Handle mouseover marking
local function OnMouseoverUnit()
    if not FellowKickDB or not FellowKickDB.autoMark then return end
    if not FellowKickDB.autoMark.enabled then return end
    if not FellowKickDB.autoMark.onMouseover then return end
    TryMarkUnit("mouseover")
end

-- Hook into the OnEvent function
local originalOnEvent = OnEvent
local function ExtendedOnEvent(self, event, ...)
    if event == "UPDATE_MOUSEOVER_UNIT" then
        OnMouseoverUnit()
    elseif event == "PLAYER_REGEN_DISABLED" then
        -- Entering combat - scan for mobs
        C_Timer.After(0.3, ScanNameplatesForInterruptMobs)
    elseif event == "PLAYER_REGEN_ENABLED" then
        -- Leaving combat - reset markers tracking
        C_Timer.After(2, ClearMarkedMobs)
    elseif event == "NAME_PLATE_UNIT_ADDED" then
        -- Let original handler run first
        originalOnEvent(self, event, ...)
        -- Mark interrupt mobs when their nameplate appears during combat
        if InCombatLockdown() then
            local unitID = ...
            C_Timer.After(0.1, function()
                if UnitExists(unitID) then
                    TryMarkUnit(unitID)
                end
            end)
        end
    else
        originalOnEvent(self, event, ...)
    end
end
f:SetScript("OnEvent", ExtendedOnEvent)


-- Timer para actualizar widgets periódicamente
C_Timer.NewTicker(0.5, function()
    ForceRefresh()
end)

-- Slash commands
SLASH_FELLOWKICK1 = "/fk"
SlashCmdList["FELLOWKICK"] = function(msg)
    if msg == "markdebug" or msg == "md" then
        -- Activar debug de marcas
        FellowKick_DebugOnce = true
        print("|cFF00FF00[FellowKick]|r Debug de marcas activado. Esperando siguiente refresh...")
        print("  myRole = " .. tostring(FellowKickDB.myRole))
        if FellowKickDB.myRole and FellowKickDB.predefinedMarks then
            print("  marca para rol = " .. tostring(FellowKickDB.predefinedMarks[FellowKickDB.myRole]))
        end
        ForceRefresh()
    elseif msg == "debug" or msg == "d" then

        -- Mostrar info del target actual
        if UnitExists("target") then
            local name = UnitName("target")
            local npcID = GetNPCIDFromUnit("target")
            
            if npcID then
                local inDatabase = FellowKick and FellowKick.InterruptMobs and FellowKick.InterruptMobs[npcID]
                print("|cFF00FF00[FellowKick]|r Target: " .. (name or "?"))
                print("  NPC ID: |cFFFFFF00" .. npcID .. "|r")
                if inDatabase then
                    print("  Estado: |cFF00FF00EN LA LISTA|r - " .. inDatabase.name)
                else
                    print("  Estado: |cFFFF0000NO está en la lista|r")
                    print("  Para añadirlo, edita InterruptMobs.lua y añade:")
                    print("  |cFFFFFF00[" .. npcID .. "] = { name = \"" .. (name or "NombreAqui") .. "\", priority = 1, dungeon = \"NombreDungeon\" },|r")
                end
            else
                -- Si no hay NPC ID por GUID, intentar buscar por nombre
                local nameID, nameData = GetNPCIDFromName(name)
                if nameID then
                    print("|cFF00FF00[FellowKick]|r Target: " .. (name or "?"))
                    print("  NPC ID (por nombre): |cFFFFFF00" .. nameID .. "|r")
                    print("  Estado: |cFF00FF00EN LA LISTA|r - " .. nameData.name)
                else
                    print("|cFF00FF00[FellowKick]|r Target: " .. (name or "?"))
                    print("  NPC ID: |cFFFF6600No disponible (GUID protegido)|r")
                    if name then
                        print("  Buscando '" .. name .. "' en la lista... |cFFFF0000NO ENCONTRADO|r")
                    end
                end
            end
        else
            print("|cFF00FF00[FellowKick]|r Pon un mob como target y usa /fk debug")
        end
    elseif msg == "test" then
        -- Test de marcado manual
        if UnitExists("target") then
            TryMarkUnit("target")
            print("|cFF00FF00[FellowKick]|r Intentando marcar target...")
        else
            print("|cFF00FF00[FellowKick]|r Pon un mob como target y usa /fk test")
        end
    elseif msg == "list" then
        -- Mostrar cuántos mobs hay en la lista
        if FellowKick and FellowKick.InterruptMobs then
            local count = 0
            for _ in pairs(FellowKick.InterruptMobs) do count = count + 1 end
            print("|cFF00FF00[FellowKick]|r Base de datos cargada: " .. count .. " mobs")
        else
            print("|cFFFF0000[FellowKick]|r ERROR: Base de datos NO cargada!")
        end
    elseif msg == "status" then
        -- Mostrar estado de configuración
        print("|cFF00FF00[FellowKick]|r Configuración:")
        print("  autoMark.enabled: " .. tostring(FellowKickDB.autoMark and FellowKickDB.autoMark.enabled))
        print("  autoMark.onCombat: " .. tostring(FellowKickDB.autoMark and FellowKickDB.autoMark.onCombat))
        print("  autoMark.onMouseover: " .. tostring(FellowKickDB.autoMark and FellowKickDB.autoMark.onMouseover))
        print("  Puedes marcar (líder/asist): " .. tostring(CanMark()))
    elseif msg == "group" or msg == "g" then
        -- Debug: mostrar estado del grupo con marcadores
        print("|cFF00FF00[FellowKick]|r Estado del grupo:")
        local myName = UnitName("player")
        for playerName, info in pairs(GroupStatus) do
            local predMark = SafeGetMarker(info.predefinedMark)
            local focMark = SafeGetMarker(info.focusMarker)
            local predStr = predMark > 0 and "|cFF00FF00[P:" .. predMark .. "]|r" or ""
            local focStr = focMark > 0 and "|cFFFFFF00[F:" .. focMark .. "]|r" or "|cFF666666[--]|r"
            local isMe = playerName == myName and " |cFF00FFFF(Yo)|r" or ""
            print("  " .. playerName .. isMe .. ": " .. predStr .. focStr .. " hasFocus=" .. tostring(info.hasFocus))
        end
        -- También mostrar mi focus actual
        if UnitExists("focus") then
            local success, rawMark = pcall(GetRaidTargetIndex, "focus")
            local focusMark = (success and rawMark and type(rawMark) == "number") and rawMark or 0
            print("  Mi focus actual: marca " .. focusMark)
        else
            print("  Mi focus actual: ninguno")
        end
        print("  Mi rol asignado: " .. (FellowKickDB.myRole or "ninguno"))
    
    elseif msg:sub(1, 5) == "role " or msg == "role" then
        -- Asignar rol predefinido
        local roleArg = msg:sub(6):lower()
        local roleNames = {
            ["tank"] = { role = "Tank", mark = 6, icon = "{square}" },
            ["heal"] = { role = "Healer", mark = 4, icon = "{triangle}" },
            ["healer"] = { role = "Healer", mark = 4, icon = "{triangle}" },
            ["dps1"] = { role = "DPS1", mark = 1, icon = "{star}" },
            ["dps2"] = { role = "DPS2", mark = 3, icon = "{diamond}" },
            ["dps3"] = { role = "DPS3", mark = 8, icon = "{skull}" },
            ["none"] = { role = nil, mark = 0, icon = "" },
            ["ninguno"] = { role = nil, mark = 0, icon = "" },
        }
        
        if roleArg == "" or not roleNames[roleArg] then
            print("|cFF00FF00[FellowKick]|r Roles disponibles:")
            print("  /fk role tank    - " .. "{square}" .. " Cuadrado")
            print("  /fk role heal    - " .. "{triangle}" .. " Triángulo")
            print("  /fk role dps1    - " .. "{star}" .. " Estrella")
            print("  /fk role dps2    - " .. "{diamond}" .. " Diamante")
            print("  /fk role dps3    - " .. "{skull}" .. " Calavera")
            print("  /fk role none    - Sin marca")
            print("  Tu rol actual: |cFFFFFF00" .. (FellowKickDB.myRole or "ninguno") .. "|r")
        else
            local roleData = roleNames[roleArg]
            FellowKickDB.myRole = roleData.role
            if roleData.role then
                print("|cFF00FF00[FellowKick]|r Rol asignado: |cFFFFFF00" .. roleData.role .. "|r " .. roleData.icon)
            else
                print("|cFF00FF00[FellowKick]|r Rol eliminado")
            end
            -- Transmitir inmediatamente al grupo
            BroadcastMyTarget()
            ForceRefresh()
        end
    
    else
        print("|cFF00FF00[FellowKick]|r Comandos disponibles:")
        print("  /fk role [rol]  - Asignar tu rol (tank, heal, dps1, dps2, dps3)")
        print("  /fk debug - Info del NPC ID de tu target")
        print("  /fk test - Intentar marcar tu target manualmente")
        print("  /fk list - Ver cuántos mobs hay en la base de datos")
        print("  /fk status - Ver configuración actual")
        print("  /fk group - Ver marcadores del grupo")
    end
end

