-- =========================================================================
-- GRS RECRUITMENT HISTORY v11.6 (NO TIME & STYLED BUTTON)
-- =========================================================================

local addonName, NS = ...
local GR_Funcs = {}

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

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

-- =========================================================================
-- 2. CONFIG & ASSETS
-- =========================================================================

-- TBC Classes Only
local CLASS_ICON_TCOORDS = {
    ["WARRIOR"] = {0, 0.25, 0, 0.25}, ["MAGE"] = {0.25, 0.5, 0, 0.25},
    ["ROGUE"] = {0.5, 0.75, 0, 0.25}, ["DRUID"] = {0.75, 1, 0, 0.25},
    ["HUNTER"] = {0, 0.25, 0.25, 0.5}, ["SHAMAN"] = {0.25, 0.5, 0.25, 0.5},
    ["PRIEST"] = {0.5, 0.75, 0.25, 0.5}, ["WARLOCK"] = {0.75, 1, 0.25, 0.5},
    ["PALADIN"] = {0, 0.25, 0.5, 0.75},
}

local function ColorText(text, r, g, b)
    if not text then return "" end
    if not r then r, g, b = 1, 1, 1 end
    return string.format("|cff%02x%02x%02x%s|r", r*255, g*255, b*255, text)
end

-- =========================================================================
-- 3. DATA PERSISTENCE ENGINE
-- =========================================================================

local RosterCache = {}

local function GetGuildKey()
    local gName = GetGuildInfo("player")
    if not gName then return nil end
    local realm = GetRealmName()
    return gName .. "-" .. (realm or "")
end

local function UpdateRosterCache()
    table.wipe(RosterCache)
    if not IsInGuild() then return end
    for i = 1, GetNumGuildMembers() do
        local name, _, _, _, _, _, _, _, _, _, classFileName = GetGuildRosterInfo(i)
        if name and classFileName then
            RosterCache[name] = classFileName
            local short = string.match(name, "^([^%-]+)")
            if short then RosterCache[short] = classFileName end
        end
    end
end

local function ResolveClass(name, dbClass)
    if dbClass then return dbClass end
    if not name then return nil end
    if RosterCache[name] then return RosterCache[name] end
    local short = string.match(name, "^([^%-]+)")
    if short and RosterCache[short] then return RosterCache[short] end
    return nil
end

local function GenerateDNA(y, m, d, h, min, type, p1, p2)
    return string.format("%d:%d:%d:%d:%d|%s|%s|%s", y, m, d, h, min, type, p1 or "nil", p2 or "nil")
end

-- =========================================================================
-- 4. LOG SCRAPER
-- =========================================================================

local function ScrapeLogIndex(index)
    if not index then return end
    
    local eventType, player1, player2, rank, year, month, day, weekday, hour, minute = GetGuildEventInfo(index)
    
    if not eventType then return end
    
    -- Normalize Year immediately for sorting purposes (even if not displayed)
    if year and year > 0 and year < 100 then 
        year = year + 2000 
    end
    
    local gKey = GetGuildKey()
    if not gKey then return end
    
    if not GRS_HistoryDB then GRS_HistoryDB = {} end
    if not GRS_HistoryDB[gKey] then GRS_HistoryDB[gKey] = {} end
    local activeDB = GRS_HistoryDB[gKey]
    
    local y, m, d, h, min = year or 0, month or 0, day or 0, hour or 0, minute or 0
    local dna = GenerateDNA(y, m, d, h, min, eventType, player1, player2)
    
    local isDuplicate = false
    for _, stored in ipairs(activeDB) do
        if stored.dna == dna then isDuplicate = true; break end
    end
    
    if not isDuplicate then
        local c1 = ResolveClass(player1)
        local c2 = ResolveClass(player2)
        
        table.insert(activeDB, {
            dna = dna, type = eventType, p1 = player1, p2 = player2, 
            cP1 = c1, cP2 = c2, rank = rank,
            y = y, m = m, d = d, h = h, min = min,
            source = "API"
        })
    end
end

local function ActivateLogQuery()
    if IsInGuild() and QueryGuildEventLog then
        QueryGuildEventLog()
    end
end

-- =========================================================================
-- 5. UI BUILDERS
-- =========================================================================

local function CreateLogFrame(parent, title)
    local f = CreateFrame("Frame", nil, parent, "BackdropTemplate")
    local t = f:CreateTexture(nil, "BACKGROUND"); t:SetAllPoints(); t:SetColorTexture(0,0,0,0.5)
    f.bg = t
    
    local lbl = f:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    lbl:SetPoint("TOP", 0, -15); lbl:SetText(title)
    
    local sf = CreateFrame("ScrollFrame", nil, f, "UIPanelScrollFrameTemplate")
    sf:SetPoint("TOPLEFT", 10, -45); sf:SetPoint("BOTTOMRIGHT", -30, 10)
    if NS.StyleScrollBar then NS.StyleScrollBar(sf) end
    
    local content = CreateFrame("Frame", nil, sf)
    content:SetSize(sf:GetWidth(), 500); sf:SetScrollChild(content)
    
    f.scroll = sf; f.content = content; f.rows = {}
    return f
