local addonName, NS = ...
local GR = NS.GR -- Reference the Core Frame

-- =========================================================================
-- UI: HELPERS
-- =========================================================================

local function CreateBg(f, r, g, b, a)
    local t = f:CreateTexture(nil, "BACKGROUND")
    t:SetAllPoints()
    t:SetColorTexture(r, g, b, a)
    f.bg = t
end

local function CreateBorder(f, r, g, b, a)
    if f.border then f.border:Hide() end
    
    local border = f:CreateTexture(nil, "BORDER")
    border:SetPoint("TOPLEFT", -1, 1)
    border:SetPoint("BOTTOMRIGHT", 1, -1)
    border:SetColorTexture(r, g, b, a)
    f.border = border
end

local function SkinButton(btn)
    if not btn then return end
    
    btn:SetNormalTexture("")
    btn:SetHighlightTexture("")
    btn:SetPushedTexture("")
    btn:SetDisabledTexture("")
    
    if btn.Left then btn.Left:SetAlpha(0) end
    if btn.Middle then btn.Middle:SetAlpha(0) end
    if btn.Right then btn.Right:SetAlpha(0) end
    if btn.Top then btn.Top:SetAlpha(0) end
    if btn.Bottom then btn.Bottom:SetAlpha(0) end
    
    CreateBg(btn, 0.2, 0.2, 0.2, 1)
    CreateBorder(btn, 0, 0, 0, 1)
    
    btn:HookScript("OnEnter", function(s) 
        if s.bg then s.bg:SetColorTexture(0.3, 0.3, 0.3, 1) end 
    end)
    btn:HookScript("OnLeave", function(s) 
        if s.bg then s.bg:SetColorTexture(0.2, 0.2, 0.2, 1) end 
    end)
    btn:HookScript("OnMouseDown", function(s) 
        if s.bg then s.bg:SetColorTexture(0.1, 0.1, 0.1, 1) end 
    end)
    btn:HookScript("OnMouseUp", function(s) 
        if s.bg then s.bg:SetColorTexture(0.3, 0.3, 0.3, 1) end 
    end)
    
    local fs = btn:GetFontString()
    if fs then fs:SetTextColor(1, 1, 1) end
end

-- Export helpers to NS
NS.CreateBg = CreateBg
NS.CreateBorder = CreateBorder
NS.SkinButton = SkinButton

-- =========================================================================
-- UI: STRUCTURE & TABS
-- =========================================================================

function GR:UpdateResizeBounds()
    local currentScale = self:GetScale() or 1
    local maxWidth = 1980 / currentScale
    local maxHeight = 750 / currentScale 
    self:SetResizeBounds(1280, 750, maxWidth, maxHeight) 
end

function GR:BuildStructuralUI()
    self:SetFrameStrata("DIALOG") 
    self:SetToplevel(true)
    self:EnableMouse(true)
    self:SetMovable(true)
    self:SetResizable(true)
    self:SetClampedToScreen(true)
    self:SetSize(1280, 750) 
    self:SetPoint("CENTER")

    CreateBg(self, 0, 0, 0, 0.85)
    CreateBorder(self, 0.3, 0.3, 0.3, 1)

    self:RegisterForDrag("LeftButton")
    self:SetScript("OnDragStart", self.StartMoving)
    self:SetScript("OnDragStop", function(self)
        self:StopMovingOrSizing()
    end)
    
    self:UpdateResizeBounds()

    local resize = CreateFrame("Button", nil, self)
    resize:SetSize(16, 16); resize:SetPoint("BOTTOMRIGHT")
    resize:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Up")
    resize:SetHighlightTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Highlight")
    resize:SetScript("OnMouseDown", function() self:StartSizing("BOTTOMRIGHT") end)
    resize:SetScript("OnMouseUp", function() 
        self:StopMovingOrSizing() 
        if self.db then
            self.db.windowWidth = self:GetWidth()
            self.db.windowHeight = self:GetHeight()
        end
    end)
    
    table.insert(UISpecialFrames, self:GetName()) 
    
    -- =========================================================================
    -- AXIOM GLOBAL HEADER
    -- =========================================================================
    local axiomHeader = CreateFrame("Frame", "GRS_AxiomHeader", self)
    axiomHeader:SetHeight(30)
    axiomHeader:SetPoint("TOPLEFT", 0, 0)
    axiomHeader:SetPoint("TOPRIGHT", 0, 0)
    CreateBg(axiomHeader, 0.1, 0.1, 0.1, 1) 
    CreateBorder(axiomHeader, 0, 0, 0, 1)
    
    local axTitle = axiomHeader:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    axTitle:SetPoint("CENTER", 0, 0)
    axTitle:SetText("A.X.I.O.M. | Automated Xenial Index & Operations Matrix")
    axTitle:SetTextColor(0.4, 0.8, 1) 
    
    -- Close Button
    local close = CreateFrame("Button", nil, axiomHeader)
    close:SetPoint("TOPRIGHT", -5, -3) 
    close:SetSize(24, 24)
    close:SetNormalFontObject("GameFontNormal")
    close:SetText("X")
    close:SetScript("OnClick", function() GR:Hide() end)
    SkinButton(close)

    -- Minimize Button
    local minimize = CreateFrame("Button", nil, axiomHeader)
    minimize:SetPoint("RIGHT", close, "LEFT", -2, 0) 
    minimize:SetSize(24, 24)
    minimize:SetNormalFontObject("GameFontNormal")
    minimize:SetText("_")
    minimize:SetScript("OnClick", function() GR:ToggleMiniMode(true) end)
    SkinButton(minimize)

    -- =========================================================================
    -- SIDEBAR & CONTENT LAYOUT
    -- =========================================================================
    
    local sideBar = CreateFrame("Frame", "GRS_SideBar", self)
    sideBar:SetWidth(40)
    sideBar:SetPoint("TOPLEFT", 0, -30) 
    sideBar:SetPoint("BOTTOMLEFT", 0, 0)
    CreateBg(sideBar, 0.15, 0.15, 0.15, 1)
    CreateBorder(sideBar, 0, 0, 0, 1)
    self.SideBar = sideBar
    
    local container = CreateFrame("Frame", "GRS_ViewContainer", self)
    container:SetPoint("TOPLEFT", sideBar, "TOPRIGHT", 0, 0)
    container:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 0, 0)
    self.ViewContainer = container

    local top = CreateFrame("Frame", nil, container)
    CreateBg(top, 0.1, 0.1, 0.1, 1)
    top:SetHeight(30); top:SetPoint("TOPLEFT"); top:SetPoint("TOPRIGHT")
    self.TitleBar = top
    
    local title = top:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    title:SetPoint("LEFT", 10, 0); title:SetText("Guild Recruiter System")
    self.MainTitle = title
    
    local ioStatus = top:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    ioStatus:SetPoint("LEFT", title, "RIGHT", 10, 0)
    self.ioStatus = ioStatus; self:UpdateRaiderIOStatus()
    
    local offStatus = top:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    offStatus:SetPoint("LEFT", ioStatus, "RIGHT", 10, 0)
    self.officerStatus = offStatus
    
    self.Tabs = {}
    local tabsData = NS.Constants.TABS
    
    for i, data in ipairs(tabsData) do
        local tab = CreateFrame("Button", nil, sideBar)
        tab:SetSize(32, 32)
        tab:SetPoint("TOP", sideBar, "TOP", 0, -10 - ((i-1) * 40))
        
        local tex = tab:CreateTexture(nil, "ARTWORK")
        tex:SetAllPoints()
        tex:SetTexture(data.icon)
        tab.icon = tex
        
        tab:SetScript("OnEnter", function(s)
            GameTooltip:SetOwner(s, "ANCHOR_CURSOR")
            GameTooltip:SetText(data.title)
            GameTooltip:Show()
            if s.timer then s.timer:Cancel() end
            s.timer = C_Timer.NewTimer(5, function() GameTooltip:Hide() end)
            if s.bg then s.bg:SetColorTexture(0.3, 0.3, 0.3, 1) end
        end)
        
        tab:SetScript("OnLeave", function(s)
            GameTooltip:Hide()
            if s.timer then s.timer:Cancel() end
            if s.bg then 
                 if GR.activeTab == i then s.bg:SetColorTexture(1, 1, 1, 0.2)
                 else s.bg:SetColorTexture(0, 0, 0, 0) end
            end
        end)
        
        tab:SetScript("OnClick", function()
            if data.id == 7 and GR.OpenSettings then GR:OpenSettings() else GR:SwitchView(data.id) end
        end)
        
        local selBg = tab:CreateTexture(nil, "BACKGROUND")
        selBg:SetAllPoints(); selBg:SetColorTexture(1, 1, 1, 0.2); selBg:Hide()
        tab.selBg = selBg
        
        self.Tabs[i] = tab
    end
    
    self:BuildMiniFrame()
