import SwiftUI
import AppKit
import SwiftData

/// Eén actie in de Opdrachtenbalk (command palette).
struct OpdrachtAction: Identifiable {
    let id = UUID()
    let titel: String
    let ondertitel: String
    let systeemIcoon: String
    /// Zoektermen (lowercased) waarop deze actie matcht, naast de titel.
    let trefwoorden: [String]
    /// Wordt op de main actor uitgevoerd wanneer de gebruiker de actie kiest.
    let uitvoeren: () -> Void
}

/// Raycast/Linear-achtige opdrachtenbalk: glas-paneel met zoekveld en
/// gefilterde actielijst, bediening via pijltjestoetsen + Enter, Esc sluit.
struct OpdrachtenbalkView: View {
    /// Sluit het venster (Esc of na uitvoeren van een actie).
    let sluiten: () -> Void
    /// Alle beschikbare acties (statisch opgebouwd door de window manager).
    let acties: [OpdrachtAction]

    @State private var zoekTekst: String = ""
    @State private var geselecteerdeIndex: Int = 0
    @FocusState private var zoekVeldFocus: Bool

    private var gefilterd: [OpdrachtAction] {
        let term = zoekTekst.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
        guard !term.isEmpty else { return acties }
        return acties.filter { actie in
            if actie.titel.lowercased().contains(term) { return true }
            if actie.ondertitel.lowercased().contains(term) { return true }
            return actie.trefwoorden.contains { $0.contains(term) }
        }
    }

    var body: some View {
        VStack(spacing: 0) {
            zoekBalk
            Divider()
                .overlay(Color.proatBorder)
            actieLijst
        }
        .frame(width: 560)
        .frame(maxHeight: 420)
        .background(ProatGlassBackground())
        .background(Color.proatBgRaised.opacity(0.55))
        .clipShape(RoundedRectangle(cornerRadius: ProatRadius.sheet, style: .continuous))
        .overlay(
            RoundedRectangle(cornerRadius: ProatRadius.sheet, style: .continuous)
                .stroke(Color.proatBorder, lineWidth: 1)
        )
        .proatShadowFloat()
        .onChange(of: zoekTekst) { _, _ in
            geselecteerdeIndex = 0
        }
        .onAppear {
            DispatchQueue.main.async {
                zoekVeldFocus = true
            }
        }
        .background(
            // Onzichtbare toetsafhandeling voor pijltjes / Enter / Esc.
            ToetsAfhandeling(
                omhoog: selecteerVorige,
                omlaag: selecteerVolgende,
                bevestig: voerGeselecteerdeUit,
                annuleer: sluiten
            )
        )
    }

    // MARK: - Subviews

    private var zoekBalk: some View {
        HStack(spacing: ProatSpacing.s) {
            Image(systemName: "magnifyingglass")
                .font(.system(size: 15, weight: .medium))
                .foregroundColor(.proatText3)

            TextField("Typ een opdracht of zoekterm…", text: $zoekTekst)
                .textFieldStyle(.plain)
                .font(ProatFont.sectie)
                .foregroundColor(.proatText1)
                .focused($zoekVeldFocus)
                .onSubmit(voerGeselecteerdeUit)

            Text("esc")
                .font(ProatFont.klein)
                .foregroundColor(.proatText3)
                .padding(.horizontal, 6)
                .padding(.vertical, 2)
                .background(Color.proatBgSunken)
                .clipShape(RoundedRectangle(cornerRadius: 4, style: .continuous))
        }
        .padding(.horizontal, ProatSpacing.m)
        .padding(.vertical, ProatSpacing.s)
    }

