
local Details = _G.Details
local DF = _G.DetailsFramework
local detailsFramework = _G.DetailsFramework
local addonName, Details222 = ...
local _

local time = time
local C_Timer = _G.C_Timer
local unpack = _G.unpack
local GetTime = _G.GetTime

local GetInstanceInfo = _G.GetInstanceInfo

local Loc = _G.LibStub("AceLocale-3.0"):GetLocale("Details")

--data for the current mythic + dungeon
Details.MythicPlus = {
    RunID = 0,
}

local mythicDungeonFrames = Details222.MythicPlus.Frames
local mythicDungeonCharts = Details:CreateEventListener()
Details222.MythicPlus.Charts.Listener = mythicDungeonCharts

-- ~mythic ~dungeon
local DetailsMythicPlusFrame = _G.CreateFrame("frame", "DetailsMythicPlusFrame", UIParent)
DetailsMythicPlusFrame.DevelopmentDebug = false

--disabling the mythic+ feature if the user is playing in wow classic
if (not DF.IsTimewalkWoW()) then
    DetailsMythicPlusFrame:RegisterEvent("CHALLENGE_MODE_START")
    DetailsMythicPlusFrame:RegisterEvent("CHALLENGE_MODE_COMPLETED")
    DetailsMythicPlusFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
    DetailsMythicPlusFrame:RegisterEvent("ENCOUNTER_END")
    DetailsMythicPlusFrame:RegisterEvent("START_TIMER")
end

function Details222.MythicPlus.LogStep(log)
    local today = date("%d/%m/%y %H:%M:%S")
    table.insert(Details.mythic_plus_log, 1, today .. "|" .. log)
    tremove(Details.mythic_plus_log, 50)
end

function DetailsMythicPlusFrame.BossDefeated(this_is_end_end, encounterID, encounterName, difficultyID, raidSize, endStatus) --hold your breath and count to ten
    --this function is called right after defeat a boss inside a mythic dungeon
    --it comes from details! control leave combat
    if (DetailsMythicPlusFrame.DevelopmentDebug) then
        print("Details!", "BossDefeated() > boss defeated | SegmentID:", Details.MythicPlus.SegmentID, " | mapID:", Details.MythicPlus.DungeonID)
    end

    --local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo()
    Details222.MythicPlus.OnBossDefeated(encounterID, encounterName) --data capture

    --increase the segment number for the mythic run
    Details.MythicPlus.SegmentID = Details.MythicPlus.SegmentID + 1

    --register the time when the last boss has been killed (started a clean up for the next trash)
    Details.MythicPlus.PreviousBossKilledAt = time()

    --update the saved table inside the profile
    Details:UpdateState_CurrentMythicDungeonRun(true, Details.MythicPlus.SegmentID, Details.MythicPlus.PreviousBossKilledAt)
end