end

-- =========================================================================
-- UI: MODULE CONTAINERS (FIXED)
-- =========================================================================

function GR:BuildModuleContainers()
    -- Tab 2: Recruitment Blacklist
    -- Removed explicit creation to match Backup logic (External Module handles this)
    
    -- Tab 3: Requirements
    self.views[3] = CreateFrame("Frame", "GRS_RequirementsView", self.ViewContainer)
    self.views[3]:SetAllPoints(); self.views[3]:Hide()

    -- Tab 4: History
    self.views[4] = CreateFrame("Frame", "GRS_HistoryView", self.ViewContainer)
    self.views[4]:SetAllPoints(); self.views[4]:Hide()

    -- Tab 5: Guild Roster (Named Globally for Guild Roster Members.lua)
    self.views[5] = CreateFrame("Frame", "GRS_RosterListFrame", self.ViewContainer)
    self.views[5]:SetAllPoints(); self.views[5]:Hide()

    -- Tab 6: Raid Roster
    self.views[6] = CreateFrame("Frame", "GRS_RaidRosterView", self.ViewContainer)
    self.views[6]:SetAllPoints(); self.views[6]:Hide()

    -- Tab 7: Settings
    -- Removed explicit creation to match Backup logic (External Module handles this via OpenSettings)
    
    -- Tab 8: MVP
    self:BuildMVPView()
end

function GR:SwitchView(id)
    self.activeTab = id
    for i, tab in ipairs(self.Tabs) do
        if i == id then
            tab:SetAlpha(1.0)
            tab.selBg:Show()
        else
            tab:SetAlpha(0.6)
            tab.selBg:Hide()
        end
    end
    for viewId, frame in pairs(self.views) do
        if viewId == id then
            frame:Show()
        else
            frame:Hide()
        end
    end
    self.MainTitle:SetText(NS.Constants.TABS[id].title)
end

-- =========================================================================
-- UI: MINI MODE LOGIC (COMPACT 125x75)
-- =========================================================================

function GR:BuildMiniFrame()
    if self.MiniFrame then return end
    
    local f = CreateFrame("Frame", "GRS_MiniFrame", UIParent)
    f:SetSize(155, 45) -- Request: 125w x 75h
    f:SetPoint("CENTER")
    f:SetFrameStrata("DIALOG")
    f:SetMovable(true)
    f:EnableMouse(true)
    f:RegisterForDrag("LeftButton")
    f:SetScript("OnDragStart", f.StartMoving)
    f:SetScript("OnDragStop", f.StopMovingOrSizing)
    f:Hide()
    
    CreateBg(f, 0, 0, 0, 1) -- Pure Black
    CreateBorder(f, 0, 0, 0, 1) -- Black Border
    
    -- CONTROLS
    local btnClose = CreateFrame("Button", nil, f)
    btnClose:SetSize(12, 12); btnClose:SetPoint("TOPRIGHT", -2, -2)
    btnClose:SetNormalFontObject("GameFontNormalSmall"); btnClose:SetText("X")
    btnClose:SetScript("OnClick", function() GR:Hide() end)
    
    local btnMax = CreateFrame("Button", nil, f)
    btnMax:SetSize(12, 12); btnMax:SetPoint("RIGHT", btnClose, "LEFT", -2, 0)
    btnMax:SetNormalFontObject("GameFontNormalSmall"); btnMax:SetText("+")
    btnMax:SetScript("OnClick", function() GR:ToggleMiniMode(false) end)
    
    -- SINGLE LINE TEXT LAYOUT
    local container = CreateFrame("Frame", nil, f)
    container:SetPoint("LEFT", 5, 0)
    container:SetPoint("RIGHT", -5, 0)
    container:SetHeight(20)
    container:SetPoint("CENTER")
    
    -- AXIOM
    local t1 = container:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    t1:SetPoint("LEFT", 0, 0)
    t1:SetText("|cff66CCFFA.X.I.O.M.|r")
    
    -- SEPARATOR
    local t2 = container:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    t2:SetPoint("LEFT", t1, "RIGHT", 2, 0)
    t2:SetText("|cffffd100|||r") -- Gold Pipe
    
    -- ACTIVE LABEL (Dynamic Color)
    local t3 = container:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    t3:SetPoint("LEFT", t2, "RIGHT", 2, 0)
    t3:SetText("Active:")
    f.ActiveLabel = t3
    
    -- COUNT
    local t4 = container:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    t4:SetPoint("LEFT", t3, "RIGHT", 2, 0)
    t4:SetText("0/0")
    f.CountLabel = t4
    
    -- ANIMATION LOGIC (Green <-> Gold Fade over 3s)
    local totalTime = 0
    f:SetScript("OnUpdate", function(self, elapsed)
        totalTime = totalTime + elapsed
        local phase = totalTime % 6
        local r, g, b
        
        -- Green: 0, 1, 0
        -- Gold:  1, 0.82, 0
        
        if phase < 3 then
            -- Fading Green to Gold
            local p = phase / 3
            r = 0 + (1 - 0) * p
            g = 1 + (0.82 - 1) * p
            b = 0
        else
            -- Fading Gold to Green
            local p = (phase - 3) / 3
            r = 1 + (0 - 1) * p
            g = 0.82 + (1 - 0.82) * p
            b = 0
        end
        
        if f.ActiveLabel then f.ActiveLabel:SetTextColor(r, g, b) end
    end)
    
    self.MiniFrame = f
end

function GR:ToggleMiniMode(enabled)
    if enabled then
        self:Hide() -- Hide Main Frame
        if not self.MiniFrame then self:BuildMiniFrame() end
        self.MiniFrame:Show()
        self:UpdateMiniStatus()
    else
        if self.MiniFrame then self.MiniFrame:Hide() end
        self:Show() -- Show Main Frame
    end