    private var actieLijst: some View {
        ScrollViewReader { proxy in
            ScrollView {
                LazyVStack(spacing: 2) {
                    if gefilterd.isEmpty {
                        Text("Geen opdrachten gevonden")
                            .font(ProatFont.body)
                            .foregroundColor(.proatText3)
                            .frame(maxWidth: .infinity, alignment: .center)
                            .padding(.vertical, ProatSpacing.l)
                    } else {
                        ForEach(Array(gefilterd.enumerated()), id: \.element.id) { index, actie in
                            OpdrachtRij(
                                actie: actie,
                                geselecteerd: index == geselecteerdeIndex
                            )
                            .id(index)
                            .contentShape(Rectangle())
                            .onTapGesture {
                                geselecteerdeIndex = index
                                voerGeselecteerdeUit()
                            }
                            .onHover { hovering in
                                if hovering { geselecteerdeIndex = index }
                            }
                        }
                    }
                }
                .padding(.horizontal, ProatSpacing.xs)
                .padding(.vertical, ProatSpacing.xs)
            }
            .onChange(of: geselecteerdeIndex) { _, nieuw in
                withAnimation(.easeOut(duration: 0.12)) {
                    proxy.scrollTo(nieuw, anchor: .center)
                }
            }
        }
    }

    // MARK: - Navigatie

    private func selecteerVorige() {
        guard !gefilterd.isEmpty else { return }
        geselecteerdeIndex = max(0, geselecteerdeIndex - 1)
    }

    private func selecteerVolgende() {
        guard !gefilterd.isEmpty else { return }
        geselecteerdeIndex = min(gefilterd.count - 1, geselecteerdeIndex + 1)
    }

    private func voerGeselecteerdeUit() {
        let lijst = gefilterd
        guard !lijst.isEmpty, geselecteerdeIndex >= 0, geselecteerdeIndex < lijst.count else { return }
        let actie = lijst[geselecteerdeIndex]
        sluiten()
        // Na sluiten uitvoeren zodat navigatie het hoofdvenster naar voren brengt.
        DispatchQueue.main.async {
            actie.uitvoeren()
        }
    }
}

/// Eén rij in de actielijst — icoon + titel + ondertitel, teal-highlight bij selectie.
private struct OpdrachtRij: View {
    let actie: OpdrachtAction
    let geselecteerd: Bool

    var body: some View {
        HStack(spacing: ProatSpacing.s) {
            Image(systemName: actie.systeemIcoon)
                .font(.system(size: 15, weight: .medium))
                .foregroundColor(geselecteerd ? .proatTeal : .proatText2)
                .frame(width: 22, height: 22)

            VStack(alignment: .leading, spacing: 1) {
                Text(actie.titel)
                    .font(ProatFont.body)
                    .foregroundColor(.proatText1)
                Text(actie.ondertitel)
                    .font(ProatFont.klein)
                    .foregroundColor(.proatText3)
            }

            Spacer(minLength: 0)

            if geselecteerd {
                Image(systemName: "return")
                    .font(.system(size: 12, weight: .semibold))
                    .foregroundColor(.proatTeal)
            }
        }
        .padding(.horizontal, ProatSpacing.s)
        .padding(.vertical, ProatSpacing.xs)
        .background(
            RoundedRectangle(cornerRadius: ProatRadius.knop, style: .continuous)
                .fill(geselecteerd ? Color.proatTealTint : Color.clear)
        )
    }
}

/// Onzichtbare NSView die pijl-omhoog/omlaag, Enter en Esc afvangt.
private struct ToetsAfhandeling: NSViewRepresentable {
    let omhoog: () -> Void
    let omlaag: () -> Void
    let bevestig: () -> Void
    let annuleer: () -> Void

    func makeNSView(context: Context) -> ToetsView {
        let v = ToetsView()
        v.omhoog = omhoog
        v.omlaag = omlaag
        v.bevestig = bevestig
        v.annuleer = annuleer
        return v
    }

    func updateNSView(_ v: ToetsView, context: Context) {
        v.omhoog = omhoog
        v.omlaag = omlaag
        v.bevestig = bevestig
        v.annuleer = annuleer
    }

    final class ToetsView: NSView {
        var omhoog: (() -> Void)?
        var omlaag: (() -> Void)?
        var bevestig: (() -> Void)?
        var annuleer: (() -> Void)?

        override var acceptsFirstResponder: Bool { true }

        override func keyDown(with event: NSEvent) {
            switch event.keyCode {
            case 126: // pijl omhoog
                omhoog?()
            case 125: // pijl omlaag
                omlaag?()
            case 36, 76: // Return / Enter
                bevestig?()
            case 53: // Esc
                annuleer?()
            default:
                super.keyDown(with: event)
            }
        }
    }
}
