local addonName, NS = ...
local GR = _G["GRS_MainFrame"]

-- =========================================================================
-- 1. DATABASE & CONSTANTS (CLASSIC / TBC EDITION)
-- =========================================================================

local REQ_DEFAULTS = {
    classes = {}, 
    races = {},   
    progressionN = {}, -- Normal
    progressionH = {}, -- Heroic
    -- Mythic Removed
    servers = {},      -- [Realm] = { recruiter="Name & Name", type="Social"|"Raid" }
    history = {}  
}

local PROGRESSION_STEPS = { "0/8", "1/8", "2/8", "3/8", "4/8", "5/8", "6/8", "7/8", "8/8" }

-- TBC Era Classes Only
local CLASS_LIST = {
    "Druid", "Hunter", "Mage", "Paladin", "Priest", 
    "Rogue", "Shaman", "Warlock", "Warrior"
}

-- Faction Specific Lists
local RACES_ALLIANCE = { "Draenei", "Dwarf", "Gnome", "Human", "Night Elf" }
local RACES_HORDE = { "Blood Elf", "Orc", "Tauren", "Troll", "Undead" }

local function GetRaceList()
    local faction = UnitFactionGroup("player")
    if faction == "Alliance" then return RACES_ALLIANCE
    elseif faction == "Horde" then return RACES_HORDE
    else return RACES_ALLIANCE end -- Fallback
end

local function InitReqDB()
    if not _G.GRS_DB.requirements then _G.GRS_DB.requirements = CopyTable(REQ_DEFAULTS) end
    local db = _G.GRS_DB.requirements
    if not db.classes then db.classes = {} end
    if not db.races then db.races = {} end
    if not db.history then db.history = {} end
    if not db.servers then db.servers = {} end 
    
    if type(db.progressionN) ~= "table" then db.progressionN = {} end
    if type(db.progressionH) ~= "table" then db.progressionH = {} end
    -- Clean up old mythic data if present
    if db.progressionM then db.progressionM = nil end
end

local function GetGuildNameStr()
    local guildName = GetGuildInfo("player")
    return guildName or "THE EXILES" 
end

-- =========================================================================
-- 2. LOCAL HELPERS (Visuals)
-- =========================================================================

local function CreateBlackBg(f)
    local t = f:CreateTexture(nil, "BACKGROUND")
    t:SetAllPoints()
    t:SetColorTexture(0, 0, 0, 0.8) -- 80% Black
    f.bg = t
    
    local border = f:CreateTexture(nil, "BORDER")
    border:SetPoint("TOPLEFT", -1, 1)
    border:SetPoint("BOTTOMRIGHT", 1, -1)
    border:SetColorTexture(0.2, 0.2, 0.2, 1)
    f.border = border
end

local function CreateColoredCheckbox(parent, colorType, onClick)
    local cb = CreateFrame("CheckButton", nil, parent, "UICheckButtonTemplate")
    cb:SetSize(20, 20)
    
    local r, g, b = 1, 1, 1
    if colorType == "L" then r,g,b = 0, 1, 0         -- Green
    elseif colorType == "M" then r,g,b = 1, 0.5, 0   -- Orange
    elseif colorType == "H" then r,g,b = 1, 0, 0     -- Red
    end
    
    cb:GetCheckedTexture():SetVertexColor(r, g, b)
    
    local bg = cb:CreateTexture(nil, "BACKGROUND")
    bg:SetAllPoints(cb)
    bg:SetColorTexture(0, 0, 0, 1)
    
    cb:SetScript("OnClick", function(self) onClick(self:GetChecked()) end)
    return cb
end

-- =========================================================================
-- 3. SYNC ENGINE
-- =========================================================================

local function AddHistoryEntry(author, description)
    local h = { ts = GetServerTime(), author = author, desc = description }
    table.insert(_G.GRS_DB.requirements.history, 1, h)
    if #_G.GRS_DB.requirements.history > 50 then
        table.remove(_G.GRS_DB.requirements.history)
    end
    if GR.ReqHistoryFrame and GR.ReqHistoryFrame:IsShown() and GR.UpdateHistoryList then
        GR:UpdateHistoryList()
    end
end

local function SendSyncAction(category, key, value)
    if not IsInGuild() then return end
    local msg = string.format("%s:%s:%s", category, key, tostring(value))
    GR:SafeSendAddonMessage("GRS_REQ", msg, "GUILD")
