-- Assistant GroupFrames generic setting registration helpers.
-- Loaded before MSUF_AssistantRegistry_GroupFrames_Core.lua.
local addonName, MSUF = ...
MSUF = MSUF or _G.MSUF_NS or {}

local M = MSUF.MSUF2 or _G.MSUF2 or {}
MSUF.MSUF2 = M

local A = MSUF.Assistant or {}
MSUF.Assistant = A
M.Assistant = A

A.GroupFramesRegistry = A.GroupFramesRegistry or {}

function A.GroupFramesRegistry.BuildRegisterCoreContext(ctx)
    if type(ctx) ~= "table" then return nil end

    local Registry = ctx.Registry
    local UNIT_LABELS = ctx.UNIT_LABELS or {}
    local GroupDB = ctx.GroupDB
    local ClampNumber = ctx.ClampNumber
    local ApplyGroup = ctx.ApplyGroup

    if not (Registry and type(Registry.RegisterSetting) == "function") then return nil end
    if type(GroupDB) ~= "function" or type(ClampNumber) ~= "function" or type(ApplyGroup) ~= "function" then return nil end

    local function RegisterGroupBoolean(scope, attr, dbKey, label, defaultValue, mode, aliases, opts)
        opts = opts or {}
        Registry:RegisterSetting({
            key = "gf_" .. scope .. "." .. (opts.keySuffix or dbKey),
            label = UNIT_LABELS[scope] .. " " .. label,
            category = UNIT_LABELS[scope] .. " / Group Frames",
            unit = scope,
            frameType = "group",
            attribute = attr,
            type = "boolean",
            aliases = aliases,
            exactAliases = opts.exactAliases,
            matchLabel = opts.matchLabel,
            booleanAliases = opts.booleanAliases,
            valueAliases = opts.valueAliases,
            intentGuard = opts.intentGuard,
            get = function()
                if opts.get then return opts.get(scope) end
                local value = GroupDB(scope)[dbKey]
                if value == nil then return defaultValue and true or false end
                return value and true or false
            end,
            set = function(value)
                if opts.set then opts.set(scope, value); return end
                GroupDB(scope)[dbKey] = value and true or false
            end,
            apply = function() ApplyGroup(scope, opts.mode or mode or "visual") end,
            description = opts.description,
            combatSafe = false,
        })
    end

    local function RegisterGroupNumber(scope, attr, dbKey, label, defaultValue, minValue, maxValue, step, mode, aliases, opts)
        opts = opts or {}
        Registry:RegisterSetting({
            key = "gf_" .. scope .. "." .. dbKey,
            label = UNIT_LABELS[scope] .. " " .. label,
            category = UNIT_LABELS[scope] .. " / Group Frames",
            unit = scope,
            frameType = "group",
            attribute = attr,
            type = "number",
            aliases = aliases,
            min = minValue,
            max = maxValue,
            step = step or 1,
            percent = opts.percent == true,
            get = function()
                if opts.get then return opts.get(scope) end
                local value = tonumber(GroupDB(scope)[dbKey])
                if value == nil then return defaultValue end
                return value
            end,
            set = function(value)
                if opts.set then opts.set(scope, value); return end
                GroupDB(scope)[dbKey] = ClampNumber(value, minValue, maxValue, step or 1)
            end,
            apply = function() ApplyGroup(scope, opts.mode or mode or "visual") end,
            combatSafe = false,
            description = opts.description,
        })
    end

    local function RegisterGroupEnum(scope, attr, dbKey, label, defaultValue, values, valueAliases, mode, aliases, opts)
        opts = opts or {}
        local allowed = {}
        for i = 1, #(values or {}) do allowed[values[i]] = true end
        Registry:RegisterSetting({
            key = "gf_" .. scope .. "." .. dbKey,
            label = UNIT_LABELS[scope] .. " " .. label,
            category = UNIT_LABELS[scope] .. " / Group Frames",
            unit = scope,
            frameType = "group",
            attribute = attr,
            type = "enum",
            aliases = aliases,
            exactAliases = opts.exactAliases,
            values = values,
            valueAliases = valueAliases,
            get = function()
                if opts.get then return opts.get(scope) end
                local value = GroupDB(scope)[dbKey]
                if allowed[value] then return value end
                return defaultValue
            end,
            set = function(value)
                if opts.set then opts.set(scope, value); return end
                if not allowed[value] then value = defaultValue end
                GroupDB(scope)[dbKey] = value
            end,
            apply = function() ApplyGroup(scope, opts.mode or mode or "visual") end,
            combatSafe = false,
        })
    end

    local function RegisterGroupString(scope, attr, dbKey, label, defaultValue, mode, aliases, opts)
        opts = opts or {}
        Registry:RegisterSetting({
            key = "gf_" .. scope .. "." .. dbKey,
            label = UNIT_LABELS[scope] .. " " .. label,
            category = UNIT_LABELS[scope] .. " / Group Frames",
            unit = scope,
            frameType = "group",
            attribute = attr,
            type = "string",
            aliases = aliases,
            valuePrefixes = opts.valuePrefixes or aliases,
            mediaType = opts.mediaType,
            get = function()
                if opts.get then return opts.get(scope) end
                local value = GroupDB(scope)[dbKey]
                if type(value) ~= "string" or value == "" then return defaultValue or "" end
                return value
            end,
            set = function(value)
                if opts.set then opts.set(scope, value); return end
                GroupDB(scope)[dbKey] = tostring(value or "")
            end,
            apply = function() ApplyGroup(scope, opts.mode or mode or "visual") end,
            combatSafe = false,
            description = opts.description,
        })
    end

    return {
        RegisterGroupBoolean = RegisterGroupBoolean,
        RegisterGroupNumber = RegisterGroupNumber,
        RegisterGroupEnum = RegisterGroupEnum,
        RegisterGroupString = RegisterGroupString,
    }
end