end

function GR:UpdateMiniStatus()
    if not self.MiniFrame then return end
    local sent = self.batchSent or 0
    local total = self.batchTotal or 0
    -- Just update the number part to fit the single line
    self.MiniFrame.CountLabel:SetText(string.format("%d/%d", sent, total))
end

-- =========================================================================
-- UI: HOME VIEW
-- =========================================================================

function GR:BuildHomeView()
    local parent = CreateFrame("Frame", "GRS_HomeView", self.ViewContainer)
    parent:SetPoint("TOPLEFT", 0, -30) 
    parent:SetPoint("BOTTOMRIGHT", 0, 0)
    self.views[1] = parent

    local outerScroll = CreateFrame("ScrollFrame", "GRS_OuterScroll", parent, "UIPanelScrollFrameTemplate")
    outerScroll:SetPoint("TOPLEFT", 0, 0)
    outerScroll:SetPoint("BOTTOMRIGHT", -28, 25) 
    
    if outerScroll.ScrollBar then outerScroll.ScrollBar:Hide(); outerScroll.ScrollBar:SetWidth(0) end
    
    local content = CreateFrame("Frame", "GRS_ScrollChild", outerScroll)
    outerScroll:SetScrollChild(content)
    
    local left = CreateFrame("Frame", nil, content)
    left:SetWidth(320); left:SetPoint("TOPLEFT"); left:SetPoint("BOTTOMLEFT")
    CreateBg(left, 0.1, 0.1, 0.1, 0.5); CreateBorder(left, 0.2, 0.2, 0.2, 1)
    self:BuildLeftPane(left)

    local rightPane = CreateFrame("Frame", "GRS_RightPane", content)
    rightPane:SetWidth(500)
    rightPane:SetPoint("TOPRIGHT"); rightPane:SetPoint("BOTTOMRIGHT")
    CreateBg(rightPane, 0.05, 0.05, 0.05, 0.8)
    CreateBorder(rightPane, 0.2, 0.2, 0.2, 1)
    self:BuildWhisperPane(rightPane)

    local center = CreateFrame("Frame", "GRS_CenterPane", content)
    center:SetPoint("TOPLEFT", left, "TOPRIGHT")
    center:SetPoint("BOTTOMRIGHT", rightPane, "BOTTOMLEFT")
    self:BuildCenterPane(center)
    
    if self.BuildFilterUI then self:BuildFilterUI() end
    
    parent:SetScript("OnSizeChanged", function(self, w, h)
        local scrollW = w - 52
        local scrollH = h - 45
        local leftPaneW = 320
        local rightPaneW = 500 
        local minCenterW = 760 
        local requiredMinW = leftPaneW + minCenterW + rightPaneW
        local finalContentW = math.max(scrollW, requiredMinW)
        local finalH = math.max(scrollH, 1)
        
        content:SetWidth(finalContentW)
        content:SetHeight(finalH)
        
        local listAvailable = finalH - 115
        if listAvailable < 20 then listAvailable = 20 end

        local whisperAvailable = finalH - 50
        if whisperAvailable < 20 then whisperAvailable = 20 end

        if GR.UpdateResultsLayout then GR:UpdateResultsLayout(listAvailable) end
        if GR.UpdateWhisperLayout then GR:UpdateWhisperLayout(whisperAvailable) end
    end)
    
    GR.UpdateHomeLayout = function()
        local w, h = parent:GetSize()
        parent:GetScript("OnSizeChanged")(parent, w, h)
    end
end

-- =========================================================================
-- UI: PANES (Left, Center, Whisper)
-- =========================================================================

