-- Frame Setup
local AnnounceFrame = CreateFrame("Frame")
AnnounceFrame:RegisterEvent("CURRENCY_DISPLAY_UPDATE")
AnnounceFrame:RegisterEvent("CHAT_MSG_ADDON")
AnnounceFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")

-- Constants
local ANNOUNCEMENT_PREFIX = "BlackBoxCrate"
local HONOR_CURRENCY_ID = 1602

local zoneMapIDs = {
    ["Azj%-Kahet"]          = 2255,
    ["Siren Isle"]          = 2369,
    ["Isle of Dorn"]        = 2248,
    ["Ringing Deeps"]       = 2214,
    ["The Ringing Deeps"]   = 2214,
    ["Hallowfall"]          = 2215,
    ["Undermine"]           = 2346,
}

local zoneNameRemap = {
    ["City of Threads"]         = "Azj-Kahet",
    ["City of Threads - Lower"] = "Azj-Kahet",
    ["Slam Central Station"]    = "Undermine"
}

local zoneCoordinates = {
    ["Azj-Kahet"] = {64.17, 74.72},
    ["Siren Isle"] = {39.49, 52.34},
    ["Isle of Dorn"] = {60.60, 66.57},
    ["The Ringing Deeps"] = {54.10, 64.31},
    ["Hallowfall"] = {40.72, 34.58},
    ["Undermine"] = {37.90, 50.56},
}

local knownCrateZoneIDs = {
    [2255] = true,
    [2369] = true,
    [2248] = true,
    [2214] = true,
    [2215] = true,
    [2346] = true,
}

-- State
local hasAnnounced = {}
local currentMapID = nil

-- Register Addon Prefix
C_ChatInfo.RegisterAddonMessagePrefix(ANNOUNCEMENT_PREFIX)

-- Utilities
local function GetZoneInfo()
    local mapID = C_Map.GetBestMapForUnit("player")
    if not mapID then return 0, "Unknown Zone", 0, 0 end
    local pos = C_Map.GetPlayerMapPosition(mapID, "player")
    if not pos then return mapID, "Unknown Zone", 0, 0 end
    local info = C_Map.GetMapInfo(mapID)
    local zoneName = info and info.name or "Unknown Zone"
    zoneName = zoneNameRemap[zoneName] or zoneName
    return mapID, zoneName, pos.x * 100, pos.y * 100
end

local function SendCrateAnnouncement(zoneName, x, y)
    local msg = string.format("War Supply Chest opened in %s (%.1f,%.1f)", zoneName, x, y)
    local channel = IsInRaid() and "RAID" or "PARTY"
    if IsInGroup() or IsInRaid() then
        if C_ChatInfo.IsAddonMessagePrefixRegistered(ANNOUNCEMENT_PREFIX) then
            C_ChatInfo.SendAddonMessage(ANNOUNCEMENT_PREFIX, zoneName, channel)
        end
        SendChatMessage(msg, channel)
    end
end

_G.PrintFirstZoneWaypoints = function()
    local isLeader = UnitIsGroupLeader("player") or not IsInGroup()
    local timers

    if isLeader then
        local GetTopSortedTimers = _G.GetTopSortedTimers
        if not GetTopSortedTimers then
            print("Ticker data function not available.")
            return
        end
        timers = GetTopSortedTimers()
    else
        timers = {}
        if not syncedTimerData or #syncedTimerData == 0 then
            print("No synced timer data available.")
            return
        end
        local elapsed = GetTime() - (syncTimestamp or 0)
        local seenZones = {}
        for _, timer in ipairs(syncedTimerData) do
            local zone = timer.zone or "Unknown"
            zone = zoneNameRemap[zone] or zone
            if not seenZones[zone] and zoneCoordinates[zone] then
                table.insert(timers, {
                    zoneName = zone,
                    shardID = timer.shardID,
                    remainingSeconds = (timer.remaining - elapsed) % 1097
                })
                seenZones[zone] = true
            end
            if #timers >= 6 then break end
        end
    end

    if not timers or #timers == 0 then
        print("No timer data available.")
        return
    end

    table.sort(timers, function(a, b)
        local aTime = a.remainingSeconds or a.remaining or a.duration or 0
        local bTime = b.remainingSeconds or b.remaining or b.duration or 0
        return aTime < bTime
    end)

    local first = timers[1]
    if not first then
        print("No valid zones in timer list.")
        return
    end

    local zone = zoneNameRemap[first.zoneName or first.zone or "Unknown"] or first.zoneName or first.zone or "Unknown"
    local coords = zoneCoordinates[zone]
    if coords then
        if not BlackBoxDB.settings or BlackBoxDB.settings.throttleCratePrint ~= false then
            print(string.format("Wait Here: %s: (%.2f,%.2f)", zone, coords[1], coords[2]))
        end
            else
        print(zone .. ": (0.0, 0.0)")
    end
end



local function ClearTomTomWaypoints()
    C_Timer.After(1, function()
        if TomTom and TomTom.db and TomTom.db.profile and TomTom.db.profile.general and TomTom.db.profile.general.confirmremoveall then
            --print("Auto-accepting TomTom remove all confirmation.")
            StaticPopupDialogs["TOMTOM_REMOVE_ALL_CONFIRM"].OnAccept()
        elseif StaticPopupDialogs and StaticPopupDialogs["TOMTOM_REMOVE_ALL_CONFIRM"] then
            --print("Auto-accepting TomTom remove all confirmation (fallback).")
            StaticPopupDialogs["TOMTOM_REMOVE_ALL_CONFIRM"].OnAccept()
        else
            print("TomTom or its confirmation dialog is not available.")
        end
        if C_Map and C_Map.ClearUserWaypoint then
            C_Map.ClearUserWaypoint()
            print("Blizzard map pins cleared.")
        else
            print("C_Map.ClearUserWaypoint is not available.")
        end
        C_Timer.After(1, _G.PrintFirstZoneWaypoints)
    end)
end

-- Event Handler
AnnounceFrame:SetScript("OnEvent", function(_, event, arg1, arg2)
    if event == "CURRENCY_DISPLAY_UPDATE" then
        local currencyID = arg1
        if currencyID ~= HONOR_CURRENCY_ID then return end
        local mapID, zoneName, x, y = GetZoneInfo()
        if knownCrateZoneIDs[mapID] and not hasAnnounced[mapID] then
            SendCrateAnnouncement(zoneName, x, y)
            hasAnnounced[mapID] = true
            ClearTomTomWaypoints()
        end
    elseif event == "CHAT_MSG_ADDON" then
        local prefix, zoneName = arg1, arg2
        if prefix == ANNOUNCEMENT_PREFIX then
            for pattern, id in pairs(zoneMapIDs) do
                if zoneName:match(pattern) then
                    hasAnnounced[id] = true
                    break
                end
            end
        end
    elseif event == "ZONE_CHANGED_NEW_AREA" then
        local mapID = C_Map.GetBestMapForUnit("player")
        if currentMapID and currentMapID ~= mapID then
            hasAnnounced[currentMapID] = nil
        end
        currentMapID = mapID
    end
end)