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

-- Import Constants
local COMM_PREFIX = GR.RR.CONST.COMM_PREFIX
local COMM_DELIM = GR.RR.CONST.COMM_DELIM
local MAX_COMM_CHUNK = GR.RR.CONST.MAX_COMM_CHUNK
local Sanitize = GR.RR.Sanitize
local GetFullPlayerName = GR.RR.GetFullPlayerName
local ParseDate = GR.RR.ParseDate

-- =========================================================================
-- NETWORK LAYER
-- =========================================================================

function GR:RR_BroadcastEvent(eventData)
    if not IsInGuild() then return end
    local timeStr = (eventData.startTime or "00:00") .. "-" .. (eventData.endTime or "00:00")
    local str = table.concat({
        "EVT", eventData.id, Sanitize(eventData.name), eventData.date, timeStr, 
        eventData.type, eventData.limit or 99, eventData.rankLimit or 99, Sanitize(eventData.def or "")
    }, COMM_DELIM)
    C_ChatInfo.SendAddonMessage(COMM_PREFIX, str, "GUILD")
    
    -- If broadcasting the event creation/edit, also broadcast the roster state immediately
    GR:RR_BroadcastRosterFull(eventData.id)
end

function GR:RR_BroadcastDelete(idList)
    if not IsInGuild() or #idList == 0 then return end
    local str = "DEL" .. COMM_DELIM .. table.concat(idList, ",")
    C_ChatInfo.SendAddonMessage(COMM_PREFIX, str, "GUILD")
end

function GR:RR_BroadcastSignUp(eventId, role, status)
    if not IsInGuild() then return end
    local str = table.concat({"SIGNUP", eventId, role, status, GetServerTime()}, COMM_DELIM)
    C_ChatInfo.SendAddonMessage(COMM_PREFIX, str, "GUILD")
end

function GR:RR_BroadcastModStatus(eventId, targetName, targetRole, newStatus)
    if not IsInGuild() then return end
    -- Strip realm before broadcasting to ensure network consistency
    local cleanTarget = Ambiguate(targetName, "none")
    local str = table.concat({"MOD_STATUS", eventId, cleanTarget, targetRole, newStatus, GetServerTime()}, COMM_DELIM)
    C_ChatInfo.SendAddonMessage(COMM_PREFIX, str, "GUILD")
end

function GR:RR_BroadcastRemove(eventId, targetName)
    if not IsInGuild() then return end
    local cleanTarget = Ambiguate(targetName, "none")
    local str = table.concat({"REMOVE_PLAYER", eventId, cleanTarget}, COMM_DELIM)
    C_ChatInfo.SendAddonMessage(COMM_PREFIX, str, "GUILD")
end

function GR:RR_BroadcastRosterFull(eventId)
    if not IsInGuild() then return end
    local evt = GRS_RaidRosterDB.events[eventId]
    if not evt then return end
    
    -- 1. Send Clear
    C_ChatInfo.SendAddonMessage(COMM_PREFIX, "ROSTER_CLEAR"..COMM_DELIM..eventId, "GUILD")
    
    -- 2. Build Bulk Data
    local buffer = ""
    
    local function AddToBuffer(name, role, status, timeVal)
        -- Format: Name:Role:Status:Time
        local entry = table.concat({name, role, status, timeVal or 0}, ":")
        if #buffer + #entry + 1 > MAX_COMM_CHUNK then
            -- Flush
            C_ChatInfo.SendAddonMessage(COMM_PREFIX, "ROSTER_DAT"..COMM_DELIM..eventId..COMM_DELIM..buffer, "GUILD")
            buffer = entry
        else
            if buffer == "" then buffer = entry else buffer = buffer .. ";" .. entry end
        end
    end
    
    for roleKey, list in pairs(evt.roster) do
        for _, member in ipairs(list) do
            AddToBuffer(member.name, member.role, member.status, member.time)
        end
    end
    
    if buffer ~= "" then
         C_ChatInfo.SendAddonMessage(COMM_PREFIX, "ROSTER_DAT"..COMM_DELIM..eventId..COMM_DELIM..buffer, "GUILD")
    end
