local addonName, ZL = ...

function ZL:GetCurrentZoneID()
    local mapID = C_Map.GetBestMapForUnit("player")
    if not mapID then return nil end

    -- Some submaps are floors; use the nearest route, catalog, or linked
    -- instance map instead of losing the instance context.
    local candidate = mapID
    while candidate do
        if self:GetRoutePosition(candidate) or self.Catalog[candidate] or self.InstanceParents[candidate] or
            self:IsHubMap(candidate) then return candidate end
        local info = C_Map.GetMapInfo(candidate)
        candidate = info and info.parentMapID
    end
    return mapID
end

function ZL:IsZoneComplete(mapID)
    if ZL_Saved.completedZones and ZL_Saved.completedZones[mapID] then return true end
    local data = self.ZoneData[mapID]
    if not data or not data.eligible or not data.catalogComplete then return false end
    local done, total = self:GetProgress(data)
    return total == 0 or done == total
end

function ZL:IsCategoryEnabled(key)
    return ZL_Saved.settings.categories[key] ~= false
end

function ZL:GetCategoryProgress(category)
    if not category then return 0, 0 end
    if category.summary then return category.done or 0, category.total or 0 end
    if category.key ~= "instances" then return category.done or 0, category.total or 0 end

    local done, total = 0, 0
    for _, instance in ipairs(category.instances or {}) do
        for _, childCategory in ipairs(instance.categories or {}) do
            if self:IsCategoryEnabled(childCategory.key) then
                done = done + (childCategory.done or 0)
                total = total + (childCategory.total or 0)
            end
        end
    end
    return done, total
end

function ZL:GetProgress(data)
    local done, total = 0, 0
    for _, category in ipairs(data and data.categories or {}) do
        if self:IsCategoryEnabled(category.key) then
            local categoryDone, categoryTotal = self:GetCategoryProgress(category)
            done = done + categoryDone
            total = total + categoryTotal
        end
    end
    return done, total
end

function ZL:GetUnlockedIndex()
    local route = ZL_Saved.route or {}
    if #route == 0 then return 0 end

    local unlocked = 1
    while unlocked < #route and self:IsZoneComplete(route[unlocked]) do
        unlocked = unlocked + 1
    end
    return unlocked
end

function ZL:GetNextZone()
    local route = ZL_Saved.route or {}
    local unlocked = self:GetUnlockedIndex()
    return unlocked > 0 and route[unlocked + 1] or nil
end

function ZL:GetActiveZone()
    return (ZL_Saved.route or {})[self:GetUnlockedIndex()]
end

function ZL:IsZoneLocked(mapID)
    local position = self:GetRoutePosition(mapID)
    return position and position > self:GetUnlockedIndex() or false
end

function ZL:RegisterSlashCommands()
    SLASH_ZONELOCKED1 = "/zonelocked"
    SLASH_ZONELOCKED2 = "/zl"
    SlashCmdList.ZONELOCKED = function(input)
        local normalized = (input or ""):lower():match("^%s*(.-)%s*$")
        local command, argument = normalized:match("^(%S*)%s*(.-)$")
        if command == "add" then
            local ok, message = self:AddCurrentZoneToRoute()
            self:Print(message)
            if ok then self:RefreshUI() end
        elseif command == "start" then
            if #(ZL_Saved.route or {}) > 0 then
                self:Print("A journey is already in progress.")
                return
            end
            local continentID, expansionKey
            if argument ~= "" then
                for _, continent in ipairs(self:GetSelectableContinents()) do
                    if continent.name:lower() == argument then
                        continentID, expansionKey = continent.continentID, continent.expansionKey
                        break
                    end
                end
            else
                continentID, expansionKey = self:GetMapContinentID(self:GetCurrentZoneID())
            end
            if continentID and self:IsExpansionEnabled(expansionKey) then
                self:StartZoneRoll(continentID, expansionKey)
            else
                if self.UI then self.UI:Show(); self:RefreshUI() end
                self:Print("Choose an enabled continent in the tracker to roll your starting zone.")
            end
        elseif command == "blackout" then
            ZL_Saved.settings.blackout = not ZL_Saved.settings.blackout
            self:CheckZoneState()
            self:Print("Locked-zone blackout " .. (ZL_Saved.settings.blackout and "enabled." or "disabled."))
        elseif command == "mini" or command == "minilist" then
            ZL_Saved.settings.minilist.enabled = not ZL_Saved.settings.minilist.enabled
            self:RefreshMiniList()
            if self.UI then self:UpdateToolbar() end
            self:Print("Mini-List " .. (ZL_Saved.settings.minilist.enabled and "enabled." or "disabled."))
        elseif command == "settings" or command == "options" then
            self:OpenSettings()
        elseif command == "history" then
            self.selectedMapID = nil
            self.showHistory = true
            self.UI:Show()
            self.UI.scroll:SetVerticalScroll(0)
            self._uiSignature = nil
            self:RefreshUI()
        elseif command == "status" then
            local mapID = self:GetCurrentZoneID()
            local contextMapID = mapID and self:GetRouteContextZone(mapID)
            local data = contextMapID and self.ZoneData[contextMapID]
            local done, total = self:GetProgress(data)
            self:Print(data and string.format("%s: %d%% (%d/%d)", data.name,
                total > 0 and math.floor((done / total) * 100 + 0.5) or 100, done, total) or "Current zone is not tracked.")
        elseif command == "roll" then
            self:StartZoneRoll()
        elseif command == "next" then
            local activeID = ZL_Saved.route[self:GetUnlockedIndex()]
            self:Print(activeID and (self:GetZoneDefinition(activeID).name .. " is the current unlocked progression zone.") or "No route is configured.")
        elseif command == "" or command == "show" then
            self:ToggleUI()
        else
            self:Print("Commands: /zl, /zl start, /zl add, /zl status, /zl next, /zl roll, /zl mini, /zl history, /zl blackout, /zl settings")
        end
    end
end