--this function is called 2 seconds after the event COMBAT_MYTHICDUNGEON_END
function DetailsMythicPlusFrame.MythicDungeonFinished(bFromZoneLeft)
    if (DetailsMythicPlusFrame.IsDoingMythicDungeon) then
        if (DetailsMythicPlusFrame.DevelopmentDebug) then
            print("Details!", "MythicDungeonFinished() > the dungeon was a Mythic+ and just ended.")
        end

        DetailsMythicPlusFrame.IsDoingMythicDungeon = false
        Details.MythicPlus.Started = false
        Details.MythicPlus.EndedAt = time()-1.9

        Details:UpdateState_CurrentMythicDungeonRun()

        --at this point, details! should not be in combat, but if something triggered a combat start, just close the combat right away
        if (Details.in_combat) then
            if (DetailsMythicPlusFrame.DevelopmentDebug) then
                print("Details!", "MythicDungeonFinished() > was in combat, calling SairDoCombate():", InCombatLockdown())
            end
            Details:SairDoCombate()
            Details222.MythicPlus.LogStep("MythicDungeonFinished() | Details was in combat.")
        end

        --check if there is trash segments after the last boss. need to merge these segments with the trash segment of the last boss
        local bCanMergeBossTrash = Details.mythic_plus.merge_boss_trash
        Details222.MythicPlus.LogStep("MythicDungeonFinished() | merge_boss_trash = " .. (bCanMergeBossTrash and "true" or "false"))

        --check if there's trash after the last boss, if does, merge it with the trash of the last boss defeated
        if (bCanMergeBossTrash and not Details.MythicPlus.IsRestoredState) then -- and not bFromZoneLeft
            --is the current combat not a boss fight?
            --this mean a combat was opened after the last boss of the dungeon was killed
            if (not Details.tabela_vigente.is_boss and Details.tabela_vigente:GetCombatTime() > 5) then
                if (DetailsMythicPlusFrame.DevelopmentDebug) then
                    print("Details!", "MythicDungeonFinished() > the last combat isn't a boss fight, might have trash after bosses done.")
                end
                Details222.MythicPlus.MergeTrashAfterLastBoss()
            end
        end

        --merge segments
        if (not Details.MythicPlus.IsRestoredState) then -- and not bFromZoneLeft
            if (DetailsMythicPlusFrame.DevelopmentDebug) then
                print("Details!", "MythicDungeonFinished() > not in combat, creating overall segment now")
            end
            DetailsMythicPlusFrame.MergeSegmentsOnEnd()
        end


        --assuming `Details222.MythicPlus.ElapsedTime` is only available at the end of the run, so if is nil, the run did not finished
        if detailsFramework.IsAddonApocalypseWow() and Details222.MythicPlus.ElapsedTime then
            --
        end


        Details.MythicPlus.IsRestoredState = nil

		--the run is valid, schedule to open the chart window
		Details.mythic_plus.delay_to_show_graphic = 1
        if (not bFromZoneLeft) then
		    C_Timer.After(Details.mythic_plus.delay_to_show_graphic, mythicDungeonFrames.ShowEndOfMythicPlusPanel)
        end

        --shutdown parser for a few seconds to avoid opening new segments after the run ends
        if (not bFromZoneLeft) then
            Details:CaptureSet(false, "damage", false, 15)
            Details:CaptureSet(false, "energy", false, 15)
            Details:CaptureSet(false, "aura", false, 15)
            Details:CaptureSet(false, "energy", false, 15)
            Details:CaptureSet(false, "spellcast", false, 15)
        end

        if detailsFramework.IsAddonApocalypseWow() then
            --delete all other segments of this run except the overall
            local runId = Details.mythic_dungeon_id
            local allSegments = Details:GetCombatSegments()
            for segmentId = #allSegments, 1, -1 do
                local thisSegment = allSegments[segmentId]
                if (thisSegment.is_mythic_dungeon and thisSegment.is_mythic_dungeon.RunID == runId and not thisSegment.is_mythic_dungeon.OverallSegment) then
                    Details:RemoveSegment(segmentId)
                end
            end
        end
    end
end

