import SwiftUI
import AppKit

struct CustomTextView: NSViewRepresentable {
    @Binding var text: String
    var onReturn: ((Int) -> Void)?
    var onBackspaceAtStart: (() -> Void)?
    var isEditable: Bool = true
    var font: NSFont = .systemFont(ofSize: NSFont.systemFontSize)
    var minHeight: CGFloat = 35
    var autoScrollToBottom: Bool = false
    
    class Coordinator: NSObject, NSTextViewDelegate {
        var parent: CustomTextView
        
        init(parent: CustomTextView) {
            self.parent = parent
        }
        
        func textDidChange(_ notification: Notification) {
            guard let textView = notification.object as? NSTextView else { return }
            parent.text = textView.string
        }
        
        func textView(_ textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
            if commandSelector == #selector(NSStandardKeyBindingResponding.insertNewline(_:)) {
                if let onReturn = parent.onReturn {
                    onReturn(textView.selectedRange().location)
                    return true
                }
            }
            
            if commandSelector == #selector(NSStandardKeyBindingResponding.deleteBackward(_:)) {
                if textView.selectedRange().location == 0,
                   let onBackspaceAtStart = parent.onBackspaceAtStart {
                    onBackspaceAtStart()
                    return true
                }
            }
            
            return false
        }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }
    
    func makeNSView(context: Context) -> NSScrollView {
        let scrollView = NSScrollView()
        let textView = NSTextView()
        
        textView.delegate = context.coordinator
        textView.isEditable = isEditable
        textView.isSelectable = true
        textView.isRichText = false
        textView.font = font
        
        textView.minSize = NSSize(width: 0, height: 0)
        textView.maxSize = NSSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
        textView.isVerticallyResizable = true
        textView.isHorizontallyResizable = false
        
        if let container = textView.textContainer {
            container.widthTracksTextView = true
            container.heightTracksTextView = false
            container.size = NSSize(width: 0, height: CGFloat.greatestFiniteMagnitude)
        }
        
        textView.string = text
        textView.textContainerInset = NSSize(width: 5, height: 5)
        
        scrollView.documentView = textView
        scrollView.hasVerticalScroller = true
        scrollView.hasHorizontalScroller = false
        scrollView.autohidesScrollers = true
        
        scrollView.borderType = .noBorder
        scrollView.drawsBackground = false
        scrollView.horizontalScrollElasticity = .none
        
        return scrollView
    }
    
    func updateNSView(_ scrollView: NSScrollView, context: Context) {
        guard let textView = scrollView.documentView as? NSTextView else { return }
        if textView.string != text {
            let selectedRanges = textView.selectedRanges
            textView.string = text
            textView.selectedRanges = selectedRanges
            
            if autoScrollToBottom {
                textView.scrollToEndOfDocument(nil)
            }
        }
        
        textView.frame.size.width = scrollView.contentSize.width
    }
}
