local PURPLE = "|cff9212d5"
local RESET = "|r"

local function say(msg)
    DEFAULT_CHAT_FRAME:AddMessage(PURPLE .. "LibMatic" .. RESET .. ": " .. tostring(msg))
end

local function testIconPicker()
    local picker = LibStub("LibMatic-IconPicker-1.0", true)
    if not picker then
        say("IconPicker library not loaded")
        return
    end
    say("opening IconPicker...")
    picker:Open(nil, function(chosen)
        if chosen then
            say("picked fileID " .. tostring(chosen))
        else
            say("cancelled")
        end
    end)
end

local function testChangeLog()
    local changelog = LibStub("LibMatic-ChangeLog-1.0", true)
    if not changelog then
        say("ChangeLog library not loaded")
        return
    end
    say("opening ChangeLog sample...")
    changelog:Show({
        title = "LibMatic - Change Log",
        statusText = "Sample changelog for /libmatictest changelog",
        version = "1.0.0",
        footer = "For the full version history see CurseForge.",
        entries = {
            {
                version = "1.0.0",
                date = "05/21/2026",
                sections = {
                    { label = "Added", body = "Sample change log entry rendered by LibMatic-ChangeLog-1.0. Scroll to confirm the popup, version header, section label, and body all render." },
                },
            },
        },
    })
end

local function testStartup()
    local startup = LibStub("LibMatic-Startup-1.0", true)
    if not startup then
        say("Startup library not loaded")
        return
    end
    local config = {
        name = "LibMatic",
        version = "1.0.0",
        useFactionColors = true,
        optionsCommand = "/lmt",
        helpCommand = "/lmt startup",
        commands = {
            { header = true, label = "Test Commands" },
            { command = "/lmt", desc = "Open the icon picker." },
            { command = "/lmt changelog", desc = "Show the sample changelog." },
            { command = "/lmt settings", desc = "Open the sample settings panel." },
            { command = "/lmt media", desc = "Register and scan custom media." },
            { command = "/lmt startup", desc = "Print this startup banner." },
        },
    }
    local h1 = startup:Register(config)
    local h2 = startup:Register(config)
    startup:PrintBanner("LibMatic")
    startup:PrintHelp("LibMatic")
    startup:PrintBanner("NotRegistered")
    local faction = (UnitFactionGroup and UnitFactionGroup("player")) or "none"
    say("startup: register idempotent = " .. tostring(h1 == h2)
        .. ", brand faction = " .. faction)
end

local function testSettings()
    local settings = LibStub("LibMatic-Settings-1.0", true)
    if not settings then
        say("Settings library not loaded")
        return
    end

    local store = {
        general = { sampleToggle = true },
        alert = { critFormat = "New %s Crit: %d!", hitFormat = "New %s Hit: %d!" },
        sound = { critSound = "None", hitSound = "None" },
        social = { party = true, raid = false, guild = true, battleground = false },
        bounceStyle = "legacy",
        alertPos = { xPos = 50, yPos = 50 },
    }
    local function tbl(name)
        return function() return store[name] end
    end

    local general = settings:BuildGeneralPage({
        order = 1,
        currentAddon = "LibMatic",
        bind = { table = tbl("general") },
        toggles = {
            { key = "sampleToggle", name = "Sample Toggle", desc = "A sample toggle." },
        },
        support = { discordURL = "https://discord.gg/sample" },
        nav = { factionIcons = true },
    })
    local alert = settings:BuildAlertPage({
        order = 2,
        bind = { table = tbl("alert") },
        notificationTypes = {
            { key = "critFormat", title = "Crit", defaultFormat = "New %s Crit: %d!" },
            { key = "hitFormat", title = "Hit", defaultFormat = "New %s Hit: %d!" },
        },
        bounce = {
            get = function() return store.bounceStyle end,
            set = function(_, v) store.bounceStyle = v end,
        },
        position = {
            get = function() return store.alertPos.xPos, store.alertPos.yPos end,
            set = function(x, y)
                store.alertPos.xPos = x
                store.alertPos.yPos = y
            end,
            default = function() return 50, 50 end,
            close = function()
                local acd = LibStub("AceConfigDialog-3.0", true)
                if acd then acd:Close("LibMaticSettingsTest") end
            end,
            reopen = function()
                local acd = LibStub("AceConfigDialog-3.0", true)
                if acd then acd:Open("LibMaticSettingsTest") end
            end,
        },
    })
    local sound = settings:BuildSoundPage({
        order = 3,
        bind = { table = tbl("sound") },
        slots = {
            { key = "critSound", label = "Crit Sound" },
            { key = "hitSound", label = "Hit Sound" },
        },
        scan = {
            addon = "LibMatic",
            onResult = function(s, f)
                say("custom media scan: " .. tostring(s) .. " sounds, " .. tostring(f) .. " fonts")
            end,
        },
    })
    local social = settings:BuildSocialPage({
        order = 4,
        bind = { table = tbl("social") },
    })
    local changeLog = settings:BuildChangeLogPage({
        order = 5,
        profile = function() return {} end,
    })
    local profiles = settings:BuildProfilesPage({ order = 90 })

    local hiddenPage = settings:BuildSocialPage({ show = false })
    local hiddenSetting = settings:BuildSocialPage({
        bind = { table = tbl("social") },
        channels = { { key = "party", show = function() return false end } },
    })
    local hiddenSettingOk = hiddenSetting and hiddenSetting.args
        and hiddenSetting.args.party
        and type(hiddenSetting.args.party.hidden) == "function"

    local resolveOk = settings:ResolveShow(nil) == true
        and settings:ResolveShow(true) == true
        and settings:ResolveShow(false) == false
        and settings:ResolveShow(function() return true end) == true
        and settings:ResolveShow(function() return false end) == false

    local pagesOk = general and alert and sound and social and changeLog and profiles

    say("settings: pages built = " .. tostring(pagesOk and true or false)
        .. ", hidden-page nil = " .. tostring(hiddenPage == nil)
        .. ", hidden-setting = " .. tostring(hiddenSettingOk and true or false)
        .. ", ResolveShow = " .. tostring(resolveOk))

    local positioner = LibStub("LibMatic-AlertPositioner-1.0", true)
    local positionerOk = positioner and type(positioner.Open) == "function"
    local positionNode = alert and alert.args and alert.args.generalTab
        and alert.args.generalTab.args and alert.args.generalTab.args.positionAlert
    local positionNodeOk = positionNode and positionNode.type == "execute"
        and type(positionNode.func) == "function"

    say("positioner: lib = " .. tostring(positionerOk and true or false)
        .. ", position node = " .. tostring(positionNodeOk and true or false))

    local scanNode = sound and sound.args and sound.args.scanCustom
    local scanNodeOk = scanNode and scanNode.type == "execute"
        and type(scanNode.func) == "function"

    say("custom media: scan node = " .. tostring(scanNodeOk and true or false))

    local AceConfig = LibStub("AceConfig-3.0", true)
    local AceConfigDialog = LibStub("AceConfigDialog-3.0", true)
    if AceConfig and AceConfigDialog then
        AceConfig:RegisterOptionsTable("LibMaticSettingsTest", {
            name = "LibMatic Settings Test",
            type = "group",
            args = {
                general = general,
                alert = alert,
                sound = sound,
                social = social,
                changeLog = changeLog,
                profiles = profiles,
            },
        })
        AceConfigDialog:Open("LibMaticSettingsTest")
        say("opened LibMaticSettingsTest panel")
    else
        say("AceConfig not present, skipped panel open")
    end
