import SwiftUI
import AppKit
import SwiftData

/// Borderless, zwevend NSPanel dat de Opdrachtenbalk host.
///
/// Spiegelt de levenscyclus van `MiniWindowManager` / `MiniRecorderPanel`:
/// een `NSPanel` subclass met een `NSWindowController`, centraal op het
/// hoofdscherm, met `orderFrontRegardless()`. Verschil: dit paneel moét
/// key kunnen worden (tekstinvoer + toetsnavigatie), dus `canBecomeKey` is
/// `true` en bij blur (resignKey) sluit het paneel.
@MainActor
final class OpdrachtenbalkWindowManager {
    static let shared = OpdrachtenbalkWindowManager()

    private var panel: OpdrachtenbalkPanel?
    private var windowController: NSWindowController?
    private(set) var isVisible = false

    /// ModelContainer voor acties die data nodig hebben (laatste transcriptie kopiëren).
    private weak var modelContainer: ModelContainer?

    private init() {}

    /// Eénmalig configureren vanuit de app-init, zodat data-acties werken.
    func configure(modelContainer: ModelContainer) {
        self.modelContainer = modelContainer
    }

    func toggle() {
        isVisible ? hide() : show()
    }

    func show() {
        if isVisible { return }
        if panel == nil { initializeWindow() }
        isVisible = true
        panel?.show()
        // Activeer de app zodat het paneel key wordt en het zoekveld focus krijgt.
        NSApplication.shared.activate(ignoringOtherApps: true)
        panel?.makeKeyAndOrderFront(nil)
    }

    func hide() {
        guard isVisible else { return }
        isVisible = false
        panel?.orderOut(nil)
    }

    // MARK: - Window lifecycle (gespiegeld op MiniWindowManager)

    private func initializeWindow() {
        deinitializeWindow()
        let metrics = OpdrachtenbalkPanel.calculateWindowMetrics()
        let newPanel = OpdrachtenbalkPanel(contentRect: metrics)
        newPanel.onResignKey = { [weak self] in
            self?.hide()
        }

        let view = OpdrachtenbalkView(
            sluiten: { [weak self] in self?.hide() },
            acties: Self.bouwActies(modelContainer: modelContainer)
        )
        let hostingController = NSHostingController(rootView: view)
        newPanel.contentView = hostingController.view

        panel = newPanel
        windowController = NSWindowController(window: newPanel)
        newPanel.orderFrontRegardless()
    }

    private func deinitializeWindow() {
        panel?.orderOut(nil)
        windowController?.close()
        windowController = nil
        panel = nil
    }

    // MARK: - Acties

    private static func bouwActies(modelContainer: ModelContainer?) -> [OpdrachtAction] {
        func navigeer(_ destination: String) {
            // Breng het hoofdvenster naar voren en navigeer (zelfde patroon als MenuBarManager).
            NSApplication.shared.setActivationPolicy(.regular)
            _ = WindowManager.shared.showMainWindow()
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                NotificationCenter.default.post(
                    name: .navigateToDestination,
                    object: nil,
                    userInfo: ["destination": destination]
                )
            }
        }

