import SwiftUI
import AppKit

/// A clickable field that records a keyboard shortcut when focused.
/// Click it, press a key combination, and it saves the binding.
struct HotkeyRecorderView: View {
    let label: String
    @Binding var binding: HotkeyBinding

    @State private var isRecording = false

    var body: some View {
        HStack {
            Text(label)
                .frame(width: 140, alignment: .leading)

            HotkeyRecorderField(binding: $binding, isRecording: $isRecording)
                .frame(width: 120, height: 24)
                .background(
                    RoundedRectangle(cornerRadius: 6)
                        .fill(isRecording ? Color.accentColor.opacity(0.15) : Color.secondary.opacity(0.1))
                )
                .overlay(
                    RoundedRectangle(cornerRadius: 6)
                        .stroke(isRecording ? Color.accentColor : Color.secondary.opacity(0.3), lineWidth: 1)
                )
        }
    }
}

struct OptionalHotkeyRecorderView: View {
    let label: String
    @Binding var binding: HotkeyBinding?

    @State private var isRecording = false

    var body: some View {
        HStack {
            Text(label)
                .frame(width: 140, alignment: .leading)

            OptionalHotkeyRecorderField(binding: $binding, isRecording: $isRecording)
                .frame(width: 120, height: 24)
                .background(
                    RoundedRectangle(cornerRadius: 6)
                        .fill(isRecording ? Color.accentColor.opacity(0.15) : Color.secondary.opacity(0.1))
                )
                .overlay(
                    RoundedRectangle(cornerRadius: 6)
                        .stroke(isRecording ? Color.accentColor : Color.secondary.opacity(0.3), lineWidth: 1)
                )

            Button("Clear") {
                binding = nil
            }
            .disabled(binding == nil)
        }
    }
}

/// NSViewRepresentable that captures key events when focused.
struct HotkeyRecorderField: NSViewRepresentable {
    @Binding var binding: HotkeyBinding
    @Binding var isRecording: Bool

    func makeNSView(context: Context) -> HotkeyNSView {
        let view = HotkeyNSView()
        view.onKeyRecorded = { newBinding in
            binding = newBinding
            isRecording = false
        }
        view.onFocusChanged = { focused in
            isRecording = focused
        }
        return view
    }

    func updateNSView(_ nsView: HotkeyNSView, context: Context) {
        nsView.update(currentLabel: binding.displayString, isRecording: isRecording)
    }
}

struct OptionalHotkeyRecorderField: NSViewRepresentable {
    @Binding var binding: HotkeyBinding?
    @Binding var isRecording: Bool

    func makeNSView(context: Context) -> HotkeyNSView {
        let view = HotkeyNSView()
        view.onKeyRecorded = { newBinding in
            binding = newBinding
            isRecording = false
        }
        view.onFocusChanged = { focused in
            isRecording = focused
        }
        return view
    }

    func updateNSView(_ nsView: HotkeyNSView, context: Context) {
        nsView.update(currentLabel: binding?.displayString ?? "Not set", isRecording: isRecording)
    }
}

/// The actual NSView that handles key capture.
class HotkeyNSView: NSView {
    var currentLabel: String = ""
    var showRecording: Bool = false
    var onKeyRecorded: ((HotkeyBinding) -> Void)?
    var onFocusChanged: ((Bool) -> Void)?

    private let label: NSTextField = {
        let field = NSTextField(labelWithString: "")
        field.alignment = .center
        field.font = NSFont.monospacedSystemFont(ofSize: 12, weight: .medium)
        field.translatesAutoresizingMaskIntoConstraints = false
        field.backgroundColor = .clear
        field.isBezeled = false
        field.lineBreakMode = .byTruncatingTail
        return field
    }()

    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        setupLabel()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupLabel()
    }

    override var acceptsFirstResponder: Bool { true }

    override func layout() {
        super.layout()
        updateLabelAppearance()
    }

    override func mouseDown(with event: NSEvent) {
        window?.makeFirstResponder(self)
    }

    override func becomeFirstResponder() -> Bool {
        onFocusChanged?(true)
        return true
    }

    override func resignFirstResponder() -> Bool {
        onFocusChanged?(false)
        return true
    }

    override func keyDown(with event: NSEvent) {
        guard showRecording else {
            super.keyDown(with: event)
            return
        }

        let relevantFlags: NSEvent.ModifierFlags = [.command, .shift, .control, .option]
        let masked = event.modifierFlags.intersection(.deviceIndependentFlagsMask).intersection(relevantFlags)

        // Require at least one modifier key
        guard !masked.isEmpty else { return }

        let binding = HotkeyBinding(modifiers: masked.rawValue, keyCode: event.keyCode)
        onKeyRecorded?(binding)

        // Resign first responder after recording
        window?.makeFirstResponder(nil)
    }

    private func setupLabel() {
        addSubview(label)
        NSLayoutConstraint.activate([
            label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 6),
            label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -6),
            label.centerYAnchor.constraint(equalTo: centerYAnchor)
        ])
        updateLabelAppearance()
    }

    func update(currentLabel: String, isRecording: Bool) {
        self.currentLabel = currentLabel
        showRecording = isRecording
        updateLabelAppearance()
    }

    private func updateLabelAppearance() {
        label.stringValue = showRecording ? "Press keys..." : currentLabel
        label.textColor = showRecording ? .controlAccentColor : .labelColor
    }
}