end

local function OnCommReceived(prefix, text, channel, sender)
    if prefix ~= "GRS_REQ" then return end
    if sender == UnitName("player") then return end
    
    local entries = { strsplit("|", text) }
    local db = _G.GRS_DB.requirements
    local updates = 0

    for _, rawMsg in ipairs(entries) do
        local cat, key, val = strsplit(":", rawMsg)
        
        if cat and key then
            local desc = ""
            
            if cat == "CLASS" then
                local pVal = (val == "nil") and nil or val
                db.classes[key] = pVal
                desc = pVal and string.format("Set Class %s to Priority %s", key, pVal) or string.format("Closed recruitment for %s", key)
                
            elseif cat == "RACE" then
                local bVal = (val == "true")
                db.races[key] = bVal
                desc = string.format("%s Race %s", bVal and "Enabled" or "Disabled", key)
                
            elseif cat == "PROG_N" then
                local bVal = (val == "true")
                db.progressionN[key] = bVal
                desc = string.format("Normal Raid: %s %s", key, bVal and "Selected" or "Deselected")
            elseif cat == "PROG_H" then
                local bVal = (val == "true")
                db.progressionH[key] = bVal
                desc = string.format("Heroic Raid: %s %s", key, bVal and "Selected" or "Deselected")
                
            elseif cat == "SERVER" then
                if val == "nil" then
                    db.servers[key] = nil
                    desc = string.format("Cleared recruiters for: %s", key)
                else
                    local rec, rType = strsplit("~", val) 
                    if not rType then rec, rType = strsplit("%", val) end 
                    
                    db.servers[key] = { recruiter = rec, type = rType }
                    desc = string.format("Recruiter update for %s: %s", key, rec)
                end
            end
            
            if desc ~= "" then
                AddHistoryEntry(sender, desc)
                updates = updates + 1
            end
        end
    end

    if updates > 0 and GR.RefreshReqUI then 
        GR:RefreshReqUI() 
    end
end

local eqFrame = CreateFrame("Frame")
eqFrame:RegisterEvent("CHAT_MSG_ADDON")
eqFrame:SetScript("OnEvent", function(self, event, ...)
    local prefix = ...
    if prefix == "GRS_REQ" then OnCommReceived(...) end
end)
C_ChatInfo.RegisterAddonMessagePrefix("GRS_REQ")

-- =========================================================================
-- 4. HISTORY WINDOW
-- =========================================================================

function GR:BuildHistoryWindow()
    if GR.ReqHistoryFrame then return end

    local f = CreateFrame("Frame", "GRS_HistoryFrame", UIParent, "BackdropTemplate")
    f:SetSize(400, 500)
    f:SetPoint("CENTER")
    f:SetFrameStrata("FULLSCREEN_DIALOG") 
    f:EnableMouse(true)
    f:SetMovable(true)
    f:RegisterForDrag("LeftButton")
    f:SetScript("OnDragStart", f.StartMoving)
    f:SetScript("OnDragStop", f.StopMovingOrSizing)
    
    f:SetBackdrop({
        bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
        edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
        tile = true, tileSize = 32, edgeSize = 32,
        insets = { left = 11, right = 12, top = 12, bottom = 11 }
    })
    f:SetBackdropColor(0, 0, 0, 1)
    f:Hide()
    
    local title = f:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    title:SetPoint("TOP", 0, -15); title:SetText("Requirement Audit Log")
    
    local close = CreateFrame("Button", nil, f, "UIPanelCloseButton")
    close:SetPoint("TOPRIGHT", -5, -5)
    
    local sf = CreateFrame("ScrollFrame", "GRS_HistScroll", f, "UIPanelScrollFrameTemplate")
    sf:SetPoint("TOPLEFT", 15, -50); sf:SetPoint("BOTTOMRIGHT", -30, 15)
    if NS.StyleScrollBar then NS.StyleScrollBar(sf) end
    
    local content = CreateFrame("Frame", nil, sf)
    content:SetSize(355, 400)
    sf:SetScrollChild(content)
    
    f.lines = {}
    
    GR.UpdateHistoryList = function()
        local h = _G.GRS_DB.requirements.history
        local y = 0
        for _, line in ipairs(f.lines) do line:Hide() end
        
        for i, entry in ipairs(h) do
            local frame = f.lines[i]
            if not frame then
                frame = CreateFrame("Frame", nil, content)
                frame:SetSize(350, 40)
                
                frame.ts = frame:CreateFontString(nil, "OVERLAY", "GameFontDisableSmall")
                frame.ts:SetPoint("TOPLEFT", 0, 0)
                
                frame.txt = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
                frame.txt:SetPoint("TOPLEFT", 0, -12)
                frame.txt:SetWidth(350); frame.txt:SetJustifyH("LEFT")
                
                local div = frame:CreateTexture(nil, "ARTWORK")
                div:SetColorTexture(0.2, 0.2, 0.2, 1); div:SetHeight(1)
                div:SetPoint("BOTTOMLEFT"); div:SetPoint("BOTTOMRIGHT")
                
                f.lines[i] = frame
            end
            frame:SetPoint("TOPLEFT", 0, y)
            frame:Show()
            local dateStr = date("%Y-%m-%d %H:%M", entry.ts)
            frame.ts:SetText(dateStr .. " - " .. (entry.author or "Unknown"))
            frame.txt:SetText(entry.desc)
            y = y - 45
        end
        content:SetHeight(math.abs(y))
    end
    
    GR.ReqHistoryFrame = f