end

local function testCustomMedia()
    local cm = LibStub("LibMatic-CustomMedia-1.0", true)
    if not cm then
        say("CustomMedia library not loaded")
        return
    end
    local LSM = LibStub("LibSharedMedia-3.0", true)
    local cache = { [3] = "Interface\\AddOns\\LibMatic\\CustomSounds\\Sound3.ogg" }
    local sounds, fonts = cm:Register({
        addon = "LibMatic",
        sounds = 10,
        fonts = 10,
        soundCache = cache,
    })
    local reg = cm:GetRegistered("LibMatic")
    local nameOk = reg and reg.sounds and reg.sounds[3] == "LibMatic Custom Sound 3"
    local scanSounds, scanFonts = cm:Scan("LibMatic")
    say("customMedia: LSM = " .. tostring(LSM and true or false)
        .. ", cache name = " .. tostring(nameOk and true or false)
        .. ", register s/f = " .. tostring(sounds) .. "/" .. tostring(fonts)
        .. ", scan s/f = " .. tostring(scanSounds) .. "/" .. tostring(scanFonts))
end

local function testBroadcast()
    local broadcast = LibStub("LibMatic-Broadcast-1.0", true)
    if not broadcast then
        say("Broadcast library not loaded")
        return
    end
    broadcast:Register({
        name = "LibMatic",
        commPrefix = "LMBTEST",
        electionEnabled = false,
        dedupeSeconds = 5,
    })
    local inGroup = IsInGroup and IsInGroup()
    local peers = broadcast:GetPeers("LibMatic")
    say("broadcast: inGroup = " .. tostring(inGroup and true or false)
        .. ", peers = " .. tostring(#peers))
    if inGroup then
        broadcast:Broadcast("LibMatic", { text = "LibMatic broadcast test", marker = 8 })
        broadcast:Broadcast("LibMatic", { text = "LibMatic broadcast test", marker = 8 })
        say("sent one marked test line (a second within 5s was deduped)")
    else
        say("join a party or raid to see the test line sent")
    end
end

local function testSoundPack()
    local pack = LibStub("LibMatic-SoundPack-1.0", true)
    if not pack then
        say("SoundPack library not loaded")
        return
    end
    local n = pack:Register("LibMatic", "")
    say("SoundPack registered " .. tostring(n) .. " sounds")
    local LSM = LibStub("LibSharedMedia-3.0", true)
    if LSM then
        local path = LSM:Fetch("sound", "Boop")
        if path and PlaySoundFile then PlaySoundFile(path, "Master") end
        say("fetched Boop -> " .. tostring(path))
    end
end

SLASH_LIBMATICTEST1 = "/libmatictest"
SLASH_LIBMATICTEST2 = "/lmt"
SlashCmdList["LIBMATICTEST"] = function(msg)
    local cmd = (msg or ""):lower():match("^(%S*)")
    if cmd == "changelog" then
        testChangeLog()
    elseif cmd == "startup" then
        testStartup()
    elseif cmd == "settings" then
        testSettings()
    elseif cmd == "media" then
        testCustomMedia()
    elseif cmd == "broadcast" then
        testBroadcast()
    elseif cmd == "soundpack" then
        testSoundPack()
    else
        testIconPicker()
    end
end