function GR:BuildLeftPane(parent)
    local y = -15
    local function AddText(txt, font, dy)
        local t = parent:CreateFontString(nil, "OVERLAY", font)
        t:SetPoint("TOPLEFT", 15, y + (dy or 0)); t:SetText(txt)
    end
    
    AddText("SEARCH FILTERS", "GameFontNormal", 0); y = y - 30
    
    local dFilt = CreateFrame("Button", nil, parent); CreateBg(dFilt, 0.2, 0.2, 0.2, 1)
    dFilt:SetSize(180, 24); dFilt:SetPoint("TOPLEFT", 15, y)
    local dFiltTxt = dFilt:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); dFiltTxt:SetPoint("LEFT", 5, 0); dFiltTxt:SetText("Filter: Default (All)")
    self.dFiltTxt = dFiltTxt
    
    local dFiltArrow = dFilt:CreateTexture(nil, "ARTWORK")
    dFiltArrow:SetTexture("Interface\\Buttons\\UI-ScrollBar-ScrollDownButton-Up")
    dFiltArrow:SetSize(20, 20)
    dFiltArrow:SetPoint("RIGHT", -2, 0)
    
    local dFiltList = CreateFrame("Frame", nil, dFilt); CreateBg(dFiltList, 0.1, 0.1, 0.1, 1); CreateBorder(dFiltList, 0.5, 0.5, 0.5, 1)
    dFiltList:SetSize(180, 50); dFiltList:SetPoint("TOPLEFT", dFilt, "BOTTOMLEFT", 0, -2); dFiltList:SetFrameStrata("FULLSCREEN_DIALOG"); dFiltList:Hide()
    self.dFiltList = dFiltList; 
    -- RefreshMainFilterList is logic, handled in Engine.lua
    if GR.RefreshMainFilterList then GR:RefreshMainFilterList() end
    
    dFilt:SetScript("OnClick", function() 
        if GR.RefreshMainFilterList then GR:RefreshMainFilterList() end
        dFiltList:SetShown(not dFiltList:IsShown()) 
    end)
    
    local cIcon = CreateFrame("Button", nil, parent); cIcon:SetSize(24, 24); cIcon:SetPoint("LEFT", dFilt, "RIGHT", 5, 0)
    cIcon:SetNormalTexture("Interface\\Buttons\\UI-OptionsButton")
    cIcon:SetScript("OnClick", function() if GR.FilterFrame then GR.FilterFrame.OpenCreate() end end)

    local eIcon = CreateFrame("Button", nil, parent); eIcon:SetSize(24, 24); eIcon:SetPoint("LEFT", cIcon, "RIGHT", 2, 0)
    eIcon:SetNormalTexture("Interface\\Buttons\\UI-GuildButton-PublicNote-Up") 
    eIcon:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight")
    eIcon:SetScript("OnClick", function() 
        if GR.selectedFilterData then 
            GR.FilterFrame.OpenEdit(GR.selectedFilterData)
        else
            print("|cffff0000GRS: Cannot edit Default filter. Select a custom filter first.|r")
        end
    end)
    
    y = y - 40; AddText("Level Range", "GameFontHighlightSmall", 0)
    local minB = CreateFrame("EditBox", nil, parent, "InputBoxTemplate"); minB:SetSize(40, 20); minB:SetPoint("TOPLEFT", 15, y - 20); minB:SetNumeric(true); minB:SetText(self.db.minLevel)
    minB:SetAutoFocus(false)
    minB:SetScript("OnEscapePressed", function(self) self:ClearFocus() end)
    minB:SetScript("OnEnterPressed", function(self) self:ClearFocus() end)
    minB:SetScript("OnTextChanged", function(e) self.db.minLevel = tonumber(e:GetText()) or 1 end)
    
    local maxB = CreateFrame("EditBox", nil, parent, "InputBoxTemplate"); maxB:SetSize(40, 20); maxB:SetPoint("LEFT", minB, "RIGHT", 15, 0); maxB:SetNumeric(true); maxB:SetText(self.db.maxLevel)
    maxB:SetAutoFocus(false)
    maxB:SetScript("OnEscapePressed", function(self) self:ClearFocus() end)
    maxB:SetScript("OnEnterPressed", function(self) self:ClearFocus() end)
    maxB:SetScript("OnTextChanged", function(e) self.db.maxLevel = tonumber(e:GetText()) or 70 end)
    
    y = y - 50; AddText("Scan Scope", "GameFontHighlightSmall", 0); y = y - 20
    
    local function MkScanBtn(text, mode, x, tooltipText)
        local b = CreateFrame("Button", nil, parent); CreateBg(b, 0.2, 0.2, 0.2, 1); b:SetSize(80, 20); b:SetPoint("TOPLEFT", 15 + x, y)
        local t = b:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); t:SetPoint("CENTER"); t:SetText(text)
        b.bg = b.bg
        b:SetScript("OnClick", function() self.db.remixMode = mode; self:UpdateRemixVisuals() end)
        
        -- Add Tooltip Logic
        b:SetScript("OnEnter", function(self) 
            if self.bg then self.bg:SetColorTexture(0.3, 0.3, 0.3, 1) end
            GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
            GameTooltip:SetText(tooltipText, nil, nil, nil, nil, true)
            GameTooltip:Show()
        end)
        b:SetScript("OnLeave", function(self) 
            GameTooltip:Hide()
            GR:UpdateRemixVisuals() -- Reset colors
        end)
        
        return b
    end
    
    self.btnWorld = MkScanBtn("World Only", "OFF", 0, "Excludes players currently inside Raid or Dungeon instances for a safer, non-intrusive scan.")
    self.btnAllow = MkScanBtn("All", "ALLOW", 85, "Searches ALL zones, including instances.\n\n|cffff0000WARNING:|r Sending unsolicited whispers to players in high-stress content carries a risk of reports.")
    
    function GR:UpdateRemixVisuals()
        self.btnWorld.bg:SetColorTexture(0.2,0.2,0.2,1); self.btnAllow.bg:SetColorTexture(0.2,0.2,0.2,1); 
        if self.db.remixMode=="OFF" then self.btnWorld.bg:SetColorTexture(0,0.6,0,1) end
        if self.db.remixMode=="ALLOW" then self.btnAllow.bg:SetColorTexture(0,0.6,0,1) end
    end
    self:UpdateRemixVisuals()
    
    y = y - 40; AddText("MESSAGE TEMPLATES", "GameFontNormal", 0); y = y - 30
    local dTemp = CreateFrame("Button", nil, parent); CreateBg(dTemp, 0.2, 0.2, 0.2, 1); dTemp:SetSize(200, 24); dTemp:SetPoint("TOPLEFT", 15, y)
    local dTempTxt = dTemp:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); dTempTxt:SetPoint("LEFT", 5, 0); dTempTxt:SetText(self.db.messageTemplate)
    
    local dTempArrow = dTemp:CreateTexture(nil, "ARTWORK")
    dTempArrow:SetTexture("Interface\\Buttons\\UI-ScrollBar-ScrollDownButton-Up")
    dTempArrow:SetSize(20, 20)
    dTempArrow:SetPoint("RIGHT", -2, 0)
    
    local dTempList = CreateFrame("Frame", nil, dTemp); CreateBg(dTempList, 0.1, 0.1, 0.1, 1); CreateBorder(dTempList, 0.5, 0.5, 0.5, 1)
    dTempList:SetSize(200, 100); dTempList:SetPoint("TOPLEFT", dTemp, "BOTTOMLEFT", 0, -2); dTempList:SetFrameStrata("FULLSCREEN_DIALOG"); dTempList:Hide()
    
    dTemp:SetScript("OnClick", function() 
        local kids = {dTempList:GetChildren()}; for _, k in ipairs(kids) do k:Hide() end
        local ty = -5
        for k, v in pairs(GR.db.templates) do
            local b = CreateFrame("Button", nil, dTempList); b:SetSize(190, 20); b:SetPoint("TOPLEFT", 5, ty)
            local t = b:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); t:SetPoint("LEFT"); t:SetText(k)
            b:SetScript("OnClick", function() 
                GR.db.messageTemplate = k; dTempTxt:SetText(k); GR.InputBody:SetText(v); GR.InputName:SetText(k); dTempList:Hide() 
                if GR.InputBody:GetScript("OnTextChanged") then
                     GR.InputBody:GetScript("OnTextChanged")(GR.InputBody)
                end
                if GR.InputName:GetScript("OnTextChanged") then
                     GR.InputName:GetScript("OnTextChanged")(GR.InputName)
                end
            end)
            ty = ty - 20
        end
        dTempList:SetHeight(math.abs(ty) + 5)
        dTempList:SetShown(not dTempList:IsShown()) 
    end)
    
    local btnNew = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
    btnNew:SetSize(50, 22); btnNew:SetPoint("LEFT", dTemp, "RIGHT", 5, 0); btnNew:SetText("New")
    btnNew:SetScript("OnClick", function() GR.InputName:SetText(""); GR.InputBody:SetText(""); GR.InputName:SetFocus() end)
    SkinButton(btnNew)

    y = y - 30
    local nameIn = CreateFrame("EditBox", nil, parent, "InputBoxTemplate")
    nameIn:SetSize(250, 20); nameIn:SetPoint("TOPLEFT", 15, y); nameIn:SetAutoFocus(false)
    nameIn:SetScript("OnEscapePressed", function(self) self:ClearFocus() end)
    self.InputName = nameIn
    local ph = nameIn:CreateFontString(nil, "ARTWORK", "GameFontDisable"); ph:SetPoint("LEFT", 5, 0); ph:SetText("Template Name...")
    
    nameIn:SetScript("OnTextChanged", function(self) 
        if self:GetText() ~= "" then ph:Hide() else ph:Show() end 
    end)
    
    nameIn:SetScript("OnEditFocusGained", function() ph:Hide() end)
    nameIn:SetScript("OnEditFocusLost", function(s) if s:GetText()=="" then ph:Show() end end)
    
    y = y - 30
    local bodyF = CreateFrame("Frame", nil, parent); CreateBg(bodyF, 0.1, 0.1, 0.1, 0.5); bodyF:SetSize(290, 100); bodyF:SetPoint("TOPLEFT", 15, y)
    local scrollM = CreateFrame("ScrollFrame", nil, bodyF, "UIPanelScrollFrameTemplate"); scrollM:SetPoint("TOPLEFT", 5, -5); scrollM:SetPoint("BOTTOMRIGHT", -25, 5)
    if NS.StyleScrollBar then NS.StyleScrollBar(scrollM) end
    local editM = CreateFrame("EditBox", nil, scrollM); editM:SetSize(265, 100); editM:SetMultiLine(true); editM:SetFontObject(ChatFontNormal); 
    editM:SetMaxLetters(255); 
    editM:SetAutoFocus(false) 
    editM:SetScript("OnEscapePressed", function(self) self:ClearFocus() end)
    editM:SetText(self.db.templates[self.db.messageTemplate] or ""); scrollM:SetScrollChild(editM); self.InputBody = editM

    local charCount = bodyF:CreateFontString(nil, "OVERLAY", "GameFontDisableSmall")
    charCount:SetPoint("BOTTOMRIGHT", -30, 2)
    local function UpdateCharCount()
        local len = string.len(editM:GetText() or "")
        charCount:SetText(len .. " / 255")
        if len >= 255 then charCount:SetTextColor(1, 0.2, 0.2) else charCount:SetTextColor(0.5, 0.5, 0.5) end
    end
    editM:SetScript("OnTextChanged", function(self)
        UpdateCharCount()
    end)
    editM:SetScript("OnEditFocusGained", function(self) UpdateCharCount() end) 
    UpdateCharCount() 
    
    y = y - 110
    local btnSave = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate"); btnSave:SetSize(80, 22); btnSave:SetPoint("TOPLEFT", 15, y); btnSave:SetText("Save")
    btnSave:SetScript("OnClick", function()
        local n, b = self.InputName:GetText(), self.InputBody:GetText()
        if n ~= "" and b ~= "" then
            self.db.templates[n] = b; self.db.messageTemplate = n; dTempTxt:SetText(n); print("Saved Template: " .. n)
        end
    end)
    SkinButton(btnSave)

    -- HELP BUTTON
    local btnHelp = CreateFrame("Button", nil, parent)
    btnHelp:SetSize(80, 22)
    btnHelp:SetPoint("LEFT", btnSave, "RIGHT", 5, 0)
    
    -- Custom Red Skinning
    btnHelp:SetNormalTexture("")
    btnHelp:SetHighlightTexture("")
    btnHelp:SetPushedTexture("")
    btnHelp:SetDisabledTexture("")
    CreateBg(btnHelp, 0.4, 0.0, 0.0, 1)
    CreateBorder(btnHelp, 0, 0, 0, 1)
    
    local hText = btnHelp:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    hText:SetPoint("CENTER"); hText:SetText("HELP"); hText:SetTextColor(1, 1, 1) 
    btnHelp:SetFontString(hText)
    
    btnHelp:SetScript("OnClick", function()
        if GR.HelpFrame then GR.HelpFrame:SetShown(not GR.HelpFrame:IsShown()) else GR:BuildHelpPopup() end
    end)
    
    btnHelp:SetScript("OnEnter", function(s) if s.bg then s.bg:SetColorTexture(0.6, 0.1, 0.1, 1) end end)
    btnHelp:SetScript("OnLeave", function(s) if s.bg then s.bg:SetColorTexture(0.4, 0.0, 0.0, 1) end end)
    btnHelp:SetScript("OnMouseDown", function(s) if s.bg then s.bg:SetColorTexture(0.2, 0.0, 0.0, 1) end end)
    btnHelp:SetScript("OnMouseUp", function(s) if s.bg then s.bg:SetColorTexture(0.6, 0.1, 0.1, 1) end end)

    -- TEST BUTTON (UPDATED WITH EXPLICIT LIST)
    local btnTest = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
    btnTest:SetSize(165, 22)
    btnTest:SetPoint("TOPLEFT", btnSave, "BOTTOMLEFT", 0, -5)
    btnTest:SetText("TEST ME")
    btnTest:SetScript("OnClick", function()
        if not GR.InputBody then return end
        local msg = GR.InputBody:GetText()
        if not msg or msg == "" then print("Template is empty."); return end
        
        local myName = UnitName("player")
        local myClass = UnitClass("player")
        local myGuild = GetGuildInfo("player") or "Guild"
        
        -- [[ PLACEHOLDER REPLACEMENT LOGIC (DUMB-PROOFED) ]]
        -- 1. Target Name (Variations) -> Becomes My Name for Test
        msg = msg:gsub("%[player%]", myName)
        msg = msg:gsub("%[Player%]", myName)
        msg = msg:gsub("%[PLAYER%]", myName)
        msg = msg:gsub("%[ player %]", myName)
        msg = msg:gsub("%[ Player %]", myName)
        msg = msg:gsub("%[ PLAYER %]", myName)
        
        -- 2. Own Name (Variations)
        msg = msg:gsub("%[ownname%]", myName)
        msg = msg:gsub("%[OwnName%]", myName)
        msg = msg:gsub("%[Ownname%]", myName)
        msg = msg:gsub("%[OWNNAME%]", myName)
        msg = msg:gsub("%[own name%]", myName)
        msg = msg:gsub("%[Own Name%]", myName)
        msg = msg:gsub("%[OWN NAME%]", myName)
        
        -- 3. Guild (Variations)
        msg = msg:gsub("%[guild%]", myGuild)
        msg = msg:gsub("%[Guild%]", myGuild)
        msg = msg:gsub("%[GUILD%]", myGuild)
        
        -- 4. Class (Variations)
        msg = msg:gsub("%[playerclass%]", myClass)
        msg = msg:gsub("%[PlayerClass%]", myClass)
        msg = msg:gsub("%[Playerclass%]", myClass)
        msg = msg:gsub("%[PLAYERCLASS%]", myClass)
        msg = msg:gsub("%[player class%]", myClass)
        msg = msg:gsub("%[Player Class%]", myClass)
        msg = msg:gsub("%[Player class%]", myClass)
        msg = msg:gsub("%[class%]", myClass)
        msg = msg:gsub("%[Class%]", myClass)
        msg = msg:gsub("%[CLASS%]", myClass)
        
        -- For TEST ME, we add 'player' to the Recruited Whitelist so it works
        if GR.recruitedPlayers then GR.recruitedPlayers[Ambiguate(myName, "none")] = true end
        
        SendChatMessage(msg, "WHISPER", nil, myName)
        print("GRS: Test message sent to self.")
    end)
    SkinButton(btnTest)
