import AppKit

extension StatusItemController {
    func prepareForAppShutdown() {
        guard !self.hasPreparedForAppShutdown else { return }
        self.hasPreparedForAppShutdown = true
        #if DEBUG
        self.isReleasedForTesting = true
        #endif

        let openMenus = Array(self.openMenus.values)
        for menu in openMenus {
            menu.cancelTrackingWithoutAnimation()
            self.forgetClosedMenu(menu)
        }

        self.cancelShutdownTasks()
        self.clearShutdownMenuState()
        self.removeShutdownStatusItems()
        self.creditsPurchaseWindow?.close()
        self.creditsPurchaseWindow = nil
    }

    private func cancelShutdownTasks() {
        self.agentSessions.stop()
        self.blinkTask?.cancel()
        self.blinkTask = nil
        self.menuBarCountdownRefreshTask?.cancel()
        self.menuBarCountdownRefreshTask = nil
        self.loginTask?.cancel()
        self.loginTask = nil
        for task in self.manualRefreshTasks.values {
            task.cancel()
        }
        self.manualRefreshTasks.removeAll()
        self.store.cancelForcedRefreshEnrichment()
        self.store.cancelRequiredRefresh()
        self.menuCardRefreshMonitor.resetManualRefresh()
        self.screenChangeVisibilityTask?.cancel()
        self.screenChangeVisibilityTask = nil
        self.pendingScreenChangePreviousCount = nil
        self.animationDriver?.stop()
        self.animationDriver = nil
        self.animationPhase = 0
        self.blinkForceUntil = nil
        self.blinkStates.removeAll(keepingCapacity: false)
        self.blinkAmounts.removeAll(keepingCapacity: false)
        self.wiggleAmounts.removeAll(keepingCapacity: false)
        self.tiltAmounts.removeAll(keepingCapacity: false)
        self.quotaWarningFlashUntil.removeAll(keepingCapacity: false)
        for task in self.quotaWarningFlashTasks.values {
            task.cancel()
        }
        self.quotaWarningFlashTasks.removeAll(keepingCapacity: false)

        for task in self.menuRefreshTasks.values {
            task.cancel()
        }
        self.cancelAllClosedMenuRebuilds()
        for task in self.openMenuRebuildTasks.values {
            task.cancel()
        }
        self.openMenuInvalidationRetryTask?.cancel()
        self.openMenuInvalidationRetryTask = nil
        self.codexAccountMenuProjectionRevalidationTask?.cancel()
        self.codexAccountMenuProjectionRevalidationTask = nil
        self.providerSelectionUIRefreshTask?.cancel()
        self.providerSelectionUIRefreshTask = nil
        self.deferredMergedIconRenderAfterTracking = false
        self.providerSwitcherPointerInteractionMenuID = nil
        self.pendingProviderSwitcherPointerRebuild = nil
    }

    private func clearShutdownMenuState() {
        self.removeProviderSwitcherShortcutMonitor()
        self.menuRefreshTasks.removeAll(keepingCapacity: false)
        self.closedMenuRebuildTasks.removeAll(keepingCapacity: false)
        self.closedMenuRebuildRequests.cancelAll()
        self.openMenuRebuildTasks.removeAll(keepingCapacity: false)
        self.openMenuRebuildRequests.cancelAll()
        self.openMenuRebuildsClosingHostedSubviewMenus.removeAll(keepingCapacity: false)
        self.menuSession.clearMenuTracking()
        self.manualRefreshViewportRestoreState.deferredUntilRebuild.removeAll(keepingCapacity: false)
        self.manualRefreshViewportRestoreState.stopAllMovementTracking()
        self.openMenus.removeAll(keepingCapacity: false)
        self.highlightedMenuItems.removeAll(keepingCapacity: false)
        self.nativeHighlightDeferredMenuRebuilds.removeAll(keepingCapacity: false)
        self.pendingMenuBaselineResyncs.removeAll(keepingCapacity: false)
        self.menuCardHeightCache.removeAll(keepingCapacity: false)
        self.measuredStandardMenuWidthCache.removeAll(keepingCapacity: false)
        self.mergedSwitcherContentCaches.removeAll(keepingCapacity: false)
        self.menuProviders.removeAll(keepingCapacity: false)
        self.menuReadinessSignatures.removeAll(keepingCapacity: false)
        self.menuIdentitySignatures.removeAll(keepingCapacity: false)
        self.providerMenus.removeAll(keepingCapacity: false)
        self.mergedMenu = nil
        self.fallbackMenu = nil
    }

    private func removeShutdownStatusItems() {
        self.statusItem.menu = nil
        self.statusBar.removeStatusItem(self.statusItem)

        for item in self.statusItems.values {
            item.menu = nil
            self.statusBar.removeStatusItem(item)
        }
        self.statusItems.removeAll(keepingCapacity: false)
        self.lastAppliedProviderIconRenderSignatures.removeAll(keepingCapacity: false)
    }

    #if DEBUG
    func releaseStatusItemsForTesting() {
        self.prepareForAppShutdown()
    }
    #endif
}
