local addonName, NS = ...

-- =========================================================================
-- Blacklist Module (Fixed: Ghost Blacklist Logic)
-- =========================================================================

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

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

        local listFrame = CreateFrame("Frame", nil, parent)
        listFrame:SetPoint("TOPLEFT", controls, "TOPRIGHT")
        listFrame:SetPoint("BOTTOMRIGHT")
        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)

        y = y - 40
        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)

        local headers = {
            {text="Name", width=140},
            {text="Race", width=100},
            {text="Class", width=100},
            {text="Score", width=80},
            {text="Heroic", width=80},
            {text="Mythic", width=80}
        }

        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)
            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, 25 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")

            r.s = r:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
            r.s:SetPoint("LEFT", r.cl, "RIGHT"); r.s:SetWidth(80); r.s:SetJustifyH("LEFT")

            r.h = r:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
            r.h:SetPoint("LEFT", r.s, "RIGHT"); r.h:SetWidth(80); r.h:SetJustifyH("LEFT")

            r.m = r:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
            r.m:SetPoint("LEFT", r.h, "RIGHT"); r.m:SetWidth(80); r.m:SetJustifyH("LEFT")

            self.blRows[i] = r
        end

        parent:SetScript("OnShow", function()
            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.s:SetText(d.rio or 0)
                r.h:SetText(d.heroic or "-")
                r.m:SetText(d.mythic or "-")
                r.c:SetChecked(d.selected or false)
            else
                r:Hide()
            end
        end
    end

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

        -- [[ FIX: STRICT NORMALIZATION ]]
        -- If name is just "Krazzothane", allow it, but preferably convert to "Krazzothane-Realm".
        -- For consistent blacklist keys, we check if it has a dash. If not, append realm.
        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
            -- Check p.name (which should be full name) or normalize it too
            local pName = p.name
            if not string.find(pName, "-") then pName = pName .. "-" .. GetRealmName() end
            
            if pName == name then 
                data = p; 
                break 
            end
        end

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

        -- Immediately remove from the current search results view if present
        if self.RemovePlayer then self:RemovePlayer(name) end
        
        -- Also try removing the non-realm version just in case of display mismatch
        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
                -- Try to remove both keys to be safe
                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

        for _, e in ipairs(entries) do
            local n, r, h, m = strsplit(":", e)
            if n and not self.db.blacklist[n] then
                -- [[ FIX: Ensure synced names are normalized ]]
                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
                }
                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
end