end

function GR:BuildHelpPopup()
    local f = CreateFrame("Frame", "GRS_HelpPopup", UIParent)
    f:SetSize(400, 300)
    f:SetPoint("CENTER")
    f:SetFrameStrata("FULLSCREEN_DIALOG")
    CreateBg(f, 0, 0, 0, 0.95)
    CreateBorder(f, 0.5, 0.5, 0.5, 1)
    
    local close = CreateFrame("Button", nil, f, "UIPanelCloseButton")
    close:SetPoint("TOPRIGHT", -5, -5)
    
    local title = f:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    title:SetPoint("TOP", 0, -15)
    title:SetText("Template Help")
    
    local content = f:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    content:SetPoint("TOPLEFT", 20, -50)
    content:SetPoint("BOTTOMRIGHT", -20, 20)
    content:SetJustifyH("LEFT")
    content:SetJustifyV("TOP")
    
    local helpText = 
        "Extra functionalities for the message template:\n\n" ..
        "|cff00ffff[player]|r - Scans and mentions the players name.\n" ..
        "|cff00ffff[ownname]|r - Scans and mentions YOUR name.\n" ..
        "|cff00ffff[Guild]|r - Scans and mentions your guilds name.\n" ..
        "|cff00ffff[playerclass]|r - Scans and mentions players class.\n"
    
    content:SetText(helpText)
    
    GR.HelpFrame = f