end

local function CreateRow(parent)
    local r = CreateFrame("Frame", nil, parent)
    r:SetSize(300, 45)
    
    r.icon = r:CreateTexture(nil, "ARTWORK"); r.icon:SetSize(24, 24); r.icon:SetPoint("LEFT", 5, 0)
    r.icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark") 
    
    -- Removed Date
    -- Centered Name next to Icon
    r.name = r:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    r.name:SetPoint("LEFT", r.icon, "RIGHT", 10, 0)
    
    r.details = r:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    r.details:SetPoint("RIGHT", -5, 0); r.details:SetJustifyH("RIGHT")
    
    r.line = r:CreateTexture(nil, "ARTWORK"); r.line:SetHeight(1)
    r.line:SetColorTexture(0.2, 0.2, 0.2, 0.5)
    r.line:SetPoint("BOTTOMLEFT", 0, 0); r.line:SetPoint("BOTTOMRIGHT", 0, 0)
    
    return r
end

-- =========================================================================
-- 6. MAIN LOGIC
-- =========================================================================

function GR_Funcs.PopulateHistory(self)
    if not IsInGuild() then return end
    
    ActivateLogQuery()
    UpdateRosterCache()
    
    local gKey = GetGuildKey()
    if not gKey then return end 
    
    if not GRS_HistoryDB then GRS_HistoryDB = {} end
    if not GRS_HistoryDB[gKey] then GRS_HistoryDB[gKey] = {} end
    local activeDB = GRS_HistoryDB[gKey]
    
    local viewList = { joins = {}, ranks = {}, leaves = {} }
    
    local numEvents = GetNumGuildEvents()
    for i = 1, numEvents do 
        ScrapeLogIndex(i) 
    end
    
    for _, entry in ipairs(activeDB) do
        -- Sort Value using full date
        local sortVal = 0
        if entry.y and entry.y >= 2000 then
            sortVal = time({year=entry.y, month=entry.m, day=entry.d, hour=entry.h, min=entry.min})
        end
        
        -- No Time String
        local rowData = { 
            ts = "", type = entry.type, p1 = entry.p1, p2 = entry.p2, 
            cP1 = entry.cP1, cP2 = entry.cP2, rank = entry.rank, val = sortVal 
        }
        
        if entry.type == "invite" or entry.type == "join" then table.insert(viewList.joins, rowData)
        elseif entry.type == "promote" or entry.type == "demote" then table.insert(viewList.ranks, rowData)
        elseif entry.type == "remove" or entry.type == "quit" then table.insert(viewList.leaves, rowData)
        end
    end
    
    local function SortNewest(a, b) return a.val > b.val end
    table.sort(viewList.joins, SortNewest)
    table.sort(viewList.ranks, SortNewest)
    table.sort(viewList.leaves, SortNewest)
    
    self:FillLogFrame(self.histJoinFrame, viewList.joins)
    self:FillLogFrame(self.histRankFrame, viewList.ranks)
    self:FillLogFrame(self.histLeaveFrame, viewList.leaves)
end

function GR_Funcs.FillLogFrame(self, frame, data)
    if not frame then return end
    for _, r in ipairs(frame.rows) do r:Hide() end
    
    local y = 0
    for i, entry in ipairs(data) do
        local r = frame.rows[i]
        if not r then r = CreateRow(frame.content); frame.rows[i] = r end
        
        r:SetWidth(frame.content:GetWidth())
        r:SetPoint("TOPLEFT", 0, y)
        r:Show()
        
        local sName, details, rC, gC, bC = "Unknown", "", 1, 1, 1
        local classFile = nil
        
        if entry.type == "invite" then 
            sName = entry.p2; classFile = entry.cP2
            details = "Invited by\n"..(entry.p1 or "?"); rC,gC,bC = 0,1,0
        elseif entry.type == "join" then 
            sName = entry.p1; classFile = entry.cP1
            details = "Joined"; rC,gC,bC = 0,1,0
        elseif entry.type == "promote" then 
            sName = entry.p2; classFile = entry.cP2
            details = "Promoted to "..(entry.rank or "?").."\nby "..(entry.p1 or "?"); rC,gC,bC = 0.2,1,0.2
        elseif entry.type == "demote" then 
            sName = entry.p2; classFile = entry.cP2
            details = "Demoted to "..(entry.rank or "?").."\nby "..(entry.p1 or "?"); rC,gC,bC = 1,0.5,0
        elseif entry.type == "remove" then 
            sName = entry.p2; classFile = entry.cP2
            details = "Kicked by\n"..(entry.p1 or "?"); rC,gC,bC = 1,0,0
        elseif entry.type == "quit" then 
            sName = entry.p1; classFile = entry.cP1
            details = "Left Guild"; rC,gC,bC = 1,0.5,0
        end
        
        if not sName then sName = "Unknown" end
        if not classFile then classFile = ResolveClass(sName) end

        if classFile and CLASS_ICON_TCOORDS[classFile] then
            r.icon:SetTexture("Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Classes")
            r.icon:SetTexCoord(unpack(CLASS_ICON_TCOORDS[classFile]))
            
            local cObj = C_ClassColor.GetClassColor(classFile)
            if cObj then 
                r.icon:SetVertexColor(1, 1, 1) 
                r.name:SetText(ColorText(sName, cObj.r, cObj.g, cObj.b))
            else
                r.name:SetText(ColorText(sName, 0.6, 0.6, 0.6))
            end
        else
            r.icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark")
            r.icon:SetTexCoord(0.08, 0.92, 0.08, 0.92) 
            r.icon:SetVertexColor(1, 1, 1) 
            r.name:SetText(ColorText(sName, 0.6, 0.6, 0.6))
        end
        
        r.details:SetText(details)
        r.details:SetTextColor(rC, gC, bC)
        
        y = y - 45
    end
    frame.content:SetHeight(math.abs(y) + 20)