end

function GR:RR_RequestSync()
    if IsInGuild() then C_ChatInfo.SendAddonMessage(COMM_PREFIX, "REQ_SYNC", "GUILD") end
end

function GR:RR_OnComm(prefix, text, channel, sender)
    if prefix ~= COMM_PREFIX then return end
    
    local senderName = Ambiguate(sender, "none")
    if senderName == GetFullPlayerName() then return end
    
    local parts = { strsplit(COMM_DELIM, text) }
    local op = parts[1]
    
    if op == "REQ_SYNC" then
        if GRS_RaidRosterDB and GRS_RaidRosterDB.events then
            for _, evt in pairs(GRS_RaidRosterDB.events) do 
                GR:RR_BroadcastEvent(evt) 
            end
        end
        
    elseif op == "EVT" then
        local id = parts[2]
        if not id then return end
        
        if not GRS_RaidRosterDB then GRS_RaidRosterDB = {} end
        if not GRS_RaidRosterDB.events then GRS_RaidRosterDB.events = {} end

        local evt = GRS_RaidRosterDB.events[id]
        if not evt then
            evt = { roster = { TANK={}, HEALER={}, DPS={}, BENCH={}, TENTATIVE={}, ABSENT={}, NOSHOW={} } }
            GRS_RaidRosterDB.events[id] = evt
        end
        
        evt.id = id; evt.name = parts[3]; evt.date = parts[4]
        local ts, te = strsplit("-", parts[5] or "")
        evt.startTime = ts; evt.endTime = te
        evt.time = parts[5]
        
        evt.type = parts[6]; evt.limit = tonumber(parts[7])
        evt.rankLimit = tonumber(parts[8]); evt.def = parts[9]
        GR:RR_ScanDB()
        
    elseif op == "ROSTER_CLEAR" then
        local eid = parts[2]
        local evt = GRS_RaidRosterDB.events[eid]
        if evt then
            evt.roster = { TANK={}, HEALER={}, DPS={}, BENCH={}, TENTATIVE={}, ABSENT={}, NOSHOW={} }
            if GR.RR.selectedEvent and GR.RR.selectedEvent.id == eid then GR:RR_SelectEvent(evt) end
        end
        
    elseif op == "ROSTER_DAT" then
        local eid = parts[2]
        local payload = parts[3]
        local evt = GRS_RaidRosterDB.events[eid]
        
        if evt and payload then
            for entry in string.gmatch(payload, "([^;]+)") do
                local name, role, status, ts = strsplit(":", entry)
                ts = tonumber(ts) or 0
                GR:RR_UpdateMemberStatus(eid, name, role, status, ts)
            end
        end
        
    elseif op == "DEL" then
        local ids = parts[2]
        if ids then
            for id in string.gmatch(ids, "([^,]+)") do
                GRS_RaidRosterDB.events[id] = nil
            end
            GR:RR_ScanDB()
            if GR.RR.selectedEvent and not GRS_RaidRosterDB.events[GR.RR.selectedEvent.id] then
                GR:RR_SelectEvent(nil)
            end
        end
        
    elseif op == "SIGNUP" or op == "MOD_STATUS" then
        local eid, target, role, status, ts
        
        if op == "SIGNUP" then
            eid = parts[2]; target = sender; role = parts[3]; status = parts[4]; ts = tonumber(parts[5])
        else
            eid = parts[2]; target = parts[3]; role = parts[4]; status = parts[5]; ts = tonumber(parts[6])
            local displayTarget = strsplit("-", Ambiguate(target, "none"))
            GR:RR_AddLogEntry(senderName, string.format("Set %s to %s for event %s", displayTarget, status, eid))
        end
        GR:RR_UpdateMemberStatus(eid, target, role, status, ts)
        
    elseif op == "REMOVE_PLAYER" then
        local eid, target = parts[2], parts[3]
        GR:RR_RemoveMember(eid, target)
    end
end