end

function GR:BuildCenterPane(parent)
    self.ResultsHeader = parent:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    self.ResultsHeader:SetPoint("TOPLEFT", 15, -15); self.ResultsHeader:SetText("Unguilded Players - Current Filter: Default (All)")
    
    local sBtn = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
    sBtn:SetSize(140, 30); sBtn:SetPoint("TOPRIGHT", -15, -10); sBtn:SetText("Search Players")
    self.SearchBtn = sBtn 
    sBtn:SetScript("OnClick", function() self:StartSearch() end)
    SkinButton(sBtn) 
    
    local rListBtn = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
    rListBtn:SetSize(100, 30)
    rListBtn:SetPoint("RIGHT", sBtn, "LEFT", -5, 0)
    rListBtn:SetText("Reset List")
    rListBtn:SetScript("OnClick", function()
        GR.foundPlayers = {}
        GR:UpdateScrollFrame()
        if GR.StatusText then GR.StatusText:SetText("List Discarded.") end
    end)
    SkinButton(rListBtn)

    local headF = CreateFrame("Frame", nil, parent); headF:SetSize(750, 20); headF:SetPoint("TOPLEFT", 21, -45) 

    local selectAll = CreateFrame("CheckButton", nil, headF, "UICheckButtonTemplate")
    selectAll:SetSize(20, 20)
    selectAll:SetPoint("LEFT", 0, 0)
    selectAll:SetScript("OnClick", function(self)
        local state = self:GetChecked()
        for _, p in ipairs(GR.foundPlayers) do
            p.selected = state
        end
        GR:UpdateScrollFrame()
    end)
    
    local headers = {
        {text="Name", key="name", width=110}, 
        {text="Race", key="race", width=90},  
        {text="Class", key="fullClass", width=100},
        {text="Level", key="level", width=40}, 
        -- REMOVED MAX KEY
        {text="Zone", key="zone", width=110}
        -- REMOVED SCORE, HEROIC, MYTHIC
    }
    
    local lastH = nil
    for i, data in ipairs(headers) do
        local btn = CreateFrame("Button", nil, headF)
        btn:SetSize(data.width, 20)
        
        if i==1 then 
            btn:SetPoint("LEFT", 30, 0) 
        else 
            btn:SetPoint("LEFT", lastH, "RIGHT", 0, 0) 
        end
        
        local txt = btn:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        txt:SetPoint("LEFT", 0, 0)
        txt:SetText(data.text)
        btn:SetFontString(txt)
        
        btn:SetScript("OnEnter", function(s) 
            s:GetFontString():SetTextColor(1, 1, 1) 
        end)
        btn:SetScript("OnLeave", function(s) 
            s:GetFontString():SetTextColor(1, 0.82, 0) 
        end)
        
        btn:SetScript("OnClick", function() 
            GR:SortPlayers(data.key) 
        end)
        
        lastH = btn
    end
    
    local bot = CreateFrame("Frame", nil, parent); bot:SetHeight(40)
    bot:SetPoint("BOTTOMLEFT", 15, 5)
    bot:SetPoint("BOTTOMRIGHT", -15, 5)
    
    local slL = bot:CreateFontString(nil,"OVERLAY","GameFontHighlightSmall"); slL:SetPoint("LEFT", 0, 0); slL:SetText("Msg Delay: 0.8s")
    local sl = CreateFrame("Slider", nil, bot, "OptionsSliderTemplate")
    sl:SetPoint("LEFT", slL, "RIGHT", 10, 0); sl:SetWidth(150); sl:SetMinMaxValues(0.5, 1.0); sl:SetValue(0.8); sl:SetValueStep(0.1); sl:SetObeyStepOnDrag(true)
    sl:SetScript("OnValueChanged", function(s,v) v=math.floor(v*10)/10; self.db.scanDelay=v; slL:SetText("Msg Delay: "..v.."s") end)
    
    local snd = CreateFrame("Button", nil, bot, "UIPanelButtonTemplate"); snd:SetSize(120, 30); snd:SetPoint("RIGHT", -10, 0); snd:SetText("Send Batch")
    snd:SetScript("OnClick", function() self:SendMessageSequence() end)
    SkinButton(snd) 

    local btnBL = CreateFrame("Button", nil, bot, "UIPanelButtonTemplate")
    btnBL:SetSize(130, 30)
    btnBL:SetPoint("RIGHT", snd, "LEFT", -10, 0)
    btnBL:SetText("Blacklist Selected")
    btnBL:SetScript("OnClick", function() self:ManualBlacklist() end)
    SkinButton(btnBL)

    self.StatusText = bot:CreateFontString(nil,"OVERLAY","GameFontNormal"); 
    self.StatusText:SetPoint("RIGHT", btnBL, "LEFT", -20, 0); 
    self.StatusText:SetText("Ready.")

    self.scroll = CreateFrame("ScrollFrame", "GRS_S", parent, "FauxScrollFrameTemplate")
    parent.scrollFrame = self.scroll
    parent.scroll = self.scroll 
    local scrollFrame = self.scroll 
    
    scrollFrame:SetPoint("TOPLEFT", headF, "BOTTOMLEFT", 0, -5)
    scrollFrame:SetPoint("BOTTOMRIGHT", bot, "TOPRIGHT", -5, 5)
    
    CreateBg(scrollFrame, 0, 0, 0, 0.8) 
    
    local scrollBar = _G["GRS_SScrollBar"]
    if scrollBar then
        CreateBg(scrollBar, 0.1, 0.1, 0.1, 0.8) 
    end

    scrollFrame:SetScript("OnVerticalScroll", function(s, offset)
        FauxScrollFrame_OnVerticalScroll(s, offset, 20, function() self:UpdateScrollFrame() end)
    end)
    
    scrollFrame:EnableMouseWheel(true)
    
    parent:SetScript("OnSizeChanged", function(frame, w, h)
        local sFrame = scrollFrame or frame.scrollFrame or frame.scroll
        if not sFrame then return end

        local availableW = w - 30 
        local MAX_WIDTH = 760 
        
        if availableW > MAX_WIDTH then
            bot:ClearAllPoints()
            bot:SetPoint("BOTTOMLEFT", 15, 5)
            bot:SetWidth(MAX_WIDTH)
            
            sFrame:ClearAllPoints()
            sFrame:SetPoint("TOPLEFT", headF, "BOTTOMLEFT", 0, -5)
            sFrame:SetPoint("BOTTOMLEFT", bot, "TOPLEFT", 0, 5)
            sFrame:SetWidth(MAX_WIDTH)
        else
            bot:ClearAllPoints()
            bot:SetPoint("BOTTOMLEFT", 15, 5)
            bot:SetPoint("BOTTOMRIGHT", -15, 5)
            
            sFrame:ClearAllPoints()
            sFrame:SetPoint("TOPLEFT", headF, "BOTTOMLEFT", 0, -5)
            sFrame:SetPoint("BOTTOMRIGHT", bot, "TOPRIGHT", -5, 5)
        end
    end)
    
    self.rows = {}
    
    function GR:UpdateResultsLayout(height)
        if not height then height = self.scroll:GetHeight() end
        local numRows = math.floor(height / 20)
        self.visibleRows = numRows 
        
        for i = 1, numRows do
            if not self.rows[i] then
                local r = CreateFrame("Button", nil, parent)
                r:SetHeight(20); 
                r:SetPoint("LEFT", 41, 0); 
                r:SetPoint("RIGHT", -25, 0)
                if i==1 then r:SetPoint("TOP", self.scroll, "TOP") else r:SetPoint("TOP", self.rows[i-1], "BOTTOM") end
                
                r.c = CreateFrame("CheckButton", nil, r, "UICheckButtonTemplate"); r.c:SetSize(20,20); r.c:SetPoint("LEFT", -20, 0)
                r.c:SetScript("OnClick", function(b) if r.d then r.d.selected=b:GetChecked() end end)
                
                r.n = r:CreateFontString(nil,"OVERLAY","GameFontHighlightSmall"); r.n:SetPoint("LEFT",10,0); r.n:SetWidth(110); r.n:SetJustifyH("LEFT")
                r.ra = r:CreateFontString(nil,"OVERLAY","GameFontHighlightSmall"); r.ra:SetPoint("LEFT",r.n,"RIGHT"); r.ra:SetWidth(90); r.ra:SetJustifyH("LEFT")
                r.cl = r:CreateFontString(nil,"OVERLAY","GameFontHighlightSmall"); r.cl:SetPoint("LEFT",r.ra,"RIGHT"); r.cl:SetWidth(100); r.cl:SetJustifyH("LEFT")
                
                r.lvl = r:CreateFontString(nil,"OVERLAY","GameFontHighlightSmall"); r.lvl:SetPoint("LEFT",r.cl,"RIGHT"); r.lvl:SetWidth(40); r.lvl:SetJustifyH("LEFT")
                
                -- r.mk REMOVED
                
                -- FIXED ANCHOR for Zone (now points to Level)
                r.z = r:CreateFontString(nil,"OVERLAY","GameFontHighlightSmall"); r.z:SetPoint("LEFT",r.lvl,"RIGHT"); r.z:SetWidth(110); r.z:SetJustifyH("LEFT")
                
                -- r.s, r.h, r.m REMOVED
                
                self.rows[i] = r
            end
        end
        self:UpdateScrollFrame() 
    end
