import SwiftUI
import AppKit

/// Works around a macOS 26 Liquid Glass quirk: the window's unified-toolbar material
/// stops compositing after the window is occluded (covered by another window) or the
/// app goes idle, leaving the toolbar a flat fill — showing the BuildBanner color flat
/// beneath it — until a manual window resize forces it to re-render. `.toolbarBackground`
/// guarantees the toolbar *has* a material, but can't keep that material from going
/// dormant.
///
/// We can't observe the dropout directly, but it's reliably cured by a relayout (the
/// resize the user reaches for). So on the events that trigger it — the window being
/// revealed, the app reactivating — we reproduce that relayout by nudging the window
/// frame a pixel and immediately back. The two `setFrame` calls coalesce within one
/// runloop pass, so there's no visible jump, but the toolbar re-composites its glass.
struct ToolbarGlassKeeper: NSViewRepresentable {
    func makeNSView(context: Context) -> NSView {
        let view = NSView(frame: .zero)
        let coordinator = context.coordinator
        // The host view isn't in a window yet during `makeNSView`; the MainActor hop
        // lets `view.window` resolve first (same pattern as `SidebarColumnConfigurator`).
        Task { @MainActor in coordinator.attach(to: view.window) }
        return view
    }

    func updateNSView(_ nsView: NSView, context: Context) {
        let coordinator = context.coordinator
        Task { @MainActor in coordinator.attach(to: nsView.window) }
    }

    func makeCoordinator() -> Coordinator { Coordinator() }

    @MainActor
    final class Coordinator {
        private weak var window: NSWindow?
        private var observers: [NSObjectProtocol] = []

        /// Idempotent: registers once for the window's reveal / app-reactivation events.
        func attach(to window: NSWindow?) {
            guard observers.isEmpty, let window else { return }
            self.window = window
            let center = NotificationCenter.default
            observers = [
                // Fully-occluded → visible again: the material commonly drops while
                // hidden and doesn't resume on reveal.
                center.addObserver(
                    forName: NSWindow.didChangeOcclusionStateNotification,
                    object: window, queue: .main
                ) { [weak self] _ in MainActor.assumeIsolated { self?.repairIfVisible() } },
                // Reactivating the app after it sat in the background is the other
                // common trigger.
                center.addObserver(
                    forName: NSApplication.didBecomeActiveNotification,
                    object: nil, queue: .main
                ) { [weak self] _ in MainActor.assumeIsolated { self?.repairIfVisible() } },
            ]
        }

        private func repairIfVisible() {
            guard let window, window.occlusionState.contains(.visible) else { return }
            let frame = window.frame
            guard frame.height > 2 else { return }
            // Shrink by a pixel (anchored at the top edge — AppKit's origin is
            // bottom-left, so raise the origin as height drops) then restore. Shrinking
            // rather than growing avoids fighting the screen's bottom/top bounds.
            var nudged = frame
            nudged.size.height -= 1
            nudged.origin.y += 1
            window.setFrame(nudged, display: false)
            window.setFrame(frame, display: true)
        }
        // No deinit-time observer removal: this coordinator lives for the window's
        // session (same as `SidebarColumnController`'s resize observer), and the blocks
        // capture `self` weakly, so a stale registration is harmless.
    }
}