function DetailsMythicPlusFrame.MythicDungeonStarted()
    --flag as a mythic dungeon
    DetailsMythicPlusFrame.IsDoingMythicDungeon = true

    --this counter is individual for each character
    Details.mythic_dungeon_id = Details.mythic_dungeon_id + 1

    local mythicLevel = C_ChallengeMode.GetActiveKeystoneInfo and C_ChallengeMode.GetActiveKeystoneInfo()
    local zoneName, _, _, _, _, _, _, currentZoneID = GetInstanceInfo()

    local mapID = C_Map.GetBestMapForUnit("player")

    if (not mapID) then
        return
    end

    local ejID = Details:GetInstanceEJID(mapID)

    --setup the mythic run info
    Details.MythicPlus.Started = true
    Details.MythicPlus.DungeonName = zoneName
    Details.MythicPlus.DungeonID = currentZoneID

    --Details:Msg("(debug) mythic dungeon start time: ", time()+9.7, "time now:", time(), "diff:", time()+9.7-time())

    Details.MythicPlus.StartedAt = time()+9.7 --there's the countdown timer of 10 seconds
    Details.MythicPlus.EndedAt = nil --reset
    Details.MythicPlus.SegmentID = 1
    Details.MythicPlus.Level = mythicLevel
    Details.MythicPlus.ejID = ejID
    Details.MythicPlus.PreviousBossKilledAt = time()

    Details:SaveState_CurrentMythicDungeonRun(Details.mythic_dungeon_id, zoneName, currentZoneID, time()+9.7, 1, mythicLevel, ejID, time())

    local name, groupType, difficultyID, difficult = GetInstanceInfo()
    if (groupType == "party" and Details.overall_clear_newchallenge) then
        Details.historico:ResetOverallData()
        Details:Msg("the overall data has been reset.") --localize-me

        if (Details.debug) then
            Details:Msg("(debug) timer is for a mythic+ dungeon, overall has been reseted.")
        end
    end

    if (DetailsMythicPlusFrame.DevelopmentDebug) then
        print("Details!", "MythicDungeonStarted() > State set to Mythic Dungeon, new combat starting in 10 seconds.")
    end
end

function DetailsMythicPlusFrame.OnChallengeModeStart()
    --is this a mythic dungeon?
    local _, _, difficultyID, _, _, _, _, currentZoneID = GetInstanceInfo()

    if (difficultyID == 8) then
        --start the dungeon on Details!
        DetailsMythicPlusFrame.MythicDungeonStarted()
        Details222.MythicPlus.LogStep("OnChallengeModeStart()")
    else
        --print("D! mythic dungeon was already started!")
        --from zone changed
        local mythicLevel = C_ChallengeMode.GetActiveKeystoneInfo and C_ChallengeMode.GetActiveKeystoneInfo()
        local zoneName, _, _, _, _, _, _, currentZoneID = GetInstanceInfo()

        if (not Details.MythicPlus.Started and Details.MythicPlus.DungeonID == currentZoneID and Details.MythicPlus.Level == mythicLevel) then
            Details.MythicPlus.Started = true
            Details.MythicPlus.EndedAt = nil
            Details.mythic_dungeon_currentsaved.started = true
            DetailsMythicPlusFrame.IsDoingMythicDungeon = true
            --print("D! mythic dungeon was NOT already started! debug 2")
        end
    end
end

--make an event listener to sync combat data
DetailsMythicPlusFrame.EventListener = Details:CreateEventListener()
DetailsMythicPlusFrame.EventListener:RegisterEvent("COMBAT_ENCOUNTER_START")
DetailsMythicPlusFrame.EventListener:RegisterEvent("COMBAT_ENCOUNTER_END")
DetailsMythicPlusFrame.EventListener:RegisterEvent("COMBAT_PLAYER_ENTER")
DetailsMythicPlusFrame.EventListener:RegisterEvent("COMBAT_PLAYER_LEAVE")
DetailsMythicPlusFrame.EventListener:RegisterEvent("COMBAT_MYTHICDUNGEON_START")
DetailsMythicPlusFrame.EventListener:RegisterEvent("COMBAT_MYTHICDUNGEON_END")
DetailsMythicPlusFrame.EventListener:RegisterEvent("COMBAT_MYTHICPLUS_OVERALL_READY")