end

function GR:BuildWhisperPane(parent)
    local expandedF = CreateFrame("Frame", nil, parent)
    expandedF:SetAllPoints()
    self.WhisperExpandedFrame = expandedF
    
    local gridH = expandedF:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    gridH:SetPoint("TOPLEFT", 15, -15)
    gridH:SetText("ACTIVE WHISPERS")
    
    local pText = expandedF:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    pText:SetPoint("LEFT", gridH, "RIGHT", 30, 0) 
    pText:SetText("Page 1 / 1")
    self.pageText = pText
    
    local prevBtn = CreateFrame("Button", nil, expandedF)
    prevBtn:SetSize(20, 20)
    prevBtn:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-PrevPage-Up")
    prevBtn:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight")
    prevBtn:SetPoint("RIGHT", pText, "LEFT", -5, 0)
    prevBtn:SetScript("OnClick", function() 
        if GR.currentPage > 1 then 
            GR.currentPage = GR.currentPage - 1
            GR:RenderWhisperGrid() 
        end 
    end)
    self.prevBtn = prevBtn
    
    local nextBtn = CreateFrame("Button", nil, expandedF)
    nextBtn:SetSize(20, 20)
    nextBtn:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up")
    nextBtn:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight")
    nextBtn:SetPoint("LEFT", pText, "RIGHT", 5, 0)
    nextBtn:SetScript("OnClick", function() 
        -- Paging logic handled in RenderWhisperGrid to account for filters
        if GR.nextBtn and GR.nextBtn:IsEnabled() then 
            GR.currentPage = GR.currentPage + 1
            GR:RenderWhisperGrid() 
        end 
    end)
    self.nextBtn = nextBtn

    local pruneBtn = CreateFrame("Button", nil, expandedF, "UIPanelButtonTemplate")
    pruneBtn:SetSize(100, 20)
    pruneBtn:SetPoint("LEFT", nextBtn, "RIGHT", 20, 0)
    pruneBtn:SetText("Prune Inactive")
    pruneBtn:SetScript("OnClick", function() self:PruneInactiveChats() end)
    SkinButton(pruneBtn)
    
    -- [[ ADDED REPLIES ONLY CHECKBOX ]]
    local rOnly = CreateFrame("CheckButton", nil, expandedF, "UICheckButtonTemplate")
    rOnly:SetSize(24, 24)
    rOnly:SetPoint("LEFT", pruneBtn, "RIGHT", 10, 0)
    rOnly.text = rOnly:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    rOnly.text:SetPoint("LEFT", rOnly, "RIGHT", 0, 0)
    rOnly.text:SetText("Replies only")
    rOnly:SetScript("OnClick", function(self)
        if GR.db then GR.db.showRepliesOnly = self:GetChecked() end
        GR.currentPage = 1
        GR:RenderWhisperGrid()
    end)
    -- Restore state if DB loaded
    if GR.db and GR.db.showRepliesOnly then rOnly:SetChecked(true) end
    self.chkReplies = rOnly
    
    self.chatFrames = {}
    local gridBase = CreateFrame("Frame", nil, expandedF)
    gridBase:SetPoint("TOPLEFT", gridH, "BOTTOMLEFT", 0, -10)
    gridBase:SetPoint("BOTTOMRIGHT", -15, 10)
    self.WhisperGridBase = gridBase
    
    function GR:UpdateWhisperLayout(totalHeight)
        self.chatPageSize = 6
        local chatH = 115
        local gap = 10
        
        for i = 1, self.chatPageSize do
            if not self.chatFrames[i] then
                local cf = CreateFrame("Frame", nil, self.WhisperGridBase)
                CreateBg(cf, 0, 0, 0, 0.6); CreateBorder(cf, 0.4, 0.4, 0.4, 1)
                cf:SetHeight(chatH); cf:SetPoint("LEFT"); cf:SetPoint("RIGHT")
                
                cf:Hide() 
                
                cf.headerBtn = CreateFrame("Button", nil, cf); cf.headerBtn:SetPoint("TOPLEFT", 5, -5); cf.headerBtn:SetSize(200, 15)
                cf.headerBtn.text = cf.headerBtn:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall"); cf.headerBtn.text:SetPoint("LEFT"); cf.headerBtn.text:SetText("Inactive")
                cf.headerBtn:RegisterForClicks("AnyUp") 
                cf.headerBtn:SetScript("OnClick", function(s, button)
                    if not s.playerName then return end
                    if button == "LeftButton" then ChatFrame_SendTell(s.playerName)
                    elseif button == "RightButton" then
                        -- TBC: Use UIDropDownMenu instead of MenuUtil
                        local menu = CreateFrame("Frame", "GRS_ChatContextMenu", UIParent, "UIDropDownMenuTemplate")
                        UIDropDownMenu_Initialize(menu, function(self, level)
                            local info = UIDropDownMenu_CreateInfo()
                            info.text = s.playerName
                            info.isTitle = true
                            info.notCheckable = true
                            UIDropDownMenu_AddButton(info, level)
                            
                            info = UIDropDownMenu_CreateInfo()
                            info.text = "Invite to guild"
                            info.notCheckable = true
                            info.func = function() GuildInvite(s.playerName) end
                            UIDropDownMenu_AddButton(info, level)
                            
                            info = UIDropDownMenu_CreateInfo()
                            info.text = "Copy Name-Realm"
                            info.notCheckable = true
                            info.func = function() NS.ShowCopyPopup(s.playerName) end
                            UIDropDownMenu_AddButton(info, level)
                        end, "MENU")
                        ToggleDropDownMenu(1, nil, menu, "cursor", 0, 0)
                    end
                end)
                
                local closeChat = CreateFrame("Button", nil, cf, "UIPanelCloseButton"); closeChat:SetSize(20, 20); closeChat:SetPoint("TOPRIGHT", -2, -2)
                closeChat:SetScript("OnClick", function()
                    -- Removal needs to find the correct index in activeChats
                    -- For now, simplistic approach: find by name
                    if cf.headerBtn.playerName then
                        for k, v in ipairs(GR.activeChats) do
                            if v.name == cf.headerBtn.playerName then
                                table.remove(GR.activeChats, k)
                                break
                            end
                        end
                        GR:RenderWhisperGrid() 
                    end
                end)
                
                cf.scroll = CreateFrame("ScrollFrame", nil, cf, "UIPanelScrollFrameTemplate"); cf.scroll:SetPoint("TOPLEFT", 5, -20); cf.scroll:SetPoint("BOTTOMRIGHT", -25, 5)
                if NS.StyleScrollBar then NS.StyleScrollBar(cf.scroll) end
                cf.text = CreateFrame("EditBox", nil, cf.scroll); cf.text:SetMultiLine(true); cf.text:SetFontObject(ChatFontSmall); cf.text:SetWidth(430); cf.text:SetAutoFocus(false); cf.text:EnableMouse(false)
                cf.scroll:SetScrollChild(cf.text)
                self.chatFrames[i] = cf
            end
            
            if i==1 then 
                self.chatFrames[i]:SetPoint("TOP") 
            else 
                self.chatFrames[i]:SetPoint("TOP", self.chatFrames[i-1], "BOTTOM", 0, -gap) 
            end
        end
        
        for i = self.chatPageSize + 1, #self.chatFrames do
            if self.chatFrames[i] then self.chatFrames[i]:Hide() end
        end
        
        self:RenderWhisperGrid()
    end