end

-- =========================================================================
-- 6. MAIN TAB CONSTRUCTION
-- =========================================================================

function GR:BuildRequirementsView(parent)
    InitReqDB()
    
    for _, region in ipairs({parent:GetRegions()}) do
        if region:GetObjectType() == "FontString" then region:Hide() end
    end
    if parent.container then parent.container:Hide() end
    
    local container = CreateFrame("Frame", nil, parent)
    container:SetAllPoints()
    parent.container = container
    
    -- ===========================
    -- COLUMN 1: CLASS PRIORITY
    -- ===========================
    local col1 = CreateFrame("Frame", nil, container)
    col1:SetPoint("TOPLEFT", 10, -60)
    col1:SetPoint("BOTTOMLEFT", 10, 90) 
    col1:SetWidth(300) 
    CreateBlackBg(col1)
    
    local h1 = col1:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    h1:SetPoint("TOPLEFT", 10, -10); h1:SetText("Class Priority")
    
    local lblClass = col1:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    lblClass:SetPoint("TOPLEFT", 10, -40); lblClass:SetText("Class")
    
    local lblL = col1:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    lblL:SetPoint("TOPRIGHT", -90, -40); lblL:SetText("Low"); lblL:SetTextColor(0, 1, 0)
    
    local lblM = col1:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    lblM:SetPoint("TOPRIGHT", -50, -40); lblM:SetText("Med"); lblM:SetTextColor(1, 0.5, 0)
    
    local lblH = col1:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    lblH:SetPoint("TOPRIGHT", -10, -40); lblH:SetText("High"); lblH:SetTextColor(1, 0, 0)
    
    GR.reqClassRows = {}
    local cy = -65
    
    for _, cls in ipairs(CLASS_LIST) do
        local row = CreateFrame("Frame", nil, col1)
        row:SetSize(280, 24)
        row:SetPoint("TOPLEFT", 10, cy)
        
        row.name = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
        row.name:SetPoint("LEFT", 0, 0); row.name:SetText(cls)
        
        local function UpdateClassDB(priority)
            local db = _G.GRS_DB.requirements.classes
            if db[cls] == priority then db[cls] = nil else db[cls] = priority end
            SendSyncAction("CLASS", cls, tostring(db[cls]))
            GR:RefreshReqUI()
        end
        
        row.cbL = CreateColoredCheckbox(row, "L", function() UpdateClassDB("L") end)
        row.cbL:SetPoint("RIGHT", -90, 0)
        
        row.cbM = CreateColoredCheckbox(row, "M", function() UpdateClassDB("M") end)
        row.cbM:SetPoint("RIGHT", -50, 0)
        
        row.cbH = CreateColoredCheckbox(row, "H", function() UpdateClassDB("H") end)
        row.cbH:SetPoint("RIGHT", -10, 0)
        
        GR.reqClassRows[cls] = row
        cy = cy - 28
    end
    
    -- ===========================
    -- COLUMN 2: RACE PRIORITY (FACTION LOCKED)
    -- ===========================
    local col2 = CreateFrame("Frame", nil, container)
    col2:SetPoint("TOPLEFT", col1, "TOPRIGHT", 10, 0)
    col2:SetPoint("BOTTOMLEFT", col1, "BOTTOMRIGHT", 10, 0)
    col2:SetWidth(150)
    CreateBlackBg(col2)
    
    local faction = UnitFactionGroup("player")
    local h2 = col2:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    h2:SetPoint("TOPLEFT", 10, -10); h2:SetText((faction or "Faction") .. " Races")
    
    local scrollR = CreateFrame("ScrollFrame", "GRS_ReqRaceScroll", col2, "UIPanelScrollFrameTemplate")
    scrollR:SetPoint("TOPLEFT", 5, -40); scrollR:SetPoint("BOTTOMRIGHT", -25, 5)
    if NS.StyleScrollBar then NS.StyleScrollBar(scrollR) end
    
    local activeRaces = GetRaceList()
    local contentR = CreateFrame("Frame", nil, scrollR)
    contentR:SetSize(120, #activeRaces * 25)
    scrollR:SetScrollChild(contentR)
    
    GR.reqRaceRows = {}
    local ry = 0
    for _, race in ipairs(activeRaces) do
        local cb = CreateFrame("CheckButton", nil, contentR, "UICheckButtonTemplate")
        cb:SetSize(20, 20); cb:SetPoint("TOPLEFT", 5, ry)
        
        cb.text = cb:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
        cb.text:SetPoint("LEFT", cb, "RIGHT", 5, 0); cb.text:SetText(race)
        
        cb:SetScript("OnClick", function(self)
            local checked = self:GetChecked()
            _G.GRS_DB.requirements.races[race] = checked
            SendSyncAction("RACE", race, tostring(checked))
        end)
        
        GR.reqRaceRows[race] = cb
        ry = ry - 25
    end
    
    -- ===========================
    -- COLUMNS 3-4: RAID PROGRESSION (NORMAL / HEROIC)
    -- ===========================
    
    GR.reqProgRows = { N = {}, H = {} }
    
    local function BuildProgressionColumn(anchorFrame, title, dbKey, syncTag, color)
        local frame = CreateFrame("Frame", nil, container)
        frame:SetPoint("TOPLEFT", anchorFrame, "TOPRIGHT", 10, 0)
        frame:SetPoint("BOTTOM", anchorFrame, "BOTTOM", 0, 0)
        frame:SetWidth(110)
        CreateBlackBg(frame)
        
        local h = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
        h:SetPoint("TOPLEFT", 10, -10)
        h:SetText(title)
        if color then h:SetTextColor(unpack(color)) end
        
        local py = -40
        for _, step in ipairs(PROGRESSION_STEPS) do
            local cb = CreateFrame("CheckButton", nil, frame, "UICheckButtonTemplate")
            cb:SetSize(20, 20); cb:SetPoint("TOPLEFT", 10, py)
            
            cb.text = cb:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
            cb.text:SetPoint("LEFT", cb, "RIGHT", 5, 0); cb.text:SetText(step)
            
            cb:SetScript("OnClick", function(self)
                local checked = self:GetChecked()
                local db = _G.GRS_DB.requirements
                if dbKey == "N" then db.progressionN[step] = checked end
                if dbKey == "H" then db.progressionH[step] = checked end
                
                SendSyncAction(syncTag, step, tostring(checked))
            end)
            
            GR.reqProgRows[dbKey][step] = cb
            py = py - 25
        end
        return frame
    end
    
    local colN = BuildProgressionColumn(col2, "Normal", "N", "PROG_N", {0, 1, 0})
    local colH = BuildProgressionColumn(colN, "Heroic", "H", "PROG_H", {0, 0.7, 1})
    
    -- ===========================
    -- COLUMN 5: SERVER / RECRUITER LIST (REPLACED MYTHIC)
    -- ===========================
    local colS = CreateFrame("Frame", nil, container)
    -- Anchored to colH now (since M is gone)
    colS:SetPoint("TOPLEFT", colH, "TOPRIGHT", 10, 0)
    colS:SetPoint("BOTTOM", colH, "BOTTOM", 0, 0)
    colS:SetWidth(260)
    CreateBlackBg(colS)

    -- Dynamic Server Title
    local currentRealm = GetRealmName()
    
    local hS = colS:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    hS:SetPoint("TOPLEFT", 10, -10); hS:SetText("Current Realm")
    
    local rName = colS:CreateFontString(nil, "OVERLAY", "GameFontNormalHuge")
    rName:SetPoint("TOPLEFT", 10, -35)
    rName:SetText(currentRealm)
    rName:SetTextColor(1, 0.82, 0) -- Gold

    -- Active Recruiters List
    local lblList = colS:CreateFontString(nil, "OVERLAY", "GameFontHighlightMedium")
    lblList:SetPoint("TOPLEFT", 10, -70)
    lblList:SetText("Recruiters (Addon Users):")

    local scrollS = CreateFrame("ScrollFrame", "GRS_RecruiterScroll", colS, "UIPanelScrollFrameTemplate")
    scrollS:SetPoint("TOPLEFT", 10, -95); scrollS:SetPoint("BOTTOMRIGHT", -25, 10)
    if NS.StyleScrollBar then NS.StyleScrollBar(scrollS) end

    local contentS = CreateFrame("Frame", nil, scrollS)
    contentS:SetSize(225, 300)
    scrollS:SetScrollChild(contentS)

    GR.recruiterRows = {}
    
    -- ===========================
    -- FOOTER & AUDIT
    -- ===========================
    
    local btnAudit = CreateFrame("Button", nil, container, "UIPanelButtonTemplate")
    btnAudit:SetSize(150, 30)
    btnAudit:SetPoint("TOPLEFT", col1, "BOTTOMLEFT", 0, -5)
    btnAudit:SetText("View Audit Log")
    btnAudit:SetScript("OnClick", function()
        if not GR.ReqHistoryFrame then 
            GR:BuildHistoryWindow() 
        end
        
        if GR.ReqHistoryFrame then
            GR:UpdateHistoryList()
            GR.ReqHistoryFrame:Show()
        end
    end)
    
    local btnSync = CreateFrame("Button", nil, container, "UIPanelButtonTemplate")
    btnSync:SetSize(150, 30)
    btnSync:SetPoint("LEFT", btnAudit, "RIGHT", 10, 0)
    btnSync:SetText("Sync with Guild")
    btnSync:SetScript("OnClick", function()
        GR:SyncRequirements()
    end)
    
    local gName = container:CreateFontString(nil, "OVERLAY", "GameFontNormalHuge")
    gName:SetPoint("BOTTOMRIGHT", -10, 10)
    gName:SetText(string.upper(GetGuildNameStr()))
    gName:SetTextColor(1, 0.82, 0, 1) 
    
    GR.RefreshReqUI = function()
        local db = _G.GRS_DB.requirements
        
        -- Classes
        for cls, row in pairs(GR.reqClassRows) do
            local val = db.classes[cls]
            row.cbL:SetChecked(val == "L")
            row.cbM:SetChecked(val == "M")
            row.cbH:SetChecked(val == "H")
        end
        
        -- Races
        for race, cb in pairs(GR.reqRaceRows) do
            cb:SetChecked(db.races[race] == true)
        end
        
        -- Progression
        for step, cb in pairs(GR.reqProgRows.N) do cb:SetChecked(db.progressionN[step] == true) end
        for step, cb in pairs(GR.reqProgRows.H) do cb:SetChecked(db.progressionH[step] == true) end
        
        -- Update Recruiter List (Column 5)
        -- Clear previous rows
        for _, row in ipairs(GR.recruiterRows) do row:Hide() end
        
        local realmData = db.servers[GetRealmName()]
        local y = 0
        
        if realmData and realmData.recruiter then
            -- Recruiter string is formatted "Name & Name & Name"
            for name in string.gmatch(realmData.recruiter, "[^&]+") do
                name = strtrim(name)
                if name ~= "" then
                    local row = GR.recruiterRows[y + 1] -- Reuse or create
                    
                    if not row then
                        row = contentS:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
                        row:SetPoint("TOPLEFT", 5, 0)
                        table.insert(GR.recruiterRows, row)
                    end
                    
                    -- Update position based on index (y)
                    row:SetPoint("TOPLEFT", 5, -(y * 20))
                    row:SetText("- " .. name)
                    row:Show()
                    y = y + 1
                end
            end
        else
            -- No recruiters listed yet
            local row = GR.recruiterRows[1]
            if not row then
                 row = contentS:CreateFontString(nil, "OVERLAY", "GameFontDisable")
                 row:SetPoint("TOPLEFT", 5, 0)
                 table.insert(GR.recruiterRows, row)
            end
            row:SetPoint("TOPLEFT", 5, 0)
            row:SetText("No active recruiters found.")
            row:Show()
        end

        gName:SetText(string.upper(GetGuildNameStr()))
    end
    
    GR:RefreshReqUI()
end

-- =========================================================================
-- 7. LOGIC & INITIALIZATION HOOK
-- =========================================================================

function GR:AutoRegisterServer()
    if not IsInGuild() then return end
    
    -- TBC: Use CanGuildInvite as fallback for officer check
    local hasOfficerAccess = (CanGuildInvite and CanGuildInvite()) or false
    if not hasOfficerAccess then return end
    
    local realm = GetRealmName()
    local myself = UnitName("player")
    local recruiterName = myself 
    
    local db = _G.GRS_DB.requirements.servers
    local entry = db[realm]
    
    if not entry then
        -- New Entry for this realm
        db[realm] = { recruiter = recruiterName, type = "Social" }
        SendSyncAction("SERVER", realm, recruiterName .. "~Social")
        print("GRS: Auto-assigned " .. recruiterName .. " to " .. realm)
    else
        -- Entry exists, check if name is present
        local current = entry.recruiter or ""
        local found = false
        
        -- Split by '&' and trim whitespace to check exact name match
        for part in string.gmatch(current, "[^&]+") do
            if strtrim(part) == recruiterName then 
                found = true 
                break 
            end
        end
        
        if not found then
            -- Append name (Sync format: Name & Name~Type)
            local newVal = current .. " & " .. recruiterName
            entry.recruiter = newVal
            local rType = entry.type or "Social"
            SendSyncAction("SERVER", realm, newVal .. "~" .. rType)
            print("GRS: Added " .. recruiterName .. " to recruiter list for " .. realm)
        end
    end
    
    -- Refresh UI to show self immediately
    if GR.RefreshReqUI then GR:RefreshReqUI() end
end

function GR:SyncRequirements()
    if not IsInGuild() then
        print("GRS: You must be in a guild to sync.")
        return
    end
    print("GRS: Sending recruitment requirements to guild...")

    local db = _G.GRS_DB.requirements
    local batch = ""
    local count = 0

    local function Append(cat, k, v)
         local str = string.format("%s:%s:%s", cat, k, tostring(v))
         
         if #batch + #str + 1 > 240 then
             GR:SafeSendAddonMessage("GRS_REQ", batch, "GUILD")
             batch = str
         else
             if batch == "" then batch = str else batch = batch .. "|" .. str end
         end
         count = count + 1
    end

    -- 1. Sync Classes
    for cls, p in pairs(db.classes) do 
        if p then Append("CLASS", cls, p) end
    end
    
    -- 2. Sync Races
    for race, b in pairs(db.races) do 
        if b then Append("RACE", race, b) end 
    end
    
    -- 3. Sync Progression
    for step, b in pairs(db.progressionN) do if b then Append("PROG_N", step, b) end end
    for step, b in pairs(db.progressionH) do if b then Append("PROG_H", step, b) end end
    
    -- 4. Sync Servers (Only sync current realm data to avoid bloat)
    local currentRealm = GetRealmName()
    local sData = db.servers[currentRealm]
    if sData and sData.recruiter then
        local val = sData.recruiter .. "~" .. (sData.type or "Social")
        Append("SERVER", currentRealm, val)
    end

    if batch ~= "" then 
        GR:SafeSendAddonMessage("GRS_REQ", batch, "GUILD") 
    end
    
    print("GRS: Sent " .. count .. " requirement settings.")
end

if GR then
    hooksecurefunc(GR, "Initialize", function(self)
        if self.views and self.views[3] then
            self:BuildRequirementsView(self.views[3])
            
            C_Timer.After(2, function() 
                if GR.AutoRegisterServer then GR:AutoRegisterServer() end
            end)
        end
    end)
    
    if GR.isInitialized and GR.views and GR.views[3] then
        GR:BuildRequirementsView(GR.views[3])
         C_Timer.After(2, function() 
             if GR.AutoRegisterServer then GR:AutoRegisterServer() end
         end)
    end
end