function DetailsMythicPlusFrame.EventListener.OnDetailsEvent(contextObject, event, ...)
    --these events triggers within Details control functions, they run exactly after details! creates or close a segment
    if (event == "COMBAT_PLAYER_ENTER") then


    elseif (event == "COMBAT_PLAYER_LEAVE") then
        --ignore the event if ignoring mythic dungeon special treatment
        if (Details.streamer_config.disable_mythic_dungeon) then
            return
        end

        if (DetailsMythicPlusFrame.IsDoingMythicDungeon) then
            local combatObject = ...

            if (combatObject.is_boss) then
                if (not combatObject.is_boss.killed) then
                    local encounterName = combatObject.is_boss.encounter
                    local zoneName = combatObject.is_boss.zone
                    local mythicLevel = C_ChallengeMode.GetActiveKeystoneInfo and C_ChallengeMode.GetActiveKeystoneInfo()

                    local currentCombat = Details:GetCurrentCombat()

                    --just in case the combat get tagged as boss fight
                    combatObject.is_boss = nil

                    --tag the combat as mythic dungeon trash
                    local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo()

                    ---@type mythicdungeoninfo
                    local mythicPlusInfo = {
                        ZoneName = Details.MythicPlus.DungeonName or zoneName,
                        MapID = Details.MythicPlus.DungeonID or instanceMapID,
                        Level = Details.MythicPlus.Level,
                        EJID = Details.MythicPlus.ejID,
                        RunID = Details.mythic_dungeon_id,
                        StartedAt = time() - currentCombat:GetCombatTime(),
                        EndedAt = time(),
                        SegmentID = Details.MythicPlus.SegmentID, --segment number within the dungeon
                        OverallSegment = false,
                        SegmentType = DETAILS_SEGMENTTYPE_MYTHICDUNGEON_BOSSWIPE,
                        SegmentName = (encounterName or Loc["STRING_UNKNOW"]) .. " (" .. string.lower(_G["BOSS"]) .. ")"
                    }

                    combatObject.is_mythic_dungeon = mythicPlusInfo

                    Details222.MythicPlus.LogStep("COMBAT_PLAYER_LEAVE | wiped on boss | key level: | " .. mythicLevel .. " | " .. (encounterName or "") .. " " .. zoneName)
                else
                    DetailsMythicPlusFrame.BossDefeated(false, combatObject.is_boss.id, combatObject.is_boss.name, combatObject.is_boss.diff, 5, 1)
                end
            end

        end

    elseif (event == "COMBAT_ENCOUNTER_START") then
        --ignore the event if ignoring mythic dungeon special treatment
        if (Details.streamer_config.disable_mythic_dungeon) then
            Details222.MythicPlus.LogStep("COMBAT_ENCOUNTER_START | streamer_config.disable_mythic_dungeon is true and the code cannot continue.")
            return
        end

        local encounterID, encounterName, difficultyID, raidSize, endStatus = ...
        --nothing

    elseif (event == "COMBAT_ENCOUNTER_END") then
        --ignore the event if ignoring mythic dungeon special treatment
        if (Details.streamer_config.disable_mythic_dungeon) then
            Details222.MythicPlus.LogStep("COMBAT_ENCOUNTER_END | streamer_config.disable_mythic_dungeon is true and the code cannot continue.")
            return
        end

        local encounterID, encounterName, difficultyID, raidSize, endStatus = ...
        --nothing

    elseif (event == "COMBAT_MYTHICDUNGEON_START") then
        local lowerInstance = Details:GetLowerInstanceNumber()
        if (lowerInstance) then
            lowerInstance = Details:GetInstance(lowerInstance)
            if (lowerInstance) then
                C_Timer.After(3, function()
                    --if (lowerInstance:IsEnabled()) then
                        --todo, need localization
                        --lowerInstance:InstanceAlert("Details!" .. " " .. "Damage" .. " " .. "Meter", {[[Interface\AddOns\Details\images\minimap]], 16, 16, false}, 3, {function() end}, false, true)
                    --end
                end)
            end
        end

        --ignore the event if ignoring mythic dungeon special treatment
        if (Details.streamer_config.disable_mythic_dungeon) then
            return
        end

        --reset spec cache if broadcaster requested
        if (Details.streamer_config.reset_spec_cache) then
            Details:Destroy(Details.cached_specs)
        end

        C_Timer.After(0.25, DetailsMythicPlusFrame.OnChallengeModeStart)

        --debugging
        local mPlusSettings = Details.mythic_plus
        local result = ""
        for key, value in pairs(Details.mythic_plus) do
			if (type(value) ~= "table") then
				result = result .. key .. " = " .. tostring(value) .. " | "
			end
		end

        local mythicLevel = C_ChallengeMode.GetActiveKeystoneInfo and C_ChallengeMode.GetActiveKeystoneInfo()
        local zoneName, _, _, _, _, _, _, currentZoneID = GetInstanceInfo()
		Details222.MythicPlus.LogStep("COMBAT_MYTHICDUNGEON_START | settings: " .. result .. " | level: " .. mythicLevel .. " | zone: " .. zoneName .. " | zoneId: " .. currentZoneID)

    elseif (event == "COMBAT_MYTHICDUNGEON_END") then
        --ignore the event if ignoring mythic dungeon special treatment
        if (Details.streamer_config.disable_mythic_dungeon) then
            Details222.MythicPlus.LogStep("COMBAT_MYTHICDUNGEON_END | streamer_config.disable_mythic_dungeon is true and the code cannot continue.")
            return
        end

        --delay to wait the encounter_end trigger first
        --assuming here the party cleaned the mobs kill objective before going to kill the last boss
        C_Timer.After(2, DetailsMythicPlusFrame.MythicDungeonFinished)

    elseif (event == "COMBAT_MYTHICPLUS_OVERALL_READY") then
        DetailsMythicPlusFrame.SaveMythicPlusStats(...)

        C_Timer.After(1, function()
            local okay, errorText = pcall(function()
                local recentPlayers = Details:GetRecentPlayers()
                local recentType = "mplus"

                --create a list of character names in the friends list, so we don't add character that already in the friends list
                local friendsCharacters = {}
                local BnetFriends = BNGetNumFriends()
                for i = 1, BnetFriends do
                    local bNetFriend = C_BattleNet.GetFriendAccountInfo(i)
                    if (bNetFriend) then
                        local gameAccountInfo = bNetFriend.gameAccountInfo
                        if (gameAccountInfo) then
                            local isOnline = gameAccountInfo.isOnline
                            local characterName = gameAccountInfo.characterName
                            if (isOnline and characterName and string.len(characterName) >= 2) then
                                friendsCharacters[gameAccountInfo.characterName] = true
                            end
                        end
                    end
                end

                for i = 1, GetNumGroupMembers() - 1 do
                    local unitId = "party" .. i
                    local playerName = UnitName(unitId)

                    if (playerName and not friendsCharacters[playerName] and not C_FriendList.GetFriendInfo(playerName)) then
                        local classId = select(3, UnitClass(unitId)) or 0
                        local specId = Details.cached_specs[UnitGUID(unitId)] or 0
                        local timeWhen = time()
                        local challengeMapId = Details222.MythicPlus.MapID or 0
                        local mapId = Details222.MythicPlus.InstanceMapID or 0
                        local level = Details222.MythicPlus.Level
                        local onTime = Details222.MythicPlus.OnTime

                        --check if the player is already in the recent players table
                        local found = false
                        for j = 1, #recentPlayers do
                            local thisTable = recentPlayers[j]
                            if (thisTable[3] == playerName) then
                                table.remove(recentPlayers, j)
                                table.insert(recentPlayers, 1, thisTable)
                                thisTable[7] = thisTable[7] + 1 --increment the played together amount
                                found = true
                                break
                            end
                        end

                        local runId = 0
                        if (DetailsMythicPlus) then
                            runId = DetailsMythicPlus.GetLatestRunId() or 0
                        end

                        if (not found) then
                            recentPlayers[#recentPlayers + 1] = {recentType, timeWhen, playerName, classId, specId, mapId, 1, challengeMapId, level, onTime, runId}
                        end
                    end
                end
            end) --pcall end

            if (not okay) then
                Details:Msg("add recent friend resulted in an error:", errorText)
            end
        end) --c_timer end
    end
end

local playerLeftDungeonZoneTimer_Callback = function()
    if (DetailsMythicPlusFrame.IsDoingMythicDungeon) then
        local _, _, difficulty, _, _, _, _, currentZoneID = GetInstanceInfo()
        if (currentZoneID ~= Details.MythicPlus.DungeonID) then
            Details222.MythicPlus.LogStep("ZONE_CHANGED_NEW_AREA | player has left the dungeon and Details! finished the dungeon because of that.")

            --send mythic dungeon end event
            Details:SendEvent("COMBAT_MYTHICDUNGEON_END") --on leave dungeon

            --finish the segment
            DetailsMythicPlusFrame.BossDefeated(true)

            --finish the mythic run
            DetailsMythicPlusFrame.MythicDungeonFinished(true)

            DetailsMythicPlusFrame.ZoneLeftTimer = nil
        end
    end
end

function Details:GetRecentPlayers()
    return Details.recent_players
end

---usage: local recentType, timeWhen, playerName, classId, specId, mapId, param1, param2, param3, param4 = Details:UnpackRecentPlayerTable(recentPlayerTable)
---@param recentPlayerTable table
---@return string recentType
---@return number timeWhen
---@return string playerName
---@return number classId
---@return number specId
---@return number mapId
---@return number playedTogetherAmount --amount of times the player played with this player
---@return number param1 --for mplus this is challengeMapId
---@return number param2 --for mplus this is level
---@return boolean param3 --for mplus this is onTime
---@return number param4 --for mplus this is runId
function Details:UnpackRecentPlayerTable(recentPlayerTable)
    local from = recentPlayerTable[1] --string, e.g. "mplus"
    local when = recentPlayerTable[2] --time()
    local playerName = recentPlayerTable[3] --string
    local classId = recentPlayerTable[4] --number
    local specId = recentPlayerTable[5] --number
    local mapId = recentPlayerTable[6] --number
    local playedTogetherAmount = recentPlayerTable[7] --number

    local challengeMapId = recentPlayerTable[8] --number
    local level = recentPlayerTable[9] --number
    local onTime = recentPlayerTable[10] --boolean
    local runId = recentPlayerTable[11] --number

    return from, when, playerName, classId, specId, mapId, playedTogetherAmount, challengeMapId, level, onTime, runId
end

DetailsMythicPlusFrame:SetScript("OnEvent", function(_, event, ...)
    if (event == "START_TIMER") then
        --DetailsMythicPlusFrame.LastTimer = GetTime()

    elseif (event == "ZONE_CHANGED_NEW_AREA") then
        if (DetailsMythicPlusFrame.IsDoingMythicDungeon) then
            if (DetailsMythicPlusFrame.DevelopmentDebug) then
                print("Details!", event, ...)
                print("Zone changed and is Doing Mythic Dungeon")
            end

            --ignore the event if ignoring mythic dungeon special treatment
            if (Details.streamer_config.disable_mythic_dungeon) then
                Details222.MythicPlus.LogStep("ZONE_CHANGED_NEW_AREA | streamer_config.disable_mythic_dungeon is true and the code cannot continue.")
                return
            end

            local _, _, difficulty, _, _, _, _, currentZoneID = GetInstanceInfo()
            if (currentZoneID ~= Details.MythicPlus.DungeonID) then
                if (DetailsMythicPlusFrame.DevelopmentDebug) then
                    print("Zone changed and the zone is different than the dungeon")
                end

                --player left the dungeon zone, start a timer to check if the player will return to the dungeon
                if (DetailsMythicPlusFrame.DevelopmentDebug) then
                    print("Details!", "ZONE_CHANGED_NEW_AREA | player left the dungeon zone, return to dungeon timer started.")
                end

                --check if the timer already exists, if does, ignore this event
                if (DetailsMythicPlusFrame.ZoneLeftTimer and not DetailsMythicPlusFrame.ZoneLeftTimer:IsCancelled()) then
                    return
                end

                DetailsMythicPlusFrame.ZoneLeftTimer = C_Timer.NewTimer(40, playerLeftDungeonZoneTimer_Callback)
            end
        end
    end
end)

---@param combatObject combat
function DetailsMythicPlusFrame.SaveMythicPlusStats(combatObject)
    local completionInfo = C_ChallengeMode.GetChallengeCompletionInfo()
    local mapChallengeModeID = C_ChallengeMode.GetActiveChallengeMapID()
    local PrimaryAffix = 0
    local upgradeMembers = completionInfo.members
    local mythicLevel = completionInfo.level
    local time = completionInfo.time
    local onTime = completionInfo.onTime
    local keystoneUpgradeLevels = completionInfo.keystoneUpgradeLevels
    local practiceRun = completionInfo.practiceRun
    local isAffixRecord = completionInfo.isAffixRecord
    local isMapRecord = completionInfo.isMapRecord
    local isEligibleForScore = completionInfo.isEligibleForScore
    local oldDungeonScore = completionInfo.oldOverallDungeonScore
    local newDungeonScore = completionInfo.newOverallDungeonScore

    if (mapChallengeModeID) then
        local statName = "mythicdungeoncompletedDF2"

        ---@type table<challengemapid, table>
        local mythicDungeonRuns = Details222.PlayerStats:GetStat(statName)
        if (not mythicDungeonRuns) then
            mythicDungeonRuns = mythicDungeonRuns or {}
        end

        --mythicDungeonRuns [mapChallengeModeID] [mythicLevel]

        ---@class mythicplusrunstats
        ---@field onTime boolean
        ---@field deaths number
        ---@field date number
        ---@field affix number
        ---@field runTime milliseconds
        ---@field combatTime number

        ---@class mythicplusstats
        ---@field completed number
        ---@field totalTime number
        ---@field minTime number
        ---@field history mythicplusrunstats[]

        ---@type table<keylevel, mythicplusstats>
        local statsForDungeon = mythicDungeonRuns[mapChallengeModeID]
        if (not statsForDungeon) then
            statsForDungeon = {}
            mythicDungeonRuns[mapChallengeModeID] = statsForDungeon
        end

        ---@type mythicplusstats
        local statsForLevel = statsForDungeon[mythicLevel]
        if (not statsForLevel) then
            ---@type mythicplusstats
            statsForLevel = {
                completed = 0,
                totalTime = 0,
                minTime = 0,
                history = {},
            }
            statsForDungeon[mythicLevel] = statsForLevel
        end

        statsForLevel.completed = (statsForLevel.completed or 0) + 1
        statsForLevel.totalTime = (statsForLevel.totalTime or 0) + time
        if (not statsForLevel.minTime or time < statsForLevel.minTime) then
            statsForLevel.minTime = time
        end

        statsForLevel.history = statsForLevel.history or {}

        local amountDeaths = C_ChallengeMode.GetDeathCount and C_ChallengeMode.GetDeathCount() or 0

        ---@type mythicplusrunstats
        local runStats = {
            date = _G.time(),
            runTime = math.floor(time/1000),
            onTime = onTime,
            deaths = amountDeaths,
            affix = PrimaryAffix,
            combatTime = combatObject:GetCombatTime(),
            playerNames = {},
        }

        local damagerContainer = combatObject:GetContainer(DETAILS_ATTRIBUTE_DAMAGE)
        if (damagerContainer) then
            for _, playerObject in damagerContainer:ListActors() do
                if (playerObject:IsPlayer()) then
                    table.insert(runStats.playerNames, playerObject.nome)
                end
            end
        end

        table.insert(statsForLevel.history, runStats)

        Details222.PlayerStats:SetStat("mythicdungeoncompletedDF2", mythicDungeonRuns)
    end
end

--[=[
    1x ...ns/Details/functions/mythicdungeon/mythicdungeon.lua:117: attempt to perform arithmetic on field 'ElapsedTime' (a nil value)
    [Details/functions/mythicdungeon/mythicdungeon.lua]:117: in function <...ns/Details/functions/mythicdungeon/mythicdungeon.lua:114>
]=]