import SwiftUI
import AppKit

/// Owns the AppKit sidebar split-view item behind `NavigationSplitView` so the
/// column only opens or closes on an explicit toggle — never on its own when the
/// window resizes.
///
/// On macOS, `NavigationSplitView` auto-collapses its sidebar whenever the window
/// narrows past the point where the sidebar and detail minimum widths both fit,
/// then re-expands it on widening. With our wide detail (chat / project views)
/// that threshold sits near the 900pt window minimum, so ordinary resizes flip
/// the column open and shut. Setting `canCollapse = false` removes AppKit's
/// automatic (and divider-drag) collapsing; we still collapse/expand on demand by
/// driving `isCollapsed` directly, which is honoured regardless of `canCollapse`.
@MainActor
final class SidebarColumnController {
    private weak var item: NSSplitViewItem?
    private var resizeObserver: NSObjectProtocol?

    /// Adopt the sidebar item once SwiftUI has built the split view, and pin it
    /// open against window-driven collapsing. Re-asserted on every window resize
    /// in case SwiftUI re-enables collapsing during a layout pass.
    func adopt(_ item: NSSplitViewItem, in window: NSWindow?) {
        self.item = item
        lockCollapse()
        guard resizeObserver == nil, let window else { return }
        resizeObserver = NotificationCenter.default.addObserver(
            forName: NSWindow.didResizeNotification, object: window, queue: .main
        ) { [weak self] _ in
            MainActor.assumeIsolated { self?.lockCollapse() }
        }
    }

    private func lockCollapse() {
        guard let item, item.canCollapse else { return }
        item.canCollapse = false
    }

    var hasItem: Bool { item != nil }

    /// Collapse or expand the sidebar in response to the toolbar button. Driving
    /// `isCollapsed` directly works even though `canCollapse` is false — that flag
    /// only governs automatic and user-divider collapsing, not programmatic intent.
    func toggle() {
        guard let item else { return }
        item.animator().isCollapsed.toggle()
    }
}

/// Locates the `NSSplitView` backing the enclosing `NavigationSplitView` and hands
/// its sidebar item to `controller`. Rendered invisibly in the sidebar background.
struct SidebarColumnConfigurator: NSViewRepresentable {
    let controller: SidebarColumnController

    func makeNSView(context: Context) -> NSView {
        let view = NSView(frame: .zero)
        Task { @MainActor in configure(from: view) }
        return view
    }

    func updateNSView(_ nsView: NSView, context: Context) {
        Task { @MainActor in configure(from: nsView) }
    }

    @MainActor
    private func configure(from view: NSView) {
        guard let splitView = enclosingSplitView(of: view),
              let splitController = splitView.delegate as? NSSplitViewController,
              let sidebar = splitController.splitViewItems.first
        else { return }
        controller.adopt(sidebar, in: view.window)
    }

    private func enclosingSplitView(of view: NSView) -> NSSplitView? {
        var current: NSView? = view.superview
        while let candidate = current {
            if let split = candidate as? NSSplitView { return split }
            current = candidate.superview
        }
        return nil
    }
}