end

function GR:UpdateScrollFrame()
    local d = self.foundPlayers
    local rowCount = self.visibleRows or 15
    if rowCount > #self.rows then rowCount = #self.rows end
    
    FauxScrollFrame_Update(self.scroll, #d, rowCount, 20)
    
    local scrollBar = _G["GRS_SScrollBar"]
    if scrollBar then
        scrollBar:Show() 
        
        local _, maxVal = scrollBar:GetMinMaxValues()
        local thumb = scrollBar:GetThumbTexture()
        
        if not maxVal or maxVal == 0 then
             if thumb then thumb:Hide() end
             
             local up = _G["GRS_SScrollBarScrollUpButton"]
             local down = _G["GRS_SScrollBarScrollDownButton"]
             if up then up:Disable() end
             if down then down:Disable() end
        else
             if thumb then thumb:Show() end
             
             local up = _G["GRS_SScrollBarScrollUpButton"]
             local down = _G["GRS_SScrollBarScrollDownButton"]
             if up then up:Enable() end
             if down then down:Enable() end
        end
    end
    
    local offset = FauxScrollFrame_GetOffset(self.scroll)
    
    for i=1, #self.rows do
        local r = self.rows[i]
        if i > rowCount then
            r:Hide()
        else
            local idx = offset + i
            if idx <= #d then
                local p = d[idx]
                r.d = p; r:Show()
                r.n:SetText(p.name); 
                r.lvl:SetText(p.level);
                
                -- r.mk REMOVED
                
                r.z:SetText(p.zone); r.ra:SetText(p.race or "Unknown")
                local cc = C_ClassColor.GetClassColor(p.classFile or "PRIEST")
                r.cl:SetText(cc and cc:WrapTextInColorCode(p.fullClass) or p.fullClass)
                
                -- r.s, r.h, r.m REMOVED
                
                r.c:SetChecked(p.selected)
            else 
                r:Hide() 
            end
        end
    end
end

-- =========================================================================
-- UI: MVP VIEW
-- =========================================================================

function GR:BuildMVPView()
    -- Defined as ID 8 in Constants.lua
    local viewId = 8 
    local parent = CreateFrame("Frame", "GRS_MVPView", self.ViewContainer)
    parent:SetAllPoints()
    parent:Hide()
    self.views[viewId] = parent
    
    -- Main Container Box
    local content = CreateFrame("Frame", nil, parent)
    -- Anchors to stretch horizontally across the parent (Maximum Width)
    content:SetPoint("TOPLEFT", 0, 0)
    content:SetPoint("BOTTOMRIGHT", 0, -1) 
    
    -- [[ BACKGROUND LOGIC ]]
    -- 1. Create Pure Black Backdrop (Sublayer -1)
    local bg = content:CreateTexture(nil, "BACKGROUND", nil, -1)
    bg:SetAllPoints()
    bg:SetColorTexture(0, 0, 0, 0.75) -- Pure Black

    -- 2. Create Logo Texture (Sublayer 1)
    local logo = content:CreateTexture(nil, "BACKGROUND", nil, 1)
    logo:SetPoint("CENTER")
    logo:SetSize(512, 512) -- Standard large icon size to act as wallpaper
    -- Dynamic path using the addonName variable
    logo:SetTexture("Interface\\AddOns\\" .. addonName .. "\\media\\AXIOM_Logo.tga")

    -- Title: MVP's
    local title = content:CreateFontString(nil, "OVERLAY", "GameFontNormalHuge")
    title:SetPoint("TOP", 0, -30)
    title:SetText("MVP's")
    title:SetTextColor(1, 0.82, 0) -- Gold Color
    
    -- Appreciation Note (Re-inserted)
    local subTitle = content:CreateFontString(nil, "OVERLAY", "GameFontHighlightMedium")
    subTitle:SetPoint("TOP", title, "BOTTOM", 0, -15)
    subTitle:SetWidth(600) -- Allow wrapping if necessary
    subTitle:SetText("A special thank you to the legends who helped shape this project.\nYour support has been invaluable.")
    subTitle:SetTextColor(0.9, 0.9, 0.9) -- Soft White
    
    -- The List of MVP Names
    local mvpList = {
		" ",
		" ",
		" ",
		" ",
        "Malthred",
        "Hahaheehee",
        "Getras",
        "Emaenno",
        "Niels",
        "Blladee",
		"GankerMaster",
		"Messami",
		"Nyx",
		"Frazic",
		"[Ben]",
		"Unknownhealz"
    }
    
    local prevObj = subTitle
    for i, name in ipairs(mvpList) do
        local t = content:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
        if i == 1 then
            t:SetPoint("TOP", prevObj, "BOTTOM", 0, -30) -- Larger gap after note
        else
            t:SetPoint("TOP", prevObj, "BOTTOM", 0, -15)
        end
        t:SetText(name)
        -- Aesthetic Light Blue
        t:SetTextColor(0.6, 0.8, 1) 
        prevObj = t
    end
end