local addonName, NS = ...

-- =========================================================================
-- Blacklist Module (Fixed: Removed os.time() for WoW API time())
-- =========================================================================

NS.Blacklist = NS.Blacklist or {}
local M = NS.Blacklist

-- =========================================================================
-- Local 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

local function GetTableSize(t)
    local count = 0
    if t then
        for _ in pairs(t) do count = count + 1 end
    end
    return count
end

-- =========================================================================
-- Attach API
-- =========================================================================

function M.Attach(GR)
    if not GR or GR.__BlacklistAttached then return end
    GR.__BlacklistAttached = true

    -- Initialize Options DB if missing
    if not GR.db.blacklistOptions then
        GR.db.blacklistOptions = {
            autoReset = false,
            resetDuration = 604800 -- Default 1 Week
        }
    end

    -- =========================================================================
    -- View 2: Blacklist UI
    -- =========================================================================

    function GR:BuildBlacklistView()
        local GR = self -- capture for closures

        local parent = CreateFrame("Frame", "GRS_BlacklistView", self.ViewContainer)
        parent:SetPoint("TOPLEFT", 0, -30)
        parent:SetPoint("BOTTOMRIGHT", 0, 0)
        parent:Hide()
        self.views[2] = parent

        -- Split Layout: Left Controls (300px), Right List (Rest)
        local controls = CreateFrame("Frame", nil, parent)
        controls:SetWidth(300)
        controls:SetPoint("TOPLEFT")
        controls:SetPoint("BOTTOMLEFT")
        CreateBg(controls, 0.1, 0.1, 0.1, 0.5)
        CreateBorder(controls, 0.2, 0.2, 0.2, 1)

        -- [[ COLUMNS CONFIGURATION ]]
        local headers = {
            {text="Name", width=140},
            {text="Race", width=100},
            {text="Class", width=100}
        }
        
        -- Calculate Total Width needed
        local totalColWidth = 0
        for _, h in ipairs(headers) do totalColWidth = totalColWidth + h.width end
        
        -- List Frame Logic:
        local listFrameWidth = totalColWidth + 25 + 20 

        local listFrame = CreateFrame("Frame", nil, parent)
        listFrame:SetPoint("TOPLEFT", controls, "TOPRIGHT", 0, 0)
        listFrame:SetWidth(listFrameWidth)
        listFrame:SetPoint("BOTTOM", 0, 0) 
        
        CreateBg(listFrame, 0, 0, 0, 0.6)

        -- [[ CONTROLS ]]
        local y = -20
        local function AddLbl(txt)
            local t = controls:CreateFontString(nil, "OVERLAY", "GameFontNormal")
            t:SetPoint("TOPLEFT", 15, y)
            t:SetText(txt)
            y = y - 25
        end

        AddLbl("MANAGE BLACKLIST")

        local btnReset = CreateFrame("Button", nil, controls, "UIPanelButtonTemplate")
        btnReset:SetSize(140, 24)
        btnReset:SetPoint("TOPLEFT", 15, y)
        btnReset:SetText("Reset Entire List")
        SkinButton(btnReset)
        btnReset:SetScript("OnClick", function()
            GR:ResetBlacklist()
        end)

        local btnDelSel = CreateFrame("Button", nil, controls, "UIPanelButtonTemplate")
        btnDelSel:SetSize(120, 24)
        btnDelSel:SetPoint("LEFT", btnReset, "RIGHT", 5, 0)
        btnDelSel:SetText("Reset Selection")
        SkinButton(btnDelSel)
        btnDelSel:SetScript("OnClick", function()
            GR:RemoveSelectedFromBlacklist()
        end)

        y = y - 40
        AddLbl("MANUAL ADD")

        local inputAdd = CreateFrame("EditBox", nil, controls, "InputBoxTemplate")
        inputAdd:SetSize(180, 24)
        inputAdd:SetPoint("TOPLEFT", 15, y)
        inputAdd:SetAutoFocus(false)
        inputAdd:SetScript("OnEscapePressed", function(s) s:ClearFocus() end)

        local btnAdd = CreateFrame("Button", nil, controls, "UIPanelButtonTemplate")
        btnAdd:SetSize(80, 24)
        btnAdd:SetPoint("LEFT", inputAdd, "RIGHT", 5, 0)
        btnAdd:SetText("Add")
        SkinButton(btnAdd)
        btnAdd:SetScript("OnClick", function()
            local n = inputAdd:GetText()
            if n and n ~= "" then
                GR:AddToBlacklist(n)
                inputAdd:SetText("")
                print("Added " .. n .. " to Blacklist.")
            end
        end)

        -- [[ AUTOMATION SECTION ]]
        y = y - 40
        AddLbl("AUTOMATION")

        local autoCheck = CreateFrame("CheckButton", nil, controls, "UICheckButtonTemplate")
        autoCheck:SetSize(24, 24)
        autoCheck:SetPoint("TOPLEFT", 15, y)
        autoCheck.text = autoCheck:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
        autoCheck.text:SetPoint("LEFT", autoCheck, "RIGHT", 5, 0)
        autoCheck.text:SetText("Automatic Reset")
        autoCheck:SetChecked(GR.db.blacklistOptions.autoReset)
        
        autoCheck:SetScript("OnClick", function(self)
            GR.db.blacklistOptions.autoReset = self:GetChecked()
            if GR.db.blacklistOptions.autoReset then
                GR:CheckAutoReset()
            end
        end)

        y = y - 30
        
        -- Dropdown Implementation
        local dd = CreateFrame("Button", nil, controls)
        CreateBg(dd, 0.2, 0.2, 0.2, 1)
        CreateBorder(dd, 0, 0, 0, 1)
        dd:SetSize(180, 24)
        dd:SetPoint("TOPLEFT", 15, y)
        
        local ddText = dd:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        ddText:SetPoint("LEFT", 5, 0)
        
        local ddArrow = dd:CreateTexture(nil, "ARTWORK")
        ddArrow:SetTexture("Interface\\Buttons\\UI-ScrollBar-ScrollDownButton-Up")
        ddArrow:SetSize(20, 20)
        ddArrow:SetPoint("RIGHT", -2, 0)

        local options = {
            { label = "1 Day", val = 86400 },
            { label = "1 Week", val = 604800 },
            { label = "2 Weeks", val = 1209600 },
            { label = "1 Month", val = 2592000 },
            { label = "2 Months", val = 5184000 },
        }

        local function UpdateDDLabel()
            local v = GR.db.blacklistOptions.resetDuration
            local l = "1 Week"
            for _, opt in ipairs(options) do
                if opt.val == v then l = opt.label break end
            end
            ddText:SetText(l)
        end
        UpdateDDLabel()

        local ddList = CreateFrame("Frame", nil, dd)
        CreateBg(ddList, 0.1, 0.1, 0.1, 1)
        CreateBorder(ddList, 0.5, 0.5, 0.5, 1)
        ddList:SetSize(180, #options * 20 + 10)
        ddList:SetPoint("TOPLEFT", dd, "BOTTOMLEFT", 0, -2)
        ddList:SetFrameStrata("FULLSCREEN_DIALOG")
        ddList:Hide()

        for i, opt in ipairs(options) do
            local b = CreateFrame("Button", nil, ddList)
            b:SetSize(170, 20)
            b:SetPoint("TOPLEFT", 5, -5 - ((i-1)*20))
            local t = b:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
            t:SetPoint("LEFT")
            t:SetText(opt.label)
            
            b:SetScript("OnEnter", function() t:SetTextColor(1, 1, 1) end)
            b:SetScript("OnLeave", function() t:SetTextColor(0.8, 0.8, 0.8) end)
            b:SetScript("OnClick", function()
                GR.db.blacklistOptions.resetDuration = opt.val
                UpdateDDLabel()
                ddList:Hide()
                if GR.db.blacklistOptions.autoReset then
                    GR:CheckAutoReset()
                end
            end)
        end

        dd:SetScript("OnClick", function()
            ddList:SetShown(not ddList:IsShown())
        end)

        -- [[ GUILD SYNC ]]
        y = y - 50 -- Push down further
        AddLbl("GUILD SYNC")

        local btnSync = CreateFrame("Button", nil, controls, "UIPanelButtonTemplate")
        btnSync:SetSize(265, 30)
        btnSync:SetPoint("TOPLEFT", 15, y)
        btnSync:SetText("Sync with Guild")
        SkinButton(btnSync)
        btnSync:SetScript("OnClick", function()
            GR:SyncBlacklist()
        end)

        y = y - 35
        local syncInfo = controls:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        syncInfo:SetPoint("TOPLEFT", 15, y)
        syncInfo:SetWidth(270)
        syncInfo:SetJustifyH("LEFT")
        syncInfo:SetText("Sends your blacklist to online guild members using this addon and merges theirs.")

        -- [[ LIST HEADER ]]
        local headF = CreateFrame("Frame", nil, listFrame)
        headF:SetSize(20, 20)
        headF:SetPoint("TOPLEFT", 0, -5)
        headF:SetPoint("TOPRIGHT", 0, -5)

        -- "Select All" Checkbox
        local cbAll = CreateFrame("CheckButton", nil, headF, "UICheckButtonTemplate")
        cbAll:SetSize(20, 20)
        cbAll:SetPoint("LEFT", 5, 0)
        cbAll:SetScript("OnClick", function(self)
            local state = self:GetChecked()
            if GR.db and GR.db.blacklist then
                for _, entry in pairs(GR.db.blacklist) do
                    if type(entry) == "table" then
                        entry.selected = state
                    end
                end
            end
            GR:UpdateBlacklistScroll()
        end)

        -- Column Headers
        local lh = nil
        for i, h in ipairs(headers) do
            local b = CreateFrame("Button", nil, headF)
            b:SetSize(h.width, 20)
            if i == 1 then
                b:SetPoint("LEFT", 30, 0) -- Leaves space for the checkbox (5 + 20 + 5 padding)
            else
                b:SetPoint("LEFT", lh, "RIGHT", 0, 0)
            end
            local t = b:CreateFontString(nil, "OVERLAY", "GameFontNormal")
            t:SetPoint("LEFT")
            t:SetText(h.text)
            lh = b
        end

        -- [[ SCROLL LIST ]]
        self.blScroll = CreateFrame("ScrollFrame", "GRS_BLScroll", listFrame, "FauxScrollFrameTemplate")
        self.blScroll:SetPoint("TOPLEFT", headF, "BOTTOMLEFT", 0, -5)
        self.blScroll:SetPoint("BOTTOMRIGHT", -25, 5)
        CreateBg(self.blScroll, 0, 0, 0, 0.3)

        self.blScroll:SetScript("OnVerticalScroll", function(s, offset)
            FauxScrollFrame_OnVerticalScroll(s, offset, 20, function()
                self:UpdateBlacklistScroll()
            end)
        end)

        self.blRows = {}
        for i = 1, 33 do
            local r = CreateFrame("Button", nil, listFrame)
            r:SetHeight(20)
            r:SetPoint("LEFT", 5, 0)
            r:SetPoint("RIGHT", -5, 0)

            if i == 1 then
                r:SetPoint("TOP", self.blScroll, "TOP")
            else
                r:SetPoint("TOP", self.blRows[i-1], "BOTTOM")
            end

            r.c = CreateFrame("CheckButton", nil, r, "UICheckButtonTemplate")
            r.c:SetSize(20, 20)
            r.c:SetPoint("LEFT", 0, 0)
            r.c:SetScript("OnClick", function(b)
                if r.data then r.data.selected = b:GetChecked() end
            end)

            r.n = r:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
            r.n:SetPoint("LEFT", 25, 0); r.n:SetWidth(140); r.n:SetJustifyH("LEFT")

            r.ra = r:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
            r.ra:SetPoint("LEFT", r.n, "RIGHT"); r.ra:SetWidth(100); 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")

            self.blRows[i] = r
        end

        parent:SetScript("OnShow", function()
            -- Check reset logic when showing
            if GR.CheckAutoReset then GR:CheckAutoReset() end
            self:UpdateBlacklistScroll()
        end)
    end

    -- =========================================================================
    -- Blacklist Logic & Sync
    -- =========================================================================

    function GR:GetBlacklistAsArray()
        local arr = {}
        for k, v in pairs(self.db.blacklist) do
            if type(v) == "table" then
                table.insert(arr, v)
            else
                table.insert(arr, {name = k, rio = 0, heroic = "-", mythic = "-", fullClass = "Unknown"})
            end
        end
        table.sort(arr, function(a, b) return a.name < b.name end)
        return arr
    end

    function GR:UpdateBlacklistScroll()
        local list = self:GetBlacklistAsArray()
        local numRows = #self.blRows

        FauxScrollFrame_Update(self.blScroll, #list, numRows, 20)

        local offset = FauxScrollFrame_GetOffset(self.blScroll)

        for i = 1, numRows do
            local r = self.blRows[i]
            local idx = offset + i
            if idx <= #list then
                local d = list[idx]
                r.data = d
                r:Show()
                r.n:SetText(d.name)
                r.ra:SetText(d.race or "-")
                r.cl:SetText(d.fullClass or "-")
                r.c:SetChecked(d.selected or false)
            else
                r:Hide()
            end
        end
    end

    function GR:CheckAutoReset()
        if not self.db.blacklistOptions.autoReset then return end
        
        local duration = self.db.blacklistOptions.resetDuration or 604800
        -- FIXED: Use WoW API time() instead of os.time()
        local now = time() 
        local removedCount = 0
        local toRemove = {}

        for name, data in pairs(self.db.blacklist) do
            -- Only remove if we have a valid timestamp
            if data.timestamp and type(data.timestamp) == "number" then
                if (now - data.timestamp) >= duration then
                    table.insert(toRemove, name)
                end
            end
        end

        for _, name in ipairs(toRemove) do
            self.db.blacklist[name] = nil
            removedCount = removedCount + 1
        end

        if removedCount > 0 then
            print("GRS: Auto-Reset removed " .. removedCount .. " expired blacklist entries.")
            if self.views and self.views[2] and self.views[2]:IsShown() then
                self:UpdateBlacklistScroll()
            end
        end
    end

    function GR:AddToBlacklist(name)
        if not name then return end

        -- [[ FIX: STRICT NORMALIZATION ]]
        if not string.find(name, "-") then
            name = name .. "-" .. GetRealmName()
        end

        local data = nil
        -- Check if we have data on this player in the current scan results
        for _, p in ipairs(self.foundPlayers) do
            local pName = p.name
            if not string.find(pName, "-") then pName = pName .. "-" .. GetRealmName() end
            
            if pName == name then 
                data = p; 
                break 
            end
        end

        -- FIXED: Use WoW API time() instead of os.time()
        local currentTime = time()

        if data then
            self.db.blacklist[name] = {
                name = data.name, 
                race = data.race,
                fullClass = data.fullClass,
                rio = data.rio,
                heroic = data.heroic,
                mythic = data.mythic,
                level = data.level,
                zone = data.zone,
                timestamp = currentTime 
            }
        else
            self.db.blacklist[name] = {
                name = name,
                race = "Unknown",
                fullClass = "Unknown",
                rio = 0,
                heroic = "-",
                mythic = "-",
                level = 0,
                zone = "Unknown",
                timestamp = currentTime 
            }
        end

        -- Immediately remove from the current search results view if present
        if self.RemovePlayer then self:RemovePlayer(name) end
        
        local shortName = string.match(name, "^(.-)-")
        if shortName and self.RemovePlayer then self:RemovePlayer(shortName) end

        if self.AddToRecent then self:AddToRecent(name, "Blacklisted") end
        
        if self.views and self.views[2] and self.views[2].IsShown and self.views[2]:IsShown() then
            self:UpdateBlacklistScroll()
        end
    end

    function GR:RemoveSelectedFromBlacklist()
        local list = self:GetBlacklistAsArray()
        for _, d in ipairs(list) do
            if d.selected then
                self.db.blacklist[d.name] = nil
                if not string.find(d.name, "-") then
                    self.db.blacklist[d.name .. "-" .. GetRealmName()] = nil
                end
            end
        end
        self:UpdateBlacklistScroll()
    end

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

        print("GRS: Sending blacklist to guild members...")

        local str = ""
        local count = 0
        for name, d in pairs(self.db.blacklist) do
            local entry = string.format("%s:%s:%s:%s", name, d.rio or 0, d.heroic or "-", d.mythic or "-")

            if #str + #entry + 1 > 240 then
                C_ChatInfo.SendAddonMessage("GRS_SYNC", str, "GUILD")
                str = entry
            else
                if str == "" then str = entry else str = str .. "|" .. entry end
            end
            count = count + 1
        end

        if str ~= "" then
            C_ChatInfo.SendAddonMessage("GRS_SYNC", str, "GUILD")
        end

        print("GRS: Sent " .. count .. " entries.")
    end

    function GR:HandleComm(prefix, text, channel, sender)
        if prefix ~= "GRS_SYNC" then return end
        if sender == UnitName("player") then return end

        local entries = { strsplit("|", text) }
        local new = 0
        -- FIXED: Use WoW API time()
        local currentTime = time()

        for _, e in ipairs(entries) do
            local n, r, h, m = strsplit(":", e)
            if n and not self.db.blacklist[n] then
                if not string.find(n, "-") then n = n .. "-" .. GetRealmName() end
                
                self.db.blacklist[n] = {
                    name = n,
                    rio = r,
                    heroic = h,
                    mythic = m,
                    race = "Unknown",
                    fullClass = "Synced",
                    level = 0,
                    timestamp = currentTime
                }
                new = new + 1
            end
        end

        if new > 0 and self.views and self.views[2] and self.views[2].IsShown and self.views[2]:IsShown() then
            self:UpdateBlacklistScroll()
            print("GRS: Synced " .. new .. " new blacklist entries from " .. sender)
        end
    end

    function GR:ManualBlacklist()
        local toBlacklist = {}
        for _, p in ipairs(self.foundPlayers) do
            if p.selected then table.insert(toBlacklist, p.name) end
        end

        if #toBlacklist == 0 then
            print("No players selected to blacklist.")
            return
        end

        for _, name in ipairs(toBlacklist) do
            self:AddToBlacklist(name)
        end
        print(string.format("Added %d players to blacklist.", #toBlacklist))
    end

    function GR:ResetBlacklist()
        self.db.blacklist = {}
        self.db.recentHistory = {}
        self.foundPlayers = {}
        if self.UpdateRecentList then self:UpdateRecentList() end
        if self.UpdateScrollFrame then self:UpdateScrollFrame() end
        if self.views and self.views[2] and self.views[2].IsShown and self.views[2]:IsShown() then
            self:UpdateBlacklistScroll()
        end
        print("GRS: Blacklist wiped.")
    end

    local blSize = GR.db and GR.db.blacklist and GetTableSize(GR.db.blacklist) or 0
    
    -- Run reset check on Attach/Startup
    C_Timer.After(2, function()
        if GR.db and GR.CheckAutoReset then GR:CheckAutoReset() end
    end)
end