        var acties: [OpdrachtAction] = [
            OpdrachtAction(
                titel: "Naar Start",
                ondertitel: "Open het dashboard",
                systeemIcoon: "house",
                trefwoorden: ["start", "dashboard", "home", "begin"],
                uitvoeren: {
                    // ContentView heeft geen "Dashboard"-route; toon hoofdvenster.
                    NSApplication.shared.setActivationPolicy(.regular)
                    _ = WindowManager.shared.showMainWindow()
                }
            ),
            OpdrachtAction(
                titel: "Naar Historie",
                ondertitel: "Bekijk je transcripties",
                systeemIcoon: "clock.arrow.circlepath",
                trefwoorden: ["historie", "geschiedenis", "history", "transcripties"],
                uitvoeren: { navigeer("History") }
            ),
            OpdrachtAction(
                titel: "Naar Verfijning",
                ondertitel: "AI-verfijning en woordenboek",
                systeemIcoon: "wand.and.stars",
                trefwoorden: ["verfijning", "enhancement", "ai", "prompt"],
                uitvoeren: { navigeer("Enhancement") }
            ),
            OpdrachtAction(
                titel: "Naar Stem & model",
                ondertitel: "Modelbeheer en audio-ingang",
                systeemIcoon: "waveform",
                trefwoorden: ["stem", "model", "modellen", "audio", "ingang"],
                uitvoeren: { navigeer("AI Models") }
            ),
            OpdrachtAction(
                titel: "Naar Instellingen",
                ondertitel: "App-instellingen",
                systeemIcoon: "gearshape",
                trefwoorden: ["instellingen", "settings", "voorkeuren"],
                uitvoeren: { navigeer("Settings") }
            ),
            OpdrachtAction(
                titel: "Woord toevoegen aan woordenboek",
                ondertitel: "Open Verfijning om een woord toe te voegen",
                systeemIcoon: "text.book.closed",
                trefwoorden: ["woord", "woordenboek", "dictionary", "toevoegen"],
                uitvoeren: { navigeer("Enhancement") }
            ),
            OpdrachtAction(
                titel: "AI-prompt bewerken",
                ondertitel: "Open Verfijning om de prompt aan te passen",
                systeemIcoon: "square.and.pencil",
                trefwoorden: ["prompt", "ai", "bewerken", "verfijning"],
                uitvoeren: { navigeer("Enhancement") }
            )
        ]

        // "Laatste transcriptie kopiëren" — hergebruikt LastTranscriptionService.
        if let container = modelContainer {
            acties.insert(
                OpdrachtAction(
                    titel: "Laatste transcriptie kopiëren",
                    ondertitel: "Kopieer de meest recente transcriptie",
                    systeemIcoon: "doc.on.clipboard",
                    trefwoorden: ["kopieer", "kopiëren", "transcriptie", "laatste", "klembord"],
                    uitvoeren: {
                        LastTranscriptionService.copyLastTranscription(from: container.mainContext)
                    }
                ),
                at: 5
            )
        }

        return acties
    }
}

/// Borderless zwevend paneel — gespiegeld op `MiniRecorderPanel`, maar
/// key-capable zodat tekstinvoer en toetsnavigatie werken.
final class OpdrachtenbalkPanel: NSPanel {
    override var canBecomeKey: Bool { true }
    override var canBecomeMain: Bool { false }

    /// Sluit-callback wanneer het paneel focus verliest (klik buiten paneel).
    var onResignKey: (() -> Void)?

    init(contentRect: NSRect) {
        super.init(
            contentRect: contentRect,
            styleMask: [.nonactivatingPanel, .fullSizeContentView, .titled],
            backing: .buffered,
            defer: false
        )
        configurePanel()
    }

    private func configurePanel() {
        isFloatingPanel = true
        level = .floating
        hidesOnDeactivate = false
        collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary]
        isMovable = false
        backgroundColor = .clear
        isOpaque = false
        hasShadow = false
        titlebarAppearsTransparent = true
        titleVisibility = .hidden
        standardWindowButton(.closeButton)?.isHidden = true
        standardWindowButton(.miniaturizeButton)?.isHidden = true
        standardWindowButton(.zoomButton)?.isHidden = true
        isReleasedWhenClosed = false
    }

    static func calculateWindowMetrics() -> NSRect {
        let width: CGFloat = 560
        let height: CGFloat = 420
        guard let screen = NSScreen.main else {
            return NSRect(x: 0, y: 0, width: width, height: height)
        }
        let visibleFrame = screen.visibleFrame
        let xPosition = visibleFrame.midX - (width / 2)
        // Iets boven het midden — Raycast/Spotlight-positie.
        let yPosition = visibleFrame.midY - (height / 2) + (visibleFrame.height * 0.12)
        return NSRect(x: xPosition, y: yPosition, width: width, height: height)
    }

    func show() {
        let metrics = OpdrachtenbalkPanel.calculateWindowMetrics()
        setFrame(metrics, display: true)
        orderFrontRegardless()
    }

    override func resignKey() {
        super.resignKey()
        onResignKey?()
    }

    // Esc moet ook werken als het zoekveld de first responder is.
    override func cancelOperation(_ sender: Any?) {
        onResignKey?()
    }
}
