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

-- =========================================================================
-- 1. DATABASE & CONSTANTS
-- =========================================================================

local REQ_DEFAULTS = {
    classes = {}, 
    races = {},   
    progressionN = {}, -- Normal
    progressionH = {}, -- Heroic
    progressionM = {}, -- Mythic
    history = {}  
}

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

local CLASS_LIST = {
    "Death Knight", "Demon Hunter", "Druid", "Evoker", "Hunter", 
    "Mage", "Monk", "Paladin", "Priest", "Rogue", 
    "Shaman", "Warlock", "Warrior"
}

local RACE_LIST = {
    "Blood Elf", "Dark Iron Dwarf", "Dracthyr", "Draenei", "Dwarf", "Earthen", 
    "Gnome", "Goblin", "Highmountain Tauren", "Human", "Kul Tiran", 
    "Lightforged Draenei", "Mag'har Orc", "Mechagnome", "Night Elf", 
    "Nightborne", "Orc", "Pandaren", "Tauren", "Troll", "Undead", 
    "Void Elf", "Vulpera", "Worgen", "Zandalari Troll"
}
table.sort(RACE_LIST)

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
    
    -- Ensure distinct tables for difficulties
    if type(db.progressionN) ~= "table" then db.progressionN = {} end
    if type(db.progressionH) ~= "table" then db.progressionH = {} end
    if type(db.progressionM) ~= "table" then db.progressionM = {} 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

-- Sends a single update immediately
local function SendSyncAction(category, key, value)
    if not IsInGuild() then return end
    local msg = string.format("%s:%s:%s", category, key, tostring(value))
    C_ChatInfo.SendAddonMessage("GRS_REQ", msg, "GUILD")
end

-- Handles incoming messages (Supports Single "cat:key:val" and Bulk "cat:key:val|cat:key:val")
local function OnCommReceived(prefix, text, channel, sender)
    if prefix ~= "GRS_REQ" then return end
    if sender == UnitName("player") then return end
    
    -- Split by pipe to handle bulk messages
    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 == "PROG_M" then
                local bVal = (val == "true")
                db.progressionM[key] = bVal
                desc = string.format("Mythic Raid: %s %s", key, bVal and "Selected" or "Deselected")
            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)
    
    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

-- =========================================================================
-- 5. 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(400)
    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(380, 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
    -- ===========================
    local col2 = CreateFrame("Frame", nil, container)
    col2:SetPoint("TOPLEFT", col1, "TOPRIGHT", 15, 0)
    col2:SetPoint("BOTTOMLEFT", col1, "BOTTOMRIGHT", 15, 0)
    col2:SetWidth(200)
    CreateBlackBg(col2)
    
    local h2 = col2:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    h2:SetPoint("TOPLEFT", 10, -10); h2:SetText("Race Selection")
    
    local scrollR = CreateFrame("ScrollFrame", "GRS_ReqRaceScroll", col2, "UIPanelScrollFrameTemplate")
    scrollR:SetPoint("TOPLEFT", 5, -40); scrollR:SetPoint("BOTTOMRIGHT", -25, 5)
    
    local contentR = CreateFrame("Frame", nil, scrollR)
    contentR:SetSize(170, #RACE_LIST * 25)
    scrollR:SetScrollChild(contentR)
    
    GR.reqRaceRows = {}
    local ry = 0
    for _, race in ipairs(RACE_LIST) 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-5: RAID PROGRESSION (N/H/M)
    -- ===========================
    
    GR.reqProgRows = { N = {}, H = {}, M = {} }
    
    -- Helper to build columns
    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(150)
        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
                if dbKey == "M" then db.progressionM[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, "Raid Normal", "N", "PROG_N", {0, 1, 0})
    local colH = BuildProgressionColumn(colN, "Raid Heroic", "H", "PROG_H", {0, 0.7, 1})
    local colM = BuildProgressionColumn(colH, "Raid Mythic", "M", "PROG_M", {1, 0.5, 0})
    
    -- ===========================
    -- 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)
    
    -- [[ NEW SYNC BUTTON ]]
    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) -- Golden
    
    GR.RefreshReqUI = function()
        local db = _G.GRS_DB.requirements
        
        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
        
        for race, cb in pairs(GR.reqRaceRows) do
            cb:SetChecked(db.races[race] == true)
        end
        
        -- Refresh 3 Raid Columns
        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
        for step, cb in pairs(GR.reqProgRows.M) do cb:SetChecked(db.progressionM[step] == true) end
        
        gName:SetText(string.upper(GetGuildNameStr()))
    end
    
    GR:RefreshReqUI()
end

-- =========================================================================
-- 6. LOGIC & INITIALIZATION HOOK
-- =========================================================================

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)
         -- format: CAT:KEY:VAL
         local str = string.format("%s:%s:%s", cat, k, tostring(v))
         
         -- Check if adding this entry exceeds 240 chars (safe limit for addons)
         if #batch + #str + 1 > 240 then
             C_ChatInfo.SendAddonMessage("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
    for step, b in pairs(db.progressionM) do if b then Append("PROG_M", step, b) end end

    -- Send remaining buffer
    if batch ~= "" then 
        C_ChatInfo.SendAddonMessage("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])
        end
    end)
    
    if GR.isInitialized and GR.views and GR.views[3] then
        GR:BuildRequirementsView(GR.views[3])
    end
end