local MAJOR, MINOR = "LibMatic-IgnoreCharacters-1.0", 1
assert(LibStub, MAJOR .. " requires LibStub")
local lib = LibStub:NewLibrary(MAJOR, MINOR)
if not lib then return end

-- Per-character "ignore this alt" tracking, moved out of GearMatic's
-- Compat.lua and Settings.lua so every -Matic addon that tracks a roster of
-- characters can share the same realm-aware ignore list and AceConfig tab
-- instead of reimplementing both. Each embedding addon calls lib:New(config)
-- with accessors into its own saved variables and character table; the
-- returned handle owns the ignore set for that one addon.

function lib:NormalizeRealm(realm)
    if not realm or realm == "" then return nil end
    return (tostring(realm):gsub("[%s%-']", "")):lower()
end

function lib:IsPlayerRealm(realm)
    local n = self:NormalizeRealm(realm)
    if not n then return false end
    return n == self:NormalizeRealm(GetRealmName and GetRealmName())
end

local function defaultRealmOf(charKey, data)
    if data and data.realm then return data.realm end
    return charKey:match("^.-%-(.+)$")
end

local function defaultLabel(charKey, data)
    local label = charKey
    local class = data and data.class
    local color = class and RAID_CLASS_COLORS and RAID_CLASS_COLORS[class]
    if color and color.colorStr then
        label = "|c" .. color.colorStr .. charKey .. "|r"
    end
    if data and data.level then
        label = label .. " (" .. tostring(data.level) .. ")"
    end
    return label
end

local Handle = {}
local Handle_mt = { __index = Handle }

function lib:New(config)
    return setmetatable({ config = config }, Handle_mt)
end

function Handle:IsIgnored(charKey)
    if not charKey then return false end
    local store = self.config.store(false)
    return (store and store[charKey] == true) or false
end

function Handle:SetIgnored(charKey, ignored)
    if not charKey then return end
    local store = self.config.store(true)
    store[charKey] = ignored and true or nil
    if self.config.onChange then self.config.onChange() end
end

function Handle:KeepOnlyCurrentRealm()
    local characters = self.config.characters()
    if not characters then return end
    local realmOf = self.config.realmOf or defaultRealmOf
    local store = self.config.store(true)
    for charKey, data in pairs(characters) do
        store[charKey] = (not lib:IsPlayerRealm(realmOf(charKey, data))) and true or nil
    end
    if self.config.onChange then self.config.onChange() end
end

function Handle:BuildSettingsTab(order)
    local config = self.config
    local strings = config.strings
    local args = {}
    args.desc = {
        type = "description", order = 0, fontSize = "medium",
        name = strings.desc .. "\n",
    }
    local characters = config.characters()
    local hasChars = characters and next(characters) ~= nil
    if not hasChars then
        args.empty = {
            type = "description", order = 1, fontSize = "medium",
            name = strings.empty,
        }
    else
        args.others = {
            type = "execute", order = 1, width = "full",
            name = strings.others,
            desc = strings.othersDesc,
            func = function() self:KeepOnlyCurrentRealm() end,
        }
        args.ignores = {
            type = "multiselect", order = 2, width = "full",
            name = strings.list,
            desc = strings.listDesc,
            values = function()
                local out = {}
                local chars = config.characters()
                if chars then
                    local label = config.label or defaultLabel
                    for charKey, data in pairs(chars) do
                        out[charKey] = label(charKey, data)
                    end
                end
                return out
            end,
            get = function(_, charKey) return self:IsIgnored(charKey) end,
            set = function(_, charKey, val) self:SetIgnored(charKey, val) end,
        }
    end
    if config.extraArgs then
        for key, node in pairs(config.extraArgs()) do
            args[key] = node
        end
    end
    return {
        type = "group", order = order,
        name = strings.tab,
        args = args,
    }
end