end

function GR_Funcs.BuildHistoryView(self, parent)
    if not parent then return end
    
    for _, region in ipairs({parent:GetRegions()}) do
        if region:GetObjectType() == "FontString" then region:Hide() end
    end

    if not self.histGuildLabel then
        self.histGuildLabel = parent:CreateFontString(nil, "OVERLAY", "GameFontNormalHuge")
        self.histGuildLabel:SetPoint("TOP", 0, -55)
        self.histGuildLabel:SetTextColor(1, 0.82, 0)
    end
    local gName = GetGuildInfo("player") or "No Guild"
    self.histGuildLabel:SetText(gName)
    
    local fJoin = self.histJoinFrame or CreateLogFrame(parent, "Invites")
    self.histJoinFrame = fJoin
    
    local fRank = self.histRankFrame or CreateLogFrame(parent, "Promotions")
    self.histRankFrame = fRank
    
    local fLeave = self.histLeaveFrame or CreateLogFrame(parent, "Departures")
    self.histLeaveFrame = fLeave
    
    local function UpdateLayout()
        local w = parent:GetWidth(); if not w or w < 10 then w = 800 end
        local colWidth = (w - 40) / 3
        
        fJoin:SetSize(colWidth, parent:GetHeight() - 85)
        fJoin:ClearAllPoints(); fJoin:SetPoint("TOPLEFT", 10, -75)
        
        fRank:SetSize(colWidth, parent:GetHeight() - 85)
        fRank:ClearAllPoints(); fRank:SetPoint("TOPLEFT", fJoin, "TOPRIGHT", 10, 0)
        
        fLeave:SetSize(colWidth, parent:GetHeight() - 85)
        fLeave:ClearAllPoints(); fLeave:SetPoint("TOPLEFT", fRank, "TOPRIGHT", 10, 0)
        
        fJoin.content:SetWidth(colWidth-40)
        fRank.content:SetWidth(colWidth-40)
        fLeave.content:SetWidth(colWidth-40)
    end
    
    parent:SetScript("OnSizeChanged", UpdateLayout)
    parent:SetScript("OnShow", function()
        UpdateLayout()
        local cName = GetGuildInfo("player") or "No Guild"
        if self.histGuildLabel then self.histGuildLabel:SetText(cName) end
        
        if IsInGuild() then
            ActivateLogQuery() 
            C_Timer.After(0.5, function() self:PopulateHistory() end)
        end
    end)
    
    if not parent.refreshBtn then
        local btn = CreateFrame("Button", nil, parent) -- Removed Template
        btn:SetSize(100, 25)
        -- Lowered Button by 20px (-10 -> -30)
        btn:SetPoint("TOPRIGHT", -10, -30) 
        
        -- Text Label
        local t = btn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        t:SetPoint("CENTER")
        t:SetText("Force Refresh")
        btn:SetFontString(t)
        
        SkinButton(btn) -- Applied Custom Style
        
        btn:SetScript("OnClick", function() 
            self:PopulateHistory() 
        end)
        parent.refreshBtn = btn
    end
    
    if not self.histEventFrame then
        self.histEventFrame = CreateFrame("Frame")
        self.histEventFrame:RegisterEvent("GUILD_EVENT_LOG_UPDATE")
        self.histEventFrame:SetScript("OnEvent", function() 
            if parent:IsVisible() then self:PopulateHistory() end 
        end)
    end
    
    UpdateLayout()
end

if _G["GRS_MainFrame"] then
    local GR = _G["GRS_MainFrame"]
    GR.PopulateHistory = GR_Funcs.PopulateHistory
    GR.FillLogFrame = GR_Funcs.FillLogFrame
    GR.BuildHistoryView = GR_Funcs.BuildHistoryView
    
    hooksecurefunc(GR, "Initialize", function(self)
        if self.views and self.views[4] then self:BuildHistoryView(self.views[4]) end
    end)
    
    if GR.isInitialized and GR.views and GR.views[4] then
        GR:BuildHistoryView(GR.views[4])
    end
    
    -- print("|cff00ff00GRS:|r Recruitment History (TBC) Active.")
end