local addonName, FN = ...
FN = FN or FavoriteNeighborhood or {}
FavoriteNeighborhood = FN

FN.Debug = FN.Debug or {}
local Debug = FN.Debug

local ANIM_INTERVAL = 1.2
local DEBUG_FULL_ID = "__FN_DEBUG_COMPLETE__"
local DEBUG_FULL_NAME = "98 Debug Complete"
local DEBUG_TEST_ID = "__FN_DEBUG_NEIGHBORHOOD__"
local DEBUG_TEST_NAME = "99 Debug District"
local DEBUG_CHAR_KEY = "Debug Tester - DebugRealm"
local ticker = nil
local activeOverride = nil

local function refreshOptions()
    if FN and FN.RefreshOptionsIfVisible then
        FN.RefreshOptionsIfVisible()
    elseif FN and FN.UpdateOptionsFrame and FN.OptionsFrame and FN.OptionsFrame:IsShown() then
        FN.UpdateOptionsFrame()
    end
end


local function triggerProgressUpdate(id)
    if FN and FN.AutoSwitch and FN.AutoSwitch.HandleProgressUpdated then
        FN.AutoSwitch:HandleProgressUpdated(id)
    end
end

local function tryAutoSwitchFromDebug()
    if FN and FN.AutoSwitch and FN.AutoSwitch.TrySwitch and FN.GetActiveNeighborhood then
        local currentID = FN.GetActiveNeighborhood()
        if currentID then
            FN.AutoSwitch:TrySwitch(currentID)
        end
    end
end

local function ensureEntry(entry, defaults)
    entry = entry or {}
    if entry.progress == nil then entry.progress = defaults.progress end
    if entry.animated == nil then entry.animated = defaults.animated end
    if entry.state == nil then entry.state = defaults.state end
    return entry
end

local function ensureConfig()
    FN_DB = FN_DB or {}
    FN_DB.config = FN_DB.config or {}
    FN_DB.config.debug = FN_DB.config.debug or {}
    local cfg = FN_DB.config.debug
    if cfg.enabled == nil then cfg.enabled = false end
    if cfg.preview == nil then cfg.preview = "LIVE" end

    cfg.entries = cfg.entries or {}
    -- migrate older single-state debug settings onto the editable district entry
    if cfg.progress ~= nil or cfg.animated ~= nil or cfg.state ~= nil then
        cfg.entries[DEBUG_TEST_ID] = cfg.entries[DEBUG_TEST_ID] or {}
        if cfg.progress ~= nil then cfg.entries[DEBUG_TEST_ID].progress = cfg.progress end
        if cfg.animated ~= nil then cfg.entries[DEBUG_TEST_ID].animated = cfg.animated end
        if cfg.state ~= nil then cfg.entries[DEBUG_TEST_ID].state = cfg.state end
        cfg.progress = nil
        cfg.animated = nil
        cfg.state = nil
    end

    cfg.entries[DEBUG_FULL_ID] = ensureEntry(cfg.entries[DEBUG_FULL_ID], { progress = 100, animated = false, state = "ALL_COMPLETE" })
    cfg.entries[DEBUG_TEST_ID] = ensureEntry(cfg.entries[DEBUG_TEST_ID], { progress = 40, animated = false, state = "DEBUG" })
    return cfg
end

function Debug:GetConfig()
    return ensureConfig()
end

function Debug:GetNeighborhoodConfig(id)
    local cfg = ensureConfig()
    local sid = tostring(id or self:GetActiveNeighborhoodOverride() or DEBUG_TEST_ID)
    cfg.entries = cfg.entries or {}
    cfg.entries[sid] = cfg.entries[sid] or ensureEntry(nil, { progress = 0, animated = false, state = "DEBUG" })
    return cfg.entries[sid]
end

function Debug:GetSelectedNeighborhoodID()
    local selected = self:GetActiveNeighborhoodOverride()
    if self:IsDebugNeighborhood(selected) then
        return tostring(selected)
    end
    return DEBUG_TEST_ID
end

function Debug:GetSelectedNeighborhoodConfig()
    return self:GetNeighborhoodConfig(self:GetSelectedNeighborhoodID())
end

function Debug:IsEnabled()
    return ensureConfig().enabled and true or false
end

function Debug:IsDebugNeighborhood(id)
    if id == nil then return false end
    local sid = tostring(id)
    return sid == DEBUG_FULL_ID or sid == DEBUG_TEST_ID
end

function Debug:IsDebugTestNeighborhood(id)
    return id ~= nil and tostring(id) == DEBUG_TEST_ID
end

function Debug:IsDebugFullNeighborhood(id)
    return id ~= nil and tostring(id) == DEBUG_FULL_ID
end

function Debug:GetDebugCharacterKey()
    return DEBUG_CHAR_KEY
end

function Debug:GetInjectedNeighborhoods()
    if not self:IsEnabled() then return {} end
    return {
        { text = DEBUG_FULL_NAME, value = DEBUG_FULL_ID, debug = true },
        { text = DEBUG_TEST_NAME, value = DEBUG_TEST_ID, debug = true },
    }
end

function Debug:GetDebugNeighborhoodItem()
    if not self:IsEnabled() then return nil end
    return { text = DEBUG_TEST_NAME, value = DEBUG_TEST_ID, debug = true }
end

function Debug:GetResolvedNeighborhoodName(id)
    if self:IsDebugFullNeighborhood(id) then
        return DEBUG_FULL_NAME
    elseif self:IsDebugTestNeighborhood(id) then
        return DEBUG_TEST_NAME
    end
    return nil
end

function Debug:GetProgressData(id)
    if not self:IsEnabled() then return nil end
    if not self:IsDebugNeighborhood(id) then return nil end
    local entry = self:GetNeighborhoodConfig(id)
    local percent = tonumber(entry.progress) or 0
    return {
        percent = percent,
        currentProgress = percent,
        maxProgress = 100,
        isComplete = percent >= 100,
        updatedAt = time(),
    }
end

function Debug:GetActiveNeighborhoodOverride()
    if not self:IsEnabled() then return nil end
    return activeOverride
end

function Debug:SetActiveNeighborhoodOverride(id)
    if not self:IsEnabled() then
        activeOverride = nil
        return false
    end
    if id and self:IsDebugNeighborhood(id) then
        activeOverride = tostring(id)
    else
        activeOverride = nil
    end
    refreshOptions()
    return true
end

function Debug:ClearActiveNeighborhoodOverride()
    activeOverride = nil
end

function Debug:IsPreviewActive()
    local cfg = ensureConfig()
    return cfg.enabled and cfg.preview == "DEBUG"
end

function Debug:SetEnabled(value)
    local cfg = ensureConfig()
    local wasEnabled = cfg.enabled and true or false
    local enable = value and true or false
    cfg.enabled = enable
    FN_DB = FN_DB or {}
    FN_DB.neighborhoods = FN_DB.neighborhoods or {}
    FN_DB.chars = FN_DB.chars or {}

    if enable and not wasEnabled then
        cfg.savedGlobal = FN_DB.global
    end

    if enable then
        FN_DB.neighborhoods[DEBUG_FULL_ID] = DEBUG_FULL_NAME
        FN_DB.neighborhoods[DEBUG_TEST_ID] = DEBUG_TEST_NAME
        FN_DB.chars[DEBUG_CHAR_KEY] = FN_DB.chars[DEBUG_CHAR_KEY] or { mode = "G", classID = 0, fav = DEBUG_TEST_ID, debug = true }
        if activeOverride == nil then
            activeOverride = DEBUG_FULL_ID
        end
        if not self:IsDebugNeighborhood(FN_DB.global) then
            FN_DB.global = DEBUG_FULL_ID
        end
    else
        FN_DB.neighborhoods[DEBUG_FULL_ID] = nil
        FN_DB.neighborhoods[DEBUG_TEST_ID] = nil
        FN_DB.chars[DEBUG_CHAR_KEY] = nil
    end
    if enable and cfg.preview == nil then
        cfg.preview = "DEBUG"
    end
    if enable and cfg.preview ~= "DEBUG" and cfg.preview ~= "LIVE" then
        cfg.preview = "DEBUG"
    end
    if not enable then
        cfg.preview = "LIVE"
        activeOverride = nil
        if FN_DB then
            if FN_DB.progress then
                FN_DB.progress[DEBUG_FULL_ID] = nil
                FN_DB.progress[DEBUG_TEST_ID] = nil
            end
            for _, entry in pairs(FN_DB.chars or {}) do
                if entry and entry.fav and self:IsDebugNeighborhood(entry.fav) then
                    entry.fav = nil
                    if entry.mode == "C" then
                        entry.mode = "G"
                    end
                end
            end
        end
        local restore = cfg.savedGlobal
        cfg.savedGlobal = nil
        if restore and not self:IsDebugNeighborhood(restore) then
            FN_DB.global = restore
        elseif FN_DB.global and self:IsDebugNeighborhood(FN_DB.global) then
            FN_DB.global = nil
        end
        if (not FN_DB.global) and FN_DB.neighborhoods then
            local firstReal = nil
            for id in pairs(FN_DB.neighborhoods) do
                if not self:IsDebugNeighborhood(id) then
                    firstReal = tostring(id)
                    break
                end
            end
            FN_DB.global = firstReal
        end
        if FN.RequestOwnedHouses then
            FN.RequestOwnedHouses()
        end
        if FN.RequestNeighborhoodProgress and FN_DB.global then
            FN.RequestNeighborhoodProgress(FN_DB.global)
        end
    end
    self:RefreshTicker()
    refreshOptions()
end

function Debug:ToggleEnabled()
    local newValue = not self:IsEnabled()
    self:SetEnabled(newValue)
    if newValue then
        local cfg = ensureConfig()
        cfg.preview = "DEBUG"
    end
    return newValue
end

function Debug:SetPreviewMode(mode)
    local cfg = ensureConfig()
    cfg.preview = (mode == "DEBUG") and "DEBUG" or "LIVE"
    self:RefreshTicker()
    refreshOptions()
end

function Debug:SetProgress(percent)
    local id = self:GetSelectedNeighborhoodID()
    local entry = self:GetNeighborhoodConfig(id)
    percent = tonumber(percent) or 0
    if percent < 0 then percent = 0 end
    if percent > 100 then percent = 100 end
    entry.progress = percent
    triggerProgressUpdate(id)
    refreshOptions()
end

function Debug:SetAnimated(value)
    local id = self:GetSelectedNeighborhoodID()
    local entry = self:GetNeighborhoodConfig(id)
    entry.animated = value and true or false
    self:RefreshTicker()
    triggerProgressUpdate(id)
    refreshOptions()
end

function Debug:GetProgressItems()
    local items = {}
    for pct = 0, 100, 20 do
        items[#items + 1] = { text = string.format("%d%%", pct), value = pct }
    end
    return items
end

function Debug:GetPreviewItems()
    return {
        { text = "Live", value = "LIVE" },
        { text = "Debug", value = "DEBUG" },
    }
end

function Debug:AdvanceAnimation()
    local id = self:GetSelectedNeighborhoodID()
    local entry = self:GetNeighborhoodConfig(id)
    local current = tonumber(entry.progress) or 0
    current = current + 20
    if current > 100 then
        current = 0
    end
    entry.progress = current
    triggerProgressUpdate(id)
    refreshOptions()
end

function Debug:EndSession()
    self:SetEnabled(false)
    self:ClearActiveNeighborhoodOverride()
end

function Debug:RefreshTicker()
    local cfg = ensureConfig()
    if ticker then
        ticker:Cancel()
        ticker = nil
    end
    local entry = self:GetSelectedNeighborhoodConfig()
    if cfg.enabled and cfg.preview == "DEBUG" and entry and entry.animated and C_Timer and C_Timer.NewTicker then
        ticker = C_Timer.NewTicker(ANIM_INTERVAL, function()
            Debug:AdvanceAnimation()
        end)
    end
end


function Debug:GetDisplayProgressInfo(liveData)
    local cfg = ensureConfig()
    if not (cfg.enabled and cfg.preview == "DEBUG") then
        return liveData
    end
    if not self:IsDebugNeighborhood(liveData and liveData.id) then
        return liveData
    end

    local id = tostring(liveData and liveData.id)
    local entry = self:GetNeighborhoodConfig(id)
    local percent = tonumber(entry.progress) or 0
    local data = {
        id = id,
        name = self:GetResolvedNeighborhoodName(id) or (liveData and liveData.name) or id,
        percent = percent,
        currentProgress = percent,
        maxProgress = 100,
        debugMode = true,
        debugGlowAlpha = percent >= 100 and 0.34 or 0,
    }

    return data
end

function Debug:GetDropdownNeighborhoods()
    if not self:IsEnabled() then return {} end
    return {
        { text = DEBUG_FULL_NAME, value = DEBUG_FULL_ID, debug = true },
        { text = DEBUG_TEST_NAME, value = DEBUG_TEST_ID, debug = true },
    }
end

function Debug:GetCharacterKeys()
    if not self:IsEnabled() then return {} end
    return { DEBUG_CHAR_KEY }
end

function Debug:GetSelectedKeyFallback()
    return DEBUG_CHAR_KEY
end

function Debug:GetDisplayCharacterName(key)
    if tostring(key) == DEBUG_CHAR_KEY then return "Debug Tester - DebugRealm" end
    return tostring(key or "None")
end

function Debug:GetEffectiveNeighborhood(charKey)
    if not self:IsEnabled() then return nil end
    if tostring(charKey) ~= DEBUG_CHAR_KEY then return nil end
    return self:GetActiveNeighborhoodOverride() or DEBUG_FULL_ID
end
