import SwiftUI
import Foundation
import OSLog

private let syntaxHighlightSignposter = OSSignposter(subsystem: "h3p.Neon-Vision-Editor", category: "SyntaxHighlight")

#if os(macOS)
private extension Notification.Name {
    static let editorPointerInteraction = Notification.Name("NeonEditorPointerInteraction")
}
#endif

private enum EditorRuntimeLimits {
    // Above this, keep editing responsive by skipping regex-heavy syntax passes.
    static let syntaxMinimalUTF16Length = 1_200_000
    static let ultraLargeResponsiveSyntaxUTF16Length = 400_000
    static let htmlFastProfileUTF16Length = 250_000
    static let csvFastProfileUTF16Length = 120_000
    static let jsonFastProfileUTF16Length = 120_000
    static let largeFileJSONVisiblePaddingUTF16 = 2_400
    static let largeFileJSONIncrementalPaddingUTF16 = 800
    static let largeFileJSONTokenBudgetSeconds = 0.0035
    static let csvFastProfileLongLineUTF16 = 4_000
    static let csvFastProfileScanLimitUTF16 = 120_000
    static let scopeComputationMaxUTF16Length = 300_000
    static let cursorRehighlightMaxUTF16Length = 220_000
    static let nonImmediateHighlightMaxUTF16Length = 220_000
    static let bindingDebounceUTF16Length = 250_000
    static let bindingDebounceDelay: TimeInterval = 0.18
}

private func shouldUseCSVFastProfile(_ nsText: NSString) -> Bool {
    if nsText.length >= EditorRuntimeLimits.csvFastProfileUTF16Length {
        return true
    }
    let scanLimit = min(nsText.length, EditorRuntimeLimits.csvFastProfileScanLimitUTF16)
    guard scanLimit > 0 else { return false }
    var currentLineLength = 0
    for idx in 0..<scanLimit {
        let codeUnit = nsText.character(at: idx)
        if codeUnit == 10 { // '\n'
            currentLineLength = 0
            continue
        }
        currentLineLength += 1
        if currentLineLength >= EditorRuntimeLimits.csvFastProfileLongLineUTF16 {
            return true
        }
    }
    return false
}

private func isJSONLikeLanguage(_ language: String) -> Bool {
    switch language.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() {
    case "json", "jsonc", "json5", "ipynb":
        return true
    default:
        return false
    }
}

private func syntaxProfile(for language: String, text: NSString) -> SyntaxPatternProfile {
    let lower = language.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
    if lower == "html" && text.length >= EditorRuntimeLimits.htmlFastProfileUTF16Length {
        return .htmlFast
    }
    if lower == "csv" && shouldUseCSVFastProfile(text) {
        return .csvFast
    }
    if isJSONLikeLanguage(lower) && text.length >= EditorRuntimeLimits.jsonFastProfileUTF16Length {
        return .jsonFast
    }
    return .full
}

private enum SyntaxFontEmphasis {
    case keyword
    case comment
}

#if os(macOS)
private func fontWithSymbolicTrait(_ font: NSFont, trait: NSFontDescriptor.SymbolicTraits) -> NSFont {
    let descriptor = font.fontDescriptor.withSymbolicTraits(font.fontDescriptor.symbolicTraits.union(trait))
    guard
          let adjustedFont = NSFont(descriptor: descriptor, size: font.pointSize) else {
        return font
    }
    return adjustedFont
}
#else
private func fontWithSymbolicTrait(_ font: UIFont, trait: UIFontDescriptor.SymbolicTraits) -> UIFont {
    guard let descriptor = font.fontDescriptor.withSymbolicTraits(font.fontDescriptor.symbolicTraits.union(trait)) else {
        return font
    }
    return UIFont(descriptor: descriptor, size: font.pointSize)
}
#endif

private func supportsResponsiveLargeFileHighlight(language: String) -> Bool {
    isJSONLikeLanguage(language) &&
        currentLargeFileSyntaxHighlightMode() == .minimal &&
        currentLargeFileOpenMode() != .plainText
}

private func supportsResponsiveLargeFileHighlight(language: String, textLength: Int) -> Bool {
    textLength <= EditorRuntimeLimits.ultraLargeResponsiveSyntaxUTF16Length &&
        supportsResponsiveLargeFileHighlight(language: language)
}

private enum LargeFileSyntaxHighlightMode: String {
    case off
    case minimal
}

private enum LargeFileOpenMode: String {
    case standard
    case deferred
    case plainText
}

private func currentLargeFileSyntaxHighlightMode() -> LargeFileSyntaxHighlightMode {
    let raw = UserDefaults.standard.string(forKey: "SettingsLargeFileSyntaxHighlighting") ?? "minimal"
    return LargeFileSyntaxHighlightMode(rawValue: raw) ?? .minimal
}

private func currentLargeFileOpenMode() -> LargeFileOpenMode {
    let raw = UserDefaults.standard.string(forKey: "SettingsLargeFileOpenMode") ?? "deferred"
    return LargeFileOpenMode(rawValue: raw) ?? .deferred
}

private func shouldUseChunkedLargeFileInstall(isLargeFileMode: Bool, textLength: Int) -> Bool {
    guard isLargeFileMode else { return false }
    guard currentLargeFileOpenMode() != .standard else { return false }
    return textLength >= EditorRuntimeLimits.syntaxMinimalUTF16Length
}

private func isJSONWhitespace(_ codeUnit: unichar) -> Bool {
    codeUnit == 32 || codeUnit == 9 || codeUnit == 10 || codeUnit == 13
}

private func isJSONDigit(_ codeUnit: unichar) -> Bool {
    codeUnit >= 48 && codeUnit <= 57
}

private func isJSONLetter(_ codeUnit: unichar) -> Bool {
    (codeUnit >= 65 && codeUnit <= 90) || (codeUnit >= 97 && codeUnit <= 122)
}

struct EditorTextMutation {
    let documentID: UUID
    let range: NSRange
    let replacement: String
}

private enum LargeFileInstallRuntime {
    static let chunkUTF16 = 262_144
}

#if os(macOS)
private func replaceTextPreservingSelectionAndFocus(
    _ textView: NSTextView,
    with newText: String,
    preserveViewport: Bool = true,
    preserveHorizontalOffset: Bool = true
) {
    let previousSelection = textView.selectedRange()
    let hadFocus = (textView.window?.firstResponder as? NSTextView) === textView
    let priorOrigin = textView.enclosingScrollView?.contentView.bounds.origin ?? .zero
    textView.string = newText
    let length = (newText as NSString).length
    let safeLocation = min(max(0, previousSelection.location), length)
    let safeLength = min(max(0, previousSelection.length), max(0, length - safeLocation))
    textView.setSelectedRange(NSRange(location: safeLocation, length: safeLength))
    if let clipView = textView.enclosingScrollView?.contentView {
        let targetOrigin: CGPoint
        if preserveViewport {
            targetOrigin = CGPoint(
                x: preserveHorizontalOffset ? priorOrigin.x : 0,
                y: priorOrigin.y
            )
        } else {
            targetOrigin = .zero
        }
        clipView.scroll(to: targetOrigin)
        textView.enclosingScrollView?.reflectScrolledClipView(clipView)
    }
    if hadFocus {
        textView.window?.makeFirstResponder(textView)
    }
}
#endif

private enum EmmetExpander {
    struct Node {
        var tag: String
        var id: String?
        var classes: [String]
        var count: Int
        var children: [Node]
    }

    private static let allowedChars = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.#>+*-_")
    private static let voidTags: Set<String> = ["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"]

    static func expansionIfPossible(in text: String, cursorUTF16Location: Int, language: String) -> (range: NSRange, expansion: String, caretOffset: Int)? {
        guard language == "html" || language == "php" else { return nil }
        if language == "php" && !isHTMLContextInPHP(text: text, cursorUTF16Location: cursorUTF16Location) {
            return nil
        }

        let ns = text as NSString
        let clamped = min(max(0, cursorUTF16Location), ns.length)
        guard let range = abbreviationRange(in: ns, cursor: clamped), range.length > 0 else { return nil }
        let raw = ns.substring(with: range).trimmingCharacters(in: .whitespacesAndNewlines)
        guard !raw.isEmpty, !raw.contains("<"), !raw.contains("> ") else { return nil }
        guard let nodes = parseChain(raw), !nodes.isEmpty else { return nil }
        let indent = leadingIndentationForLine(in: ns, at: range.location)
        let rendered = render(nodes: nodes, indent: indent, level: 0)
        if let first = rendered.range(of: "></") {
            let caretUTF16 = rendered[..<first.lowerBound].utf16.count + 1
            return (range, rendered, caretUTF16)
        }
        return (range, rendered, rendered.utf16.count)
    }

    private static func abbreviationRange(in text: NSString, cursor: Int) -> NSRange? {
        guard text.length > 0, cursor > 0 else { return nil }
        var start = cursor
        while start > 0 {
            let scalar = text.character(at: start - 1)
            guard let uni = UnicodeScalar(scalar), allowedChars.contains(uni) else { break }
            start -= 1
        }
        guard start < cursor else { return nil }
        return NSRange(location: start, length: cursor - start)
    }

    private static func leadingIndentationForLine(in text: NSString, at location: Int) -> String {
        let lineRange = text.lineRange(for: NSRange(location: max(0, min(location, text.length)), length: 0))
        let line = text.substring(with: lineRange)
        return String(line.prefix { $0 == " " || $0 == "\t" })
    }

    private static func isHTMLContextInPHP(text: String, cursorUTF16Location: Int) -> Bool {
        let ns = text as NSString
        let clamped = min(max(0, cursorUTF16Location), ns.length)
        let search = NSRange(location: 0, length: clamped)
        let openRanges = [
            ns.range(of: "<?php", options: .backwards, range: search),
            ns.range(of: "<?=", options: .backwards, range: search),
            ns.range(of: "<?", options: .backwards, range: search)
        ]
        let latestOpen = openRanges.compactMap { $0.location == NSNotFound ? nil : $0.location }.max() ?? -1
        let latestCloseRange = ns.range(of: "?>", options: .backwards, range: search)
        let latestClose = latestCloseRange.location
        return latestOpen == -1 || (latestClose != NSNotFound && latestClose > latestOpen)
    }

    private static func parseChain(_ raw: String) -> [Node]? {
        let hierarchyParts = raw.split(separator: ">", omittingEmptySubsequences: false).map(String.init)
        guard !hierarchyParts.isEmpty else { return nil }

        var levels: [[Node]] = []
        for part in hierarchyParts {
            let siblings = part.split(separator: "+", omittingEmptySubsequences: false).map(String.init)
            var levelNodes: [Node] = []
            for sibling in siblings {
                guard let node = parseNode(sibling), !node.tag.isEmpty else { return nil }
                levelNodes.append(node)
            }
            guard !levelNodes.isEmpty else { return nil }
            levels.append(levelNodes)
        }

        for level in stride(from: levels.count - 2, through: 0, by: -1) {
            let children = levels[level + 1]
            for idx in levels[level].indices {
                levels[level][idx].children = children
            }
        }
        return levels.first
    }

    private static func parseNode(_ token: String) -> Node? {
        let source = token.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !source.isEmpty else { return nil }

        var count = 1
        var core = source
        if let star = source.lastIndex(of: "*") {
            let multiplier = String(source[source.index(after: star)...])
            if let n = Int(multiplier), n > 0 {
                count = n
                core = String(source[..<star])
            }
        }

        var tag = ""
        var id: String?
        var classes: [String] = []
        var i = core.startIndex
        while i < core.endIndex {
            let ch = core[i]
            if ch == "." || ch == "#" { break }
            tag.append(ch)
            i = core.index(after: i)
        }
        if tag.isEmpty { tag = "div" }

        while i < core.endIndex {
            let marker = core[i]
            guard marker == "." || marker == "#" else { return nil }
            i = core.index(after: i)
            var value = ""
            while i < core.endIndex {
                let c = core[i]
                if c == "." || c == "#" { break }
                value.append(c)
                i = core.index(after: i)
            }
            guard !value.isEmpty else { return nil }
            if marker == "#" { id = value } else { classes.append(value) }
        }

        return Node(tag: tag, id: id, classes: classes, count: count, children: [])
    }

    private static func render(nodes: [Node], indent: String, level: Int) -> String {
        nodes.map { render(node: $0, indent: indent, level: level) }.joined(separator: "\n")
    }

    private static func render(node: Node, indent: String, level: Int) -> String {
        var lines: [String] = []
        for _ in 0..<max(1, node.count) {
            let pad = indent + String(repeating: "    ", count: level)
            let attrs = attributes(for: node)
            if node.children.isEmpty {
                if voidTags.contains(node.tag.lowercased()) {
                    lines.append("\(pad)<\(node.tag)\(attrs)>")
                } else {
                    lines.append("\(pad)<\(node.tag)\(attrs)></\(node.tag)>")
                }
            } else {
                lines.append("\(pad)<\(node.tag)\(attrs)>")
                lines.append(render(nodes: node.children, indent: indent, level: level + 1))
                lines.append("\(pad)</\(node.tag)>")
            }
        }
        return lines.joined(separator: "\n")
    }

    private static func attributes(for node: Node) -> String {
        var attrs: [String] = []
        if let id = node.id { attrs.append("id=\"\(id)\"") }
        if !node.classes.isEmpty { attrs.append("class=\"\(node.classes.joined(separator: " "))\"") }
        return attrs.isEmpty ? "" : " " + attrs.joined(separator: " ")
    }
}

///MARK: - Paste Notifications
extension Notification.Name {
    static let pastedFileURL = Notification.Name("pastedFileURL")
    static let editorSelectionDidChange = Notification.Name("editorSelectionDidChange")
    static let editorRequestCodeSnapshotFromSelection = Notification.Name("editorRequestCodeSnapshotFromSelection")
}

///MARK: - Scope Match Models
// Bracket-based scope data used for highlighting and guide rendering.
private struct BracketScopeMatch {
    let openRange: NSRange
    let closeRange: NSRange
    let scopeRange: NSRange?
    let guideMarkerRanges: [NSRange]
}

// Indentation-based scope data used for Python/YAML style highlighting.
private struct IndentationScopeMatch {
    let scopeRange: NSRange
    let guideMarkerRanges: [NSRange]
}

///MARK: - Bracket/Indent Scope Helpers
private func matchingOpeningBracket(for closing: unichar) -> unichar? {
    switch UnicodeScalar(closing) {
    case "}": return unichar(UnicodeScalar("{").value)
    case "]": return unichar(UnicodeScalar("[").value)
    case ")": return unichar(UnicodeScalar("(").value)
    default: return nil
    }
}

private func matchingClosingBracket(for opening: unichar) -> unichar? {
    switch UnicodeScalar(opening) {
    case "{": return unichar(UnicodeScalar("}").value)
    case "[": return unichar(UnicodeScalar("]").value)
    case "(": return unichar(UnicodeScalar(")").value)
    default: return nil
    }
}

private func isBracket(_ c: unichar) -> Bool {
    matchesAny(c, ["{", "}", "[", "]", "(", ")"])
}

private func matchesAny(_ c: unichar, _ chars: [Character]) -> Bool {
    guard let scalar = UnicodeScalar(c) else { return false }
    return chars.contains(Character(scalar))
}

private func computeBracketScopeMatch(text: String, caretLocation: Int) -> BracketScopeMatch? {
    let ns = text as NSString
    let length = ns.length
    guard length > 0 else { return nil }

    func matchFrom(start: Int) -> BracketScopeMatch? {
        guard start >= 0 && start < length else { return nil }
        let startChar = ns.character(at: start)
        let openIndex: Int
        let closeIndex: Int

        if let wantedClose = matchingClosingBracket(for: startChar) {
            var depth = 0
            var found: Int?
            for i in start..<length {
                let c = ns.character(at: i)
                if c == startChar { depth += 1 }
                if c == wantedClose {
                    depth -= 1
                    if depth == 0 {
                        found = i
                        break
                    }
                }
            }
            guard let found else { return nil }
            openIndex = start
            closeIndex = found
        } else if let wantedOpen = matchingOpeningBracket(for: startChar) {
            var depth = 0
            var found: Int?
            var i = start
            while i >= 0 {
                let c = ns.character(at: i)
                if c == startChar { depth += 1 }
                if c == wantedOpen {
                    depth -= 1
                    if depth == 0 {
                        found = i
                        break
                    }
                }
                i -= 1
            }
            guard let found else { return nil }
            openIndex = found
            closeIndex = start
        } else {
            return nil
        }

        let openRange = NSRange(location: openIndex, length: 1)
        let closeRange = NSRange(location: closeIndex, length: 1)
        let scopeLength = max(0, closeIndex - openIndex - 1)
        let scopeRange: NSRange? = scopeLength > 0 ? NSRange(location: openIndex + 1, length: scopeLength) : nil

        let openLineRange = ns.lineRange(for: NSRange(location: openIndex, length: 0))
        let closeLineRange = ns.lineRange(for: NSRange(location: closeIndex, length: 0))
        let column = openIndex - openLineRange.location

        var markers: [NSRange] = []
        var lineStart = openLineRange.location
        while lineStart <= closeLineRange.location && lineStart < length {
            let lineRange = ns.lineRange(for: NSRange(location: lineStart, length: 0))
            let lineEndExcludingNewline = lineRange.location + max(0, lineRange.length - 1)
            if lineEndExcludingNewline > lineRange.location {
                let markerLoc = min(lineRange.location + column, lineEndExcludingNewline - 1)
                if markerLoc >= lineRange.location && markerLoc < lineEndExcludingNewline {
                    markers.append(NSRange(location: markerLoc, length: 1))
                }
            }
            let nextLineStart = lineRange.location + lineRange.length
            if nextLineStart <= lineStart { break }
            lineStart = nextLineStart
        }

        return BracketScopeMatch(
            openRange: openRange,
            closeRange: closeRange,
            scopeRange: scopeRange,
            guideMarkerRanges: markers
        )
    }

    let safeCaret = max(0, min(caretLocation, length))
    var probeIndices: [Int] = [safeCaret]
    if safeCaret > 0 { probeIndices.append(safeCaret - 1) }

    var candidateIndices: [Int] = []
    var seenCandidates = Set<Int>()
    func addCandidate(_ index: Int) {
        guard index >= 0 && index < length else { return }
        if seenCandidates.insert(index).inserted {
            candidateIndices.append(index)
        }
    }
    for idx in probeIndices where idx >= 0 && idx < length {
        if isBracket(ns.character(at: idx)) {
            addCandidate(idx)
        }
    }

    // If caret is not directly on a bracket, find the nearest enclosing opening
    // bracket whose matching close still contains the caret.
    var stack: [Int] = []
    if safeCaret > 0 {
        for i in 0..<safeCaret {
            let c = ns.character(at: i)
            if matchingClosingBracket(for: c) != nil {
                stack.append(i)
                continue
            }
            if let wantedOpen = matchingOpeningBracket(for: c), let last = stack.last, ns.character(at: last) == wantedOpen {
                stack.removeLast()
            }
        }
    }
    while let candidate = stack.popLast() {
        let c = ns.character(at: candidate)
        guard let wantedClose = matchingClosingBracket(for: c) else { continue }
        var depth = 0
        var foundClose: Int?
        for i in candidate..<length {
            let current = ns.character(at: i)
            if current == c { depth += 1 }
            if current == wantedClose {
                depth -= 1
                if depth == 0 {
                    foundClose = i
                    break
                }
            }
        }
        if let close = foundClose, safeCaret >= candidate && safeCaret <= close {
            addCandidate(candidate)
        }
    }

    // Add all brackets by nearest distance so we still find a valid scope even if
    // early candidates are unmatched (e.g. bracket chars inside strings/comments).
    let allBracketIndices = (0..<length).filter { isBracket(ns.character(at: $0)) }
    let sortedByDistance = allBracketIndices.sorted { abs($0 - safeCaret) < abs($1 - safeCaret) }
    for idx in sortedByDistance {
        addCandidate(idx)
    }

    for candidate in candidateIndices {
        if let match = matchFrom(start: candidate) {
            return match
        }
    }
    return nil
}

private func supportsIndentationScopes(language: String) -> Bool {
    let lang = language.lowercased()
    return lang == "python" || lang == "yaml" || lang == "yml"
}

private func computeIndentationScopeMatch(text: String, caretLocation: Int) -> IndentationScopeMatch? {
    let ns = text as NSString
    let length = ns.length
    guard length > 0 else { return nil }

    struct LineInfo {
        let range: NSRange
        let contentEnd: Int
        let indent: Int?
    }

    func lineIndent(_ lineRange: NSRange) -> Int? {
        guard lineRange.length > 0 else { return nil }
        let line = ns.substring(with: lineRange)
        var indent = 0
        var sawContent = false
        for ch in line {
            if ch == " " {
                indent += 1
                continue
            }
            if ch == "\t" {
                indent += 4
                continue
            }
            if ch == "\n" || ch == "\r" {
                continue
            }
            sawContent = true
            break
        }
        return sawContent ? indent : nil
    }

    var lines: [LineInfo] = []
    var lineStart = 0
    while lineStart < length {
        let lr = ns.lineRange(for: NSRange(location: lineStart, length: 0))
        let contentEnd = lr.location + max(0, lr.length - 1)
        lines.append(LineInfo(range: lr, contentEnd: contentEnd, indent: lineIndent(lr)))
        let next = lr.location + lr.length
        if next <= lineStart { break }
        lineStart = next
    }
    guard !lines.isEmpty else { return nil }

    let safeCaret = max(0, min(caretLocation, max(0, length - 1)))
    guard let caretLineIndex = lines.firstIndex(where: { NSLocationInRange(safeCaret, $0.range) }) else { return nil }

    var blockStart = caretLineIndex
    var baseIndent: Int? = lines[caretLineIndex].indent

    // If caret is on a block header line (e.g. Python ":"), use the next indented line.
    if baseIndent == nil || baseIndent == 0 {
        let currentLine = ns.substring(with: lines[caretLineIndex].range).trimmingCharacters(in: .whitespacesAndNewlines)
        if currentLine.hasSuffix(":") {
            var next = caretLineIndex + 1
            while next < lines.count {
                if let nextIndent = lines[next].indent, nextIndent > 0 {
                    baseIndent = nextIndent
                    blockStart = next
                    break
                }
                next += 1
            }
        }
    }

    guard let indentLevel = baseIndent, indentLevel > 0 else { return nil }

    var start = blockStart
    while start > 0 {
        let prev = lines[start - 1]
        guard let prevIndent = prev.indent else {
            start -= 1
            continue
        }
        if prevIndent >= indentLevel {
            start -= 1
            continue
        }
        break
    }

    var end = blockStart
    var idx = blockStart + 1
    while idx < lines.count {
        let info = lines[idx]
        if let infoIndent = info.indent {
            if infoIndent < indentLevel { break }
            end = idx
            idx += 1
            continue
        }
        // Keep blank lines inside the current block.
        end = idx
        idx += 1
    }

    let startLoc = lines[start].range.location
    let endLoc = lines[end].contentEnd
    guard endLoc > startLoc else { return nil }

    var guideMarkers: [NSRange] = []
    for i in start...end {
        let info = lines[i]
        guard info.contentEnd > info.range.location else { continue }
        guard let infoIndent = info.indent, infoIndent >= indentLevel else { continue }
        let marker = min(info.range.location + max(0, indentLevel - 1), info.contentEnd - 1)
        if marker >= info.range.location && marker < info.contentEnd {
            guideMarkers.append(NSRange(location: marker, length: 1))
        }
    }

    return IndentationScopeMatch(
        scopeRange: NSRange(location: startLoc, length: endLoc - startLoc),
        guideMarkerRanges: guideMarkers
    )
}

private func isValidRange(_ range: NSRange, utf16Length: Int) -> Bool {
    guard range.location != NSNotFound, range.length >= 0, range.location >= 0 else { return false }
    return NSMaxRange(range) <= utf16Length
}

private func fastSyntaxColorRanges(
    language: String,
    profile: SyntaxPatternProfile,
    text: NSString,
    in range: NSRange,
    colors: SyntaxColors
) -> [(NSRange, Color)]? {
    let lower = language.lowercased()
    if profile == .csvFast || (profile == .full && lower == "csv" && range.length >= 180_000) {
        let rangeEnd = NSMaxRange(range)
        var out: [(NSRange, Color)] = []
        var i = range.location
        while i < rangeEnd {
            let ch = text.character(at: i)
            if ch == 34 { // "
                let start = i
                i += 1
                while i < rangeEnd {
                    let c = text.character(at: i)
                    if c == 34 {
                        if i + 1 < rangeEnd && text.character(at: i + 1) == 34 {
                            i += 2
                            continue
                        }
                        i += 1
                        break
                    }
                    i += 1
                }
                out.append((NSRange(location: start, length: max(0, i - start)), colors.string))
                continue
            }
            if ch == 44 { // ,
                out.append((NSRange(location: i, length: 1), colors.property))
            }
            i += 1
        }
        return out
    }

    if profile == .htmlFast && (lower == "html" || lower == "xml") {
        let rangeEnd = NSMaxRange(range)
        var out: [(NSRange, Color)] = []
        var i = range.location
        while i < rangeEnd {
            let ch = text.character(at: i)
            if ch == 60 { // <
                let start = i
                i += 1
                while i < rangeEnd && text.character(at: i) != 62 { // >
                    i += 1
                }
                if i < rangeEnd && text.character(at: i) == 62 { i += 1 }
                out.append((NSRange(location: start, length: max(0, i - start)), colors.tag))
                continue
            }
            if ch == 34 { // "
                let start = i
                i += 1
                while i < rangeEnd && text.character(at: i) != 34 {
                    i += 1
                }
                if i < rangeEnd { i += 1 }
                out.append((NSRange(location: start, length: max(0, i - start)), colors.string))
                continue
            }
            i += 1
        }
        return out
    }

    if profile == .jsonFast && isJSONLikeLanguage(lower) {
        let rangeEnd = NSMaxRange(range)
        var out: [(NSRange, Color)] = []
        var i = range.location
        let budgetDeadline = CFAbsoluteTimeGetCurrent() + EditorRuntimeLimits.largeFileJSONTokenBudgetSeconds
        while i < rangeEnd {
            if CFAbsoluteTimeGetCurrent() >= budgetDeadline {
                break
            }
            let ch = text.character(at: i)
            if isJSONWhitespace(ch) {
                i += 1
                continue
            }
            if ch == 34 { // "
                let start = i
                i += 1
                while i < rangeEnd {
                    let c = text.character(at: i)
                    if c == 92 { // \
                        i += min(2, rangeEnd - i)
                        continue
                    }
                    i += 1
                    if c == 34 {
                        break
                    }
                }
                let tokenRange = NSRange(location: start, length: max(0, i - start))
                var lookahead = i
                while lookahead < rangeEnd && isJSONWhitespace(text.character(at: lookahead)) {
                    lookahead += 1
                }
                let tokenColor = (lookahead < rangeEnd && text.character(at: lookahead) == 58)
                    ? colors.property
                    : colors.string
                out.append((tokenRange, tokenColor))
                continue
            }
            if ch == 123 || ch == 125 || ch == 91 || ch == 93 || ch == 58 || ch == 44 {
                out.append((NSRange(location: i, length: 1), colors.meta))
                i += 1
                continue
            }
            if ch == 45 || isJSONDigit(ch) {
                let start = i
                if ch == 45 {
                    i += 1
                }
                while i < rangeEnd && isJSONDigit(text.character(at: i)) {
                    i += 1
                }
                if i < rangeEnd && text.character(at: i) == 46 {
                    i += 1
                    while i < rangeEnd && isJSONDigit(text.character(at: i)) {
                        i += 1
                    }
                }
                if i < rangeEnd {
                    let exp = text.character(at: i)
                    if exp == 69 || exp == 101 {
                        i += 1
                        if i < rangeEnd {
                            let sign = text.character(at: i)
                            if sign == 43 || sign == 45 {
                                i += 1
                            }
                        }
                        while i < rangeEnd && isJSONDigit(text.character(at: i)) {
                            i += 1
                        }
                    }
                }
                if i > start {
                    out.append((NSRange(location: start, length: i - start), colors.number))
                    continue
                }
            }
            if isJSONLetter(ch) {
                let start = i
                i += 1
                while i < rangeEnd && isJSONLetter(text.character(at: i)) {
                    i += 1
                }
                let wordRange = NSRange(location: start, length: i - start)
                let word = text.substring(with: wordRange)
                if word == "true" || word == "false" || word == "null" {
                    out.append((wordRange, colors.keyword))
                }
                continue
            }
            i += 1
        }
        return out
    }
    return nil
}

#if os(macOS)
import AppKit

private struct TextViewObserverToken: @unchecked Sendable {
    let raw: NSObjectProtocol
}

final class AcceptingTextView: NSTextView {
    override var acceptsFirstResponder: Bool { true }
    override func acceptsFirstMouse(for event: NSEvent?) -> Bool { true }
    override var mouseDownCanMoveWindow: Bool { false }
    override var isOpaque: Bool { false }
    private let vimModeDefaultsKey = "EditorVimModeEnabled"
    private let vimInterceptionDefaultsKey = "EditorVimInterceptionEnabled"
    private var isVimInsertMode: Bool = true
    private var vimObservers: [TextViewObserverToken] = []
    private var activityObservers: [TextViewObserverToken] = []
    private var didConfigureVimMode: Bool = false
    private var lastAppliedInvisiblePreference: Bool?
    private var defaultsObserver: TextViewObserverToken?
    private let dropReadChunkSize = 64 * 1024
    fileprivate var isApplyingDroppedContent: Bool = false
    private var inlineSuggestion: String?
    private var inlineSuggestionLocation: Int?
    private var inlineSuggestionView: NSTextField?
    fileprivate var isApplyingInlineSuggestion: Bool = false
    fileprivate var recentlyAcceptedInlineSuggestion: Bool = false
    fileprivate var isApplyingPaste: Bool = false
    var autoIndentEnabled: Bool = true
    var autoCloseBracketsEnabled: Bool = true
    var emmetLanguage: String = "plain"
    var indentStyle: String = "spaces"
    var indentWidth: Int = 4
    var highlightCurrentLine: Bool = true
    private let editorInsetX: CGFloat = 12

    // We want the caret at the *start* of the paste.
    private var pendingPasteCaretLocation: Int?

    deinit {
        if let defaultsObserver {
            NotificationCenter.default.removeObserver(defaultsObserver.raw)
        }
        for observer in activityObservers {
            NotificationCenter.default.removeObserver(observer.raw)
        }
        for observer in vimObservers {
            NotificationCenter.default.removeObserver(observer.raw)
        }
    }

    override func viewDidMoveToWindow() {
        super.viewDidMoveToWindow()
        if !didConfigureVimMode {
            configureVimMode()
            didConfigureVimMode = true
        }
        configureActivityObservers()
        Task { @MainActor [weak self] in
            guard let self else { return }
            self.window?.makeFirstResponder(self)
        }
        textContainerInset = NSSize(width: editorInsetX, height: 12)
        if defaultsObserver == nil {
            defaultsObserver = TextViewObserverToken(raw: NotificationCenter.default.addObserver(
                forName: UserDefaults.didChangeNotification,
                object: nil,
                queue: .main
            ) { [weak self] _ in
                Task { @MainActor [weak self] in
                    self?.forceDisableInvisibleGlyphRendering(deep: true)
                }
            })
        }
        forceDisableInvisibleGlyphRendering(deep: true)
    }

    override func draw(_ dirtyRect: NSRect) {
        // Keep invisible/control marker rendering aligned with user preference on every redraw.
        forceDisableInvisibleGlyphRendering()
        super.draw(dirtyRect)
    }

    override func mouseDown(with event: NSEvent) {
        cancelPendingPasteCaretEnforcement()
        clearInlineSuggestion()
        NotificationCenter.default.post(name: .editorPointerInteraction, object: self)
        super.mouseDown(with: event)
        window?.makeFirstResponder(self)
    }

    override func scrollWheel(with event: NSEvent) {
        let flags = event.modifierFlags.intersection(.deviceIndependentFlagsMask)
        if flags.contains([.shift, .option]) {
            let delta = event.scrollingDeltaY
            if abs(delta) > 0.1 {
                let step: Double = delta > 0 ? 1 : -1
                NotificationCenter.default.post(name: .zoomEditorFontRequested, object: step)
                return
            }
        }
        cancelPendingPasteCaretEnforcement()
        super.scrollWheel(with: event)
        updateInlineSuggestionPosition()
    }

    override func becomeFirstResponder() -> Bool {
        let didBecome = super.becomeFirstResponder()
        if didBecome, UserDefaults.standard.bool(forKey: vimModeDefaultsKey) {
            // Re-enter NORMAL whenever Vim mode is active.
            isVimInsertMode = false
            postVimModeState()
        }
        return didBecome
    }

    override func layout() {
        super.layout()
        updateInlineSuggestionPosition()
        forceDisableInvisibleGlyphRendering()
    }

    ///MARK: - Drag and Drop
    override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
        let pb = sender.draggingPasteboard
        let canReadFileURL = pb.canReadObject(forClasses: [NSURL.self], options: [
            .urlReadingFileURLsOnly: true
        ])
        let canReadPlainText = pasteboardPlainString(from: pb)?.isEmpty == false
        return (canReadFileURL || canReadPlainText) ? .copy : []
    }

    override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
        let pb = sender.draggingPasteboard
        if let nsurls = pb.readObjects(forClasses: [NSURL.self], options: [.urlReadingFileURLsOnly: true]) as? [NSURL],
           !nsurls.isEmpty {
            let urls = nsurls.map { $0 as URL }
            if urls.count == 1 {
                NotificationCenter.default.post(name: .pastedFileURL, object: urls[0])
            } else {
                NotificationCenter.default.post(name: .pastedFileURL, object: urls)
            }
            // Do not insert content; let higher-level controller open a new tab.
            return true
        }
        if let droppedString = pasteboardPlainString(from: pb), !droppedString.isEmpty {
            let sanitized = sanitizedPlainText(droppedString)
            let dropRange = insertionRangeForDrop(sender)
            isApplyingPaste = true
            if let storage = textStorage {
                storage.beginEditing()
                replaceCharacters(in: dropRange, with: sanitized)
                storage.endEditing()
            } else {
                let current = string as NSString
                if dropRange.location <= current.length &&
                    dropRange.location + dropRange.length <= current.length {
                    string = current.replacingCharacters(in: dropRange, with: sanitized)
                } else {
                    isApplyingPaste = false
                    return false
                }
            }
            isApplyingPaste = false

            NotificationCenter.default.post(name: .pastedText, object: sanitized)
            didChangeText()
            return true
        }
        return false
    }

    private func insertionRangeForDrop(_ sender: NSDraggingInfo) -> NSRange {
        let windowPoint = sender.draggingLocation
        let viewPoint = convert(windowPoint, from: nil)
        let insertionIndex = characterIndexForInsertion(at: viewPoint)
        let clamped = clampedRange(NSRange(location: insertionIndex, length: 0), forTextLength: (string as NSString).length)
        setSelectedRange(clamped)
        return clamped
    }

    private func applyDroppedContentInChunks(
        _ content: String,
        at selection: NSRange,
        fileName: String,
        largeFileMode: Bool,
        completion: @escaping (Bool, Int) -> Void
    ) {
        let nsContent = content as NSString
        let safeSelection = clampedRange(selection, forTextLength: (string as NSString).length)
        let total = nsContent.length
        if total == 0 {
            completion(true, 0)
            return
        }
        NotificationCenter.default.post(
            name: .droppedFileLoadProgress,
            object: nil,
            userInfo: [
                "fraction": 0.70,
                "fileName": "Applying file",
                "largeFileMode": largeFileMode
            ]
        )

        // Large payloads: prefer one atomic replace after yielding one runloop turn so
        // progress updates can render before the heavy text-system mutation begins.
        if total >= 300_000 {
            isApplyingDroppedContent = true
            NotificationCenter.default.post(
                name: .droppedFileLoadProgress,
                object: nil,
                userInfo: [
                    "fraction": 0.90,
                    "fileName": "Applying file",
                    "largeFileMode": largeFileMode,
                    "isDeterminate": true
                ]
            )

            DispatchQueue.main.async { [weak self] in
                guard let self else {
                    completion(false, 0)
                    return
                }

                let replaceSucceeded: Bool
                if let storage = self.textStorage {
                    let liveSafeSelection = self.clampedRange(safeSelection, forTextLength: storage.length)
                    self.undoManager?.disableUndoRegistration()
                    storage.beginEditing()
                    if storage.length == 0 && liveSafeSelection.location == 0 && liveSafeSelection.length == 0 {
                        storage.mutableString.setString(content)
                    } else {
                        storage.mutableString.replaceCharacters(in: liveSafeSelection, with: content)
                    }
                    storage.endEditing()
                    self.undoManager?.enableUndoRegistration()
                    replaceSucceeded = true
                } else {
                    let current = self.string as NSString
                    if safeSelection.location <= current.length &&
                        safeSelection.location + safeSelection.length <= current.length {
                        let replaced = current.replacingCharacters(in: safeSelection, with: content)
                        self.string = replaced
                        replaceSucceeded = true
                    } else {
                        replaceSucceeded = false
                    }
                }

                self.isApplyingDroppedContent = false
                NotificationCenter.default.post(
                    name: .droppedFileLoadProgress,
                    object: nil,
                    userInfo: [
                        "fraction": replaceSucceeded ? 1.0 : 0.0,
                        "fileName": replaceSucceeded ? "Reading file" : "Import failed",
                        "largeFileMode": largeFileMode,
                        "isDeterminate": true
                    ]
                )
                completion(replaceSucceeded, replaceSucceeded ? total : 0)
            }
            return
        }

        let replaceSucceeded: Bool
        if let storage = textStorage {
            undoManager?.disableUndoRegistration()
            storage.beginEditing()
            storage.mutableString.replaceCharacters(in: safeSelection, with: content)
            storage.endEditing()
            undoManager?.enableUndoRegistration()
            replaceSucceeded = true
        } else {
            // Fallback for environments where textStorage is temporarily unavailable.
            let current = string as NSString
            if safeSelection.location <= current.length &&
                safeSelection.location + safeSelection.length <= current.length {
                let replaced = current.replacingCharacters(in: safeSelection, with: content)
                string = replaced
                replaceSucceeded = true
            } else {
                replaceSucceeded = false
            }
        }

        NotificationCenter.default.post(
            name: .droppedFileLoadProgress,
            object: nil,
            userInfo: [
                "fraction": replaceSucceeded ? 1.0 : 0.0,
                "fileName": replaceSucceeded ? "Reading file" : "Import failed",
                "largeFileMode": largeFileMode
            ]
        )

        completion(replaceSucceeded, replaceSucceeded ? total : 0)
    }

    private func clampedSelectionRange() -> NSRange {
        clampedRange(selectedRange(), forTextLength: (string as NSString).length)
    }

    private func clampedRange(_ range: NSRange, forTextLength length: Int) -> NSRange {
        guard length >= 0 else { return NSRange(location: 0, length: 0) }
        if range.location == NSNotFound {
            return NSRange(location: length, length: 0)
        }
        let safeLocation = min(max(0, range.location), length)
        let maxLen = max(0, length - safeLocation)
        let safeLength = min(max(0, range.length), maxLen)
        return NSRange(location: safeLocation, length: safeLength)
    }

    private func readDroppedFileData(
        at url: URL,
        totalBytes: Int64,
        progress: @escaping (Double) -> Void
    ) throws -> Data {
        do {
            let handle = try FileHandle(forReadingFrom: url)
            defer { try? handle.close() }

            var data = Data()
            if totalBytes > 0, totalBytes <= Int64(Int.max) {
                data.reserveCapacity(Int(totalBytes))
            }

            var loadedBytes: Int64 = 0
            var lastReported: Double = -1

            while true {
                let chunk = try handle.read(upToCount: dropReadChunkSize) ?? Data()
                if chunk.isEmpty { break }
                data.append(chunk)
                loadedBytes += Int64(chunk.count)

                if totalBytes > 0 {
                    let fraction = min(1.0, Double(loadedBytes) / Double(totalBytes))
                    if fraction - lastReported >= 0.02 || fraction >= 1.0 {
                        lastReported = fraction
                        DispatchQueue.main.async {
                            progress(fraction)
                        }
                    }
                }
            }

            if totalBytes > 0, lastReported < 1.0 {
                DispatchQueue.main.async {
                    progress(1.0)
                }
            }
            return data
        } catch {
            // Fallback path for URLs/FileHandle edge cases in sandboxed drag-drop.
            let data = try Data(contentsOf: url, options: [.mappedIfSafe])
            DispatchQueue.main.async {
                progress(1.0)
            }
            return data
        }
    }

    private func decodeDroppedFileText(_ data: Data, fileURL: URL) -> String {
        let encodings: [String.Encoding] = [.utf8, .utf16, .utf16LittleEndian, .utf16BigEndian, .windowsCP1252, .isoLatin1]
        for encoding in encodings {
            if let decoded = String(data: data, encoding: encoding) {
                return Self.sanitizePlainText(decoded)
            }
        }
        if let fallback = try? String(contentsOf: fileURL, encoding: .utf8) {
            return Self.sanitizePlainText(fallback)
        }
        return Self.sanitizePlainText(String(decoding: data, as: UTF8.self))
    }

    ///MARK: - Typing Helpers
    override func insertText(_ insertString: Any, replacementRange: NSRange) {
        if !isApplyingInlineSuggestion {
            clearInlineSuggestion()
        }
        guard let s = insertString as? String else {
            super.insertText(insertString, replacementRange: replacementRange)
            return
        }
        let sanitized = sanitizedPlainText(s)

        // Keep invisible/control marker rendering aligned with current preference.
        forceDisableInvisibleGlyphRendering()

        // Auto-indent by copying leading whitespace
        if sanitized == "\n" && autoIndentEnabled {
            let ns = (string as NSString)
            let sel = selectedRange()
            let lineRange = ns.lineRange(for: NSRange(location: sel.location, length: 0))
            let currentLine = ns.substring(with: NSRange(
                location: lineRange.location,
                length: max(0, sel.location - lineRange.location)
            ))
            let indent = currentLine.prefix { $0 == " " || $0 == "\t" }
            super.insertText("\n" + indent, replacementRange: replacementRange)
            return
        }

        // Auto-close common bracket/quote pairs
        let pairs: [String: String] = ["(": ")", "[": "]", "{": "}", "\"": "\"", "'": "'"]
        if autoCloseBracketsEnabled, let closing = pairs[sanitized] {
            let sel = selectedRange()
            super.insertText(sanitized + closing, replacementRange: replacementRange)
            setSelectedRange(NSRange(location: sel.location + 1, length: 0))
            return
        }

        super.insertText(sanitized, replacementRange: replacementRange)
    }

    static func sanitizePlainText(_ input: String) -> String {
        // Reuse model-level sanitizer to keep all text paths consistent.
        EditorTextSanitizer.sanitize(input)
    }

    private static func containsGlyphArtifacts(_ input: String) -> Bool {
        for scalar in input.unicodeScalars {
            let value = scalar.value
            if value == 0x2581 || (0x2400...0x243F).contains(value) {
                return true
            }
        }
        return false
    }

    private func sanitizedPlainText(_ input: String) -> String {
        Self.sanitizePlainText(input)
    }

    override func keyDown(with event: NSEvent) {
        if event.keyCode == 48 || event.keyCode == 124 { // Tab or Right Arrow
            if acceptInlineSuggestion() {
                return
            }
        }
        // Safety default: bypass Vim interception unless explicitly enabled.
        if !UserDefaults.standard.bool(forKey: vimInterceptionDefaultsKey) {
            super.keyDown(with: event)
            return
        }

        let flags = event.modifierFlags.intersection(.deviceIndependentFlagsMask)
        if flags.contains(.command) || flags.contains(.option) || flags.contains(.control) {
            super.keyDown(with: event)
            return
        }

        let vimModeEnabled = UserDefaults.standard.bool(forKey: vimModeDefaultsKey)
        guard vimModeEnabled else {
            super.keyDown(with: event)
            return
        }

        if !isVimInsertMode {
            let key = event.charactersIgnoringModifiers ?? ""
            switch key {
            case "h":
                moveLeft(nil)
            case "j":
                moveDown(nil)
            case "k":
                moveUp(nil)
            case "l":
                moveRight(nil)
            case "w":
                moveWordForward(nil)
            case "b":
                moveWordBackward(nil)
            case "0":
                moveToBeginningOfLine(nil)
            case "$":
                moveToEndOfLine(nil)
            case "x":
                deleteForward(nil)
            case "p":
                paste(nil)
            case "i":
                isVimInsertMode = true
                postVimModeState()
            case "a":
                moveRight(nil)
                isVimInsertMode = true
                postVimModeState()
            case "\u{1B}":
                break
            default:
                break
            }
            return
        }

        // Escape exits insert mode.
        if event.keyCode == 53 || event.characters == "\u{1B}" {
            isVimInsertMode = false
            postVimModeState()
            return
        }

        super.keyDown(with: event)
    }

    override func insertTab(_ sender: Any?) {
        if acceptInlineSuggestion() {
            return
        }
        if let expansion = EmmetExpander.expansionIfPossible(
            in: string,
            cursorUTF16Location: selectedRange().location,
            language: emmetLanguage
        ) {
            textStorage?.beginEditing()
            replaceCharacters(in: expansion.range, with: expansion.expansion)
            textStorage?.endEditing()
            let caretLocation = expansion.range.location + expansion.caretOffset
            setSelectedRange(NSRange(location: caretLocation, length: 0))
            didChangeText()
            return
        }
        // Keep Tab insertion deterministic and avoid platform-level invisible glyph rendering.
        let insertion: String
        if indentStyle == "tabs" {
            insertion = "\t"
        } else {
            insertion = String(repeating: " ", count: max(1, indentWidth))
        }
        super.insertText(sanitizedPlainText(insertion), replacementRange: selectedRange())
        forceDisableInvisibleGlyphRendering()
    }

    // Paste: capture insertion point and enforce caret position after paste across async updates.
    override func paste(_ sender: Any?) {
        let pasteboard = NSPasteboard.general
        if let nsurls = pasteboard.readObjects(forClasses: [NSURL.self], options: [.urlReadingFileURLsOnly: true]) as? [NSURL],
           !nsurls.isEmpty {
            let urls = nsurls.map { $0 as URL }
            if urls.count == 1 {
                NotificationCenter.default.post(name: .pastedFileURL, object: urls[0])
            } else {
                NotificationCenter.default.post(name: .pastedFileURL, object: urls)
            }
            return
        }
        if let urls = fileURLsFromPasteboard(pasteboard), !urls.isEmpty {
            if urls.count == 1 {
                NotificationCenter.default.post(name: .pastedFileURL, object: urls[0])
            } else {
                NotificationCenter.default.post(name: .pastedFileURL, object: urls)
            }
            return
        }
        // Keep caret anchored at the current insertion location while paste async work settles.
        pendingPasteCaretLocation = selectedRange().location

        if let raw = pasteboardPlainString(from: pasteboard), !raw.isEmpty {
            if let pathURL = fileURLFromString(raw) {
                NotificationCenter.default.post(name: .pastedFileURL, object: pathURL)
                return
            }
            let sanitized = sanitizedPlainText(raw)
            isApplyingPaste = true
            textStorage?.beginEditing()
            replaceCharacters(in: selectedRange(), with: sanitized)
            textStorage?.endEditing()
            isApplyingPaste = false

            forceDisableInvisibleGlyphRendering()

            NotificationCenter.default.post(name: .pastedText, object: sanitized)
            didChangeText()

            schedulePasteCaretEnforcement()
            return
        }

        isApplyingPaste = true
        super.paste(sender)
        DispatchQueue.main.async { [weak self] in
            self?.isApplyingPaste = false

            self?.forceDisableInvisibleGlyphRendering()
        }

        // Enforce caret after paste (multiple ticks beats late selection changes)
        schedulePasteCaretEnforcement()
    }

    private func pasteboardPlainString(from pasteboard: NSPasteboard) -> String? {
        if let raw = pasteboard.string(forType: .string), !raw.isEmpty {
            return raw
        }
        if let strings = pasteboard.readObjects(forClasses: [NSString.self], options: nil) as? [NSString],
           let first = strings.first,
           first.length > 0 {
            return first as String
        }
        if let rtf = pasteboard.data(forType: .rtf),
           let attributed = try? NSAttributedString(
               data: rtf,
               options: [.documentType: NSAttributedString.DocumentType.rtf],
               documentAttributes: nil
           ),
           !attributed.string.isEmpty {
            return attributed.string
        }
        return nil
    }

    private func fileURLsFromPasteboard(_ pasteboard: NSPasteboard) -> [URL]? {
        if let fileURLString = pasteboard.string(forType: .fileURL),
           let url = URL(string: fileURLString),
           url.isFileURL,
           FileManager.default.fileExists(atPath: url.path) {
            return [url]
        }
        let filenamesType = NSPasteboard.PasteboardType("NSFilenamesPboardType")
        if let list = pasteboard.propertyList(forType: filenamesType) as? [String] {
            let urls = list.map { URL(fileURLWithPath: $0) }.filter { FileManager.default.fileExists(atPath: $0.path) }
            if !urls.isEmpty { return urls }
        }
        return nil
    }

    private func fileURLFromString(_ text: String) -> URL? {
        let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
        if let url = URL(string: trimmed), url.isFileURL, FileManager.default.fileExists(atPath: url.path) {
            return url
        }
        // Plain paths (with spaces or ~)
        let expanded = (trimmed as NSString).expandingTildeInPath
        if FileManager.default.fileExists(atPath: expanded) {
            return URL(fileURLWithPath: expanded)
        }
        return nil
    }

    override func didChangeText() {
        super.didChangeText()
        forceDisableInvisibleGlyphRendering(deep: true)
        if let storage = textStorage {
            let raw = storage.string
            if Self.containsGlyphArtifacts(raw) {
                let sanitized = Self.sanitizePlainText(raw)
                let sel = selectedRange()
                storage.beginEditing()
                storage.replaceCharacters(in: NSRange(location: 0, length: (raw as NSString).length), with: sanitized)
                storage.endEditing()
                setSelectedRange(NSRange(location: min(sel.location, (sanitized as NSString).length), length: 0))
            }
        }
        if !isApplyingInlineSuggestion {
            clearInlineSuggestion()
        }
        // Pasting triggers didChangeText; schedule enforcement again.
        schedulePasteCaretEnforcement()
    }

    private func forceDisableInvisibleGlyphRendering(deep: Bool = false) {
        let defaults = UserDefaults.standard
        let shouldShow = defaults.bool(forKey: "SettingsShowInvisibleCharacters")
        if defaults.bool(forKey: "NSShowAllInvisibles") != shouldShow {
            defaults.set(shouldShow, forKey: "NSShowAllInvisibles")
        }
        if defaults.bool(forKey: "NSShowControlCharacters") != shouldShow {
            defaults.set(shouldShow, forKey: "NSShowControlCharacters")
        }
        layoutManager?.showsInvisibleCharacters = shouldShow
        layoutManager?.showsControlCharacters = shouldShow

        guard deep else { return }
        if lastAppliedInvisiblePreference == shouldShow {
            return
        }
        lastAppliedInvisiblePreference = shouldShow
        if let storage = textStorage {
            layoutManager?.invalidateDisplay(forCharacterRange: NSRange(location: 0, length: storage.length))
        }
        needsDisplay = true
    }

    private func configureActivityObservers() {
        guard activityObservers.isEmpty else { return }
        let center = NotificationCenter.default
        let names: [Notification.Name] = [
            NSApplication.didBecomeActiveNotification,
            NSApplication.didResignActiveNotification,
            NSWindow.didBecomeKeyNotification,
            NSWindow.didResignKeyNotification
        ]
        for name in names {
            let token = TextViewObserverToken(raw: center.addObserver(forName: name, object: nil, queue: .main) { [weak self] notif in
                guard let self else { return }
                if let targetWindow = notif.object as? NSWindow, targetWindow != self.window {
                    return
                }
                self.forceDisableInvisibleGlyphRendering(deep: true)
            })
            activityObservers.append(token)
        }
    }

    func showInlineSuggestion(_ suggestion: String, at location: Int) {
        guard !suggestion.isEmpty else {
            clearInlineSuggestion()
            return
        }
        inlineSuggestion = suggestion
        inlineSuggestionLocation = location
        if inlineSuggestionView == nil {
            let label = NSTextField(labelWithString: suggestion)
            label.isBezeled = false
            label.isEditable = false
            label.isSelectable = false
            label.drawsBackground = false
            label.textColor = NSColor.secondaryLabelColor.withAlphaComponent(0.6)
            label.font = font ?? NSFont.monospacedSystemFont(ofSize: 13, weight: .regular)
            label.lineBreakMode = .byClipping
            label.maximumNumberOfLines = 1
            inlineSuggestionView = label
            addSubview(label)
        } else {
            inlineSuggestionView?.stringValue = suggestion
            inlineSuggestionView?.font = font ?? NSFont.monospacedSystemFont(ofSize: 13, weight: .regular)
        }
        updateInlineSuggestionPosition()
    }

    func clearInlineSuggestion() {
        inlineSuggestion = nil
        inlineSuggestionLocation = nil
        inlineSuggestionView?.removeFromSuperview()
        inlineSuggestionView = nil
    }

    private func acceptInlineSuggestion() -> Bool {
        guard let suggestion = inlineSuggestion,
              let loc = inlineSuggestionLocation else { return false }
        let sanitizedSuggestion = sanitizedPlainText(suggestion)
        guard !sanitizedSuggestion.isEmpty else {
            clearInlineSuggestion()
            return false
        }
        let sel = selectedRange()
        guard sel.length == 0, sel.location == loc else {
            clearInlineSuggestion()
            return false
        }
        isApplyingInlineSuggestion = true
        textStorage?.replaceCharacters(in: NSRange(location: loc, length: 0), with: sanitizedSuggestion)
        setSelectedRange(NSRange(location: loc + (sanitizedSuggestion as NSString).length, length: 0))
        isApplyingInlineSuggestion = false
        recentlyAcceptedInlineSuggestion = true
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak self] in
            self?.recentlyAcceptedInlineSuggestion = false
        }
        clearInlineSuggestion()
        return true
    }

    private func updateInlineSuggestionPosition() {
        guard let suggestion = inlineSuggestion,
              let loc = inlineSuggestionLocation,
              let label = inlineSuggestionView,
              let window else { return }
        let sel = selectedRange()
        if sel.location != loc || sel.length != 0 {
            clearInlineSuggestion()
            return
        }
        let rectInScreen = firstRect(forCharacterRange: NSRange(location: loc, length: 0), actualRange: nil)
        let rectInWindow = window.convertFromScreen(rectInScreen)
        let rectInView = convert(rectInWindow, from: nil)
        label.stringValue = suggestion
        label.sizeToFit()
        label.frame.origin = NSPoint(x: rectInView.origin.x, y: rectInView.origin.y)
    }

    // Re-apply the desired caret position over multiple runloop ticks to beat late layout/async work.
    private func schedulePasteCaretEnforcement() {
        guard pendingPasteCaretLocation != nil else { return }

        // Cancel previously queued enforcement to avoid spamming
        NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(applyPendingPasteCaret), object: nil)

        // Run next turn
        perform(#selector(applyPendingPasteCaret), with: nil, afterDelay: 0)

        // Run again next runloop tick (beats "snap back" from late async work)
        DispatchQueue.main.async { [weak self] in
            self?.applyPendingPasteCaret()
        }

        // Run once more with a tiny delay (beats slower async highlight passes)
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.02) { [weak self] in
            self?.applyPendingPasteCaret()
        }
    }

    private func cancelPendingPasteCaretEnforcement() {
        pendingPasteCaretLocation = nil
        NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(applyPendingPasteCaret), object: nil)
    }

    @objc private func applyPendingPasteCaret() {
        guard let desired = pendingPasteCaretLocation else { return }

        let length = (string as NSString).length
        let loc = min(max(0, desired), length)
        let range = NSRange(location: loc, length: 0)

        // Set caret and keep it visible
        setSelectedRange(range)

        if let container = textContainer {
            layoutManager?.ensureLayout(for: container)
        }
        scrollRangeToVisible(range)

        // Important: clear only after we've enforced at least once.
        // The delayed calls will no-op once this is nil.
        pendingPasteCaretLocation = nil
    }

    private func postVimModeState() {
        NotificationCenter.default.post(
            name: .vimModeStateDidChange,
            object: nil,
            userInfo: ["insertMode": isVimInsertMode]
        )
    }

    private func insertBracketHelperToken(_ token: String) {
        guard isEditable else { return }
        clearInlineSuggestion()
        let selection = selectedRange()

        let pairMap: [String: (String, String)] = [
            "()": ("(", ")"),
            "{}": ("{", "}"),
            "[]": ("[", "]"),
            "\"\"": ("\"", "\""),
            "''": ("'", "'")
        ]

        if let pair = pairMap[token] {
            let insertion = pair.0 + pair.1
            textStorage?.replaceCharacters(in: selection, with: insertion)
            setSelectedRange(NSRange(location: selection.location + (pair.0 as NSString).length, length: 0))
            didChangeText()
            return
        }

        textStorage?.replaceCharacters(in: selection, with: token)
        setSelectedRange(NSRange(location: selection.location + (token as NSString).length, length: 0))
        didChangeText()
    }

    private func scalarName(for value: UInt32) -> String {
        switch value {
        case 0x20: return "SPACE"
        case 0x09: return "TAB"
        case 0x0A: return "LF"
        case 0x0D: return "CR"
        case 0x2581: return "LOWER_ONE_EIGHTH_BLOCK"
        default: return "U+\(String(format: "%04X", value))"
        }
    }

    private func inspectWhitespaceScalarsAtCaret() {
        let ns = string as NSString
        let length = ns.length
        let caret = min(max(selectedRange().location, 0), max(length - 1, 0))
        let lineRange = ns.lineRange(for: NSRange(location: caret, length: 0))
        let line = ns.substring(with: lineRange)
        let lineOneBased = ns.substring(to: lineRange.location).reduce(1) { $1 == "\n" ? $0 + 1 : $0 }
        var counts: [UInt32: Int] = [:]
        for scalar in line.unicodeScalars {
            let value = scalar.value
            let isWhitespace = scalar.properties.generalCategory == .spaceSeparator || value == 0x20 || value == 0x09
            let isLineBreak = value == 0x0A || value == 0x0D
            let isControlPicture = (0x2400...0x243F).contains(value)
            let isLowBlock = value == 0x2581
            if isWhitespace || isLineBreak || isControlPicture || isLowBlock {
                counts[value, default: 0] += 1
            }
        }

        let header = "Line \(lineOneBased) at UTF16@\(selectedRange().location), whitespace scalars:"
        let body: String
        if counts.isEmpty {
            body = "none detected"
        } else {
            let rows = counts.keys.sorted().map { key in
                "\(scalarName(for: key)) x\(counts[key] ?? 0)"
            }
            body = rows.joined(separator: ", ")
        }

        let windowNumber = window?.windowNumber ?? -1
        NotificationCenter.default.post(
            name: .whitespaceScalarInspectionResult,
            object: nil,
            userInfo: [
                EditorCommandUserInfo.windowNumber: windowNumber,
                EditorCommandUserInfo.inspectionMessage: "\(header)\n\(body)"
            ]
        )
    }

    private func configureVimMode() {
        // Vim enabled starts in NORMAL; disabled uses regular insert typing.
        isVimInsertMode = !UserDefaults.standard.bool(forKey: vimModeDefaultsKey)
        postVimModeState()

        let observerRaw = NotificationCenter.default.addObserver(
            forName: .toggleVimModeRequested,
            object: nil,
            queue: .main
        ) { [weak self] _ in
            Task { @MainActor [weak self] in
                guard let self else { return }
                // Enter NORMAL when Vim mode is enabled; INSERT when disabled.
                let enabled = UserDefaults.standard.bool(forKey: self.vimModeDefaultsKey)
                self.isVimInsertMode = !enabled
                self.postVimModeState()
            }
        }
        let observer = TextViewObserverToken(raw: observerRaw)
        vimObservers.append(observer)

        let inspectorObserverRaw = NotificationCenter.default.addObserver(
            forName: .inspectWhitespaceScalarsRequested,
            object: nil,
            queue: .main
        ) { [weak self] notif in
            guard let self else { return }
            if let target = notif.userInfo?[EditorCommandUserInfo.windowNumber] as? Int,
               let own = self.window?.windowNumber,
               target != own {
                return
            }
            self.inspectWhitespaceScalarsAtCaret()
        }
        let inspectorObserver = TextViewObserverToken(raw: inspectorObserverRaw)
        vimObservers.append(inspectorObserver)

        let bracketHelperObserverRaw = NotificationCenter.default.addObserver(
            forName: .insertBracketHelperTokenRequested,
            object: nil,
            queue: .main
        ) { [weak self] notif in
            guard let self else { return }
            if let target = notif.userInfo?[EditorCommandUserInfo.windowNumber] as? Int,
               let own = self.window?.windowNumber,
               target != own {
                return
            }
            guard let token = notif.userInfo?[EditorCommandUserInfo.bracketToken] as? String else { return }
            self.insertBracketHelperToken(token)
        }
        let bracketHelperObserver = TextViewObserverToken(raw: bracketHelperObserverRaw)
        vimObservers.append(bracketHelperObserver)
    }

    private func trimTrailingWhitespaceIfEnabled() {
        let enabled = UserDefaults.standard.bool(forKey: "SettingsTrimTrailingWhitespace")
        guard enabled else { return }
        let original = self.string
        let lines = original.components(separatedBy: .newlines)
        var changed = false
        let trimmedLines = lines.map { line -> String in
            let trimmed = line.replacingOccurrences(of: #"[\t\x20]+$"#, with: "", options: .regularExpression)
            if trimmed != line { changed = true }
            return trimmed
        }
        guard changed else { return }
        let newString = trimmedLines.joined(separator: "\n")
        let oldSelected = self.selectedRange()
        self.textStorage?.beginEditing()
        self.string = newString
        self.textStorage?.endEditing()
        let newLoc = min(oldSelected.location, (newString as NSString).length)
        self.setSelectedRange(NSRange(location: newLoc, length: 0))
        self.didChangeText()
    }

}

// NSViewRepresentable wrapper around NSTextView to integrate with SwiftUI.
struct CustomTextEditor: NSViewRepresentable {
    @Binding var text: String
    let documentID: UUID?
    let externalEditRevision: Int
    let language: String
    let colorScheme: ColorScheme
    let fontSize: CGFloat
    @Binding var isLineWrapEnabled: Bool
    let isLargeFileMode: Bool
    let translucentBackgroundEnabled: Bool
    let showKeyboardAccessoryBar: Bool
    let showLineNumbers: Bool
    let showInvisibleCharacters: Bool
    let highlightCurrentLine: Bool
    let highlightMatchingBrackets: Bool
    let showScopeGuides: Bool
    let highlightScopeBackground: Bool
    let indentStyle: String
    let indentWidth: Int
    let autoIndentEnabled: Bool
    let autoCloseBracketsEnabled: Bool
    let highlightRefreshToken: Int
    let isTabLoadingContent: Bool
    let isReadOnly: Bool
    let onTextMutation: ((EditorTextMutation) -> Void)?

    private var fontName: String {
        UserDefaults.standard.string(forKey: "SettingsEditorFontName") ?? ""
    }

    private var useSystemFont: Bool {
        UserDefaults.standard.bool(forKey: "SettingsUseSystemFont")
    }

    private var lineHeightMultiple: CGFloat {
        let stored = UserDefaults.standard.double(forKey: "SettingsLineHeight")
        return CGFloat(stored > 0 ? stored : 1.0)
    }

    // Toggle soft-wrapping by adjusting text container sizing and scroller visibility.
    private func applyWrapMode(isWrapped: Bool, textView: NSTextView, scrollView: NSScrollView) {
        if isWrapped {
            // Wrap: track the text view width, no horizontal scrolling
            textView.isHorizontallyResizable = false
            textView.textContainer?.widthTracksTextView = true
            textView.textContainer?.heightTracksTextView = false
            scrollView.hasHorizontalScroller = false
            // Ensure the container width matches the visible content width right now
            let contentWidth = scrollView.contentSize.width
            let width = contentWidth > 0 ? contentWidth : scrollView.frame.size.width
            textView.textContainer?.containerSize = NSSize(width: width, height: CGFloat.greatestFiniteMagnitude)
        } else {
            // No wrap: allow horizontal expansion and horizontal scrolling
            textView.isHorizontallyResizable = true
            textView.textContainer?.widthTracksTextView = false
            textView.textContainer?.heightTracksTextView = false
            scrollView.hasHorizontalScroller = true
            textView.textContainer?.containerSize = NSSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
        }

        // Keep wrap-mode flips lightweight; avoid forcing a full invalidation pass.
        let textLength = (textView.string as NSString).length
        if textLength <= 300_000, let container = textView.textContainer, let lm = textView.layoutManager {
            lm.ensureLayout(for: container)
        }
    }

    private func resolvedFont() -> NSFont {
        if useSystemFont {
            return NSFont.systemFont(ofSize: fontSize)
        }
        if let named = NSFont(name: fontName, size: fontSize) {
            return named
        }
        return NSFont.monospacedSystemFont(ofSize: fontSize, weight: .regular)
    }

    private func paragraphStyle() -> NSParagraphStyle {
        let style = NSMutableParagraphStyle()
        style.lineHeightMultiple = max(0.9, lineHeightMultiple)
        return style
    }

    private func effectiveBaseTextColor() -> NSColor {
        let theme = currentEditorTheme(colorScheme: colorScheme)
        return NSColor(theme.text)
    }

    private func applyInvisibleCharacterPreference(_ textView: NSTextView) {
        // Keep layout manager and defaults in sync with the user-facing setting.
        let shouldShow = showInvisibleCharacters
        let defaults = UserDefaults.standard
        defaults.set(shouldShow, forKey: "NSShowAllInvisibles")
        defaults.set(shouldShow, forKey: "NSShowControlCharacters")
        defaults.set(shouldShow, forKey: "SettingsShowInvisibleCharacters")
        textView.layoutManager?.showsInvisibleCharacters = shouldShow
        textView.layoutManager?.showsControlCharacters = shouldShow
        if let storage = textView.textStorage {
            textView.layoutManager?.invalidateDisplay(forCharacterRange: NSRange(location: 0, length: storage.length))
        }
        textView.needsDisplay = true
    }

    private func sanitizedForExternalSet(_ input: String) -> String {
        let nsLength = (input as NSString).length
        if nsLength > 300_000 {
            if !input.contains("\0") && !input.contains("\r") {
                return input
            }
            return input
                .replacingOccurrences(of: "\0", with: "")
                .replacingOccurrences(of: "\r\n", with: "\n")
                .replacingOccurrences(of: "\r", with: "\n")
        }
        return AcceptingTextView.sanitizePlainText(input)
    }

    func makeNSView(context: Context) -> NSScrollView {
        // Build scroll view and text view
        let scrollView = NSScrollView()
        scrollView.drawsBackground = false
        scrollView.autohidesScrollers = true
        scrollView.hasVerticalScroller = true
        scrollView.contentView.postsBoundsChangedNotifications = true

        let textView = AcceptingTextView(frame: .zero)
        textView.identifier = NSUserInterfaceItemIdentifier("NeonEditorTextView")
        // Configure editing behavior and visuals
        textView.isEditable = !isReadOnly
        textView.isRichText = false
        textView.usesFindBar = !isLargeFileMode
        textView.usesInspectorBar = false
        textView.usesFontPanel = false
        textView.isVerticallyResizable = true
        textView.isHorizontallyResizable = false
        textView.font = resolvedFont()

        // Apply visibility preference from Settings (off by default).
        applyInvisibleCharacterPreference(textView)
        textView.textStorage?.beginEditing()
        if let storage = textView.textStorage {
            let fullRange = NSRange(location: 0, length: storage.length)
            storage.removeAttribute(.backgroundColor, range: fullRange)
            storage.removeAttribute(.underlineStyle, range: fullRange)
            storage.removeAttribute(.strikethroughStyle, range: fullRange)
        }
        textView.textStorage?.endEditing()

        let theme = currentEditorTheme(colorScheme: colorScheme)
        if translucentBackgroundEnabled {
            textView.backgroundColor = .clear
            textView.drawsBackground = false
        } else {
            textView.backgroundColor = NSColor(theme.background)
            textView.drawsBackground = true
        }

        // Use NSRulerView line numbering (v0.4.4-beta behavior).
        textView.minSize = NSSize(width: 0, height: 0)
        textView.maxSize = NSSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
        textView.isSelectable = true
        textView.allowsUndo = !isLargeFileMode
        let baseTextColor = effectiveBaseTextColor()
        textView.textColor = baseTextColor
        textView.insertionPointColor = NSColor(theme.cursor)
        textView.selectedTextAttributes = [
            .backgroundColor: resolvedSelectionColor(for: theme)
        ]
        textView.usesInspectorBar = false
        textView.usesFontPanel = false
        textView.layoutManager?.allowsNonContiguousLayout = true
        // Keep a fixed left gutter gap so content never visually collides with line numbers.
        textView.textContainerInset = NSSize(width: 6, height: 8)
        textView.textContainer?.lineFragmentPadding = 4

        // Keep horizontal rulers disabled; vertical ruler is dedicated to line numbers.
        let shouldShowInitialLineNumbers = showLineNumbers
        textView.usesRuler = shouldShowInitialLineNumbers
        textView.isRulerVisible = shouldShowInitialLineNumbers
        scrollView.hasHorizontalRuler = false
        scrollView.horizontalRulerView = nil
        scrollView.hasVerticalRuler = shouldShowInitialLineNumbers
        scrollView.rulersVisible = shouldShowInitialLineNumbers
        scrollView.verticalRulerView = shouldShowInitialLineNumbers ? LineNumberRulerView(textView: textView) : nil

        applyInvisibleCharacterPreference(textView)
        textView.autoIndentEnabled = autoIndentEnabled
        textView.autoCloseBracketsEnabled = autoCloseBracketsEnabled
        textView.emmetLanguage = language
        textView.indentStyle = indentStyle
        textView.indentWidth = indentWidth
        textView.highlightCurrentLine = highlightCurrentLine

        // Disable smart substitutions/detections that can interfere with selection when recoloring
        textView.isAutomaticTextCompletionEnabled = false
        textView.isAutomaticQuoteSubstitutionEnabled = false
        textView.isAutomaticDashSubstitutionEnabled = false
        textView.isAutomaticDataDetectionEnabled = false
        textView.isAutomaticLinkDetectionEnabled = false
        textView.isGrammarCheckingEnabled = false
        textView.isContinuousSpellCheckingEnabled = false
        textView.smartInsertDeleteEnabled = false
        if #available(macOS 15.0, *) {
            textView.writingToolsBehavior = .none
        }

        textView.registerForDraggedTypes([.fileURL, .URL])

        // Embed the text view in the scroll view
        scrollView.documentView = textView

        // Configure the text view delegate
        textView.delegate = context.coordinator

        // Apply wrapping and seed initial content
        applyWrapMode(isWrapped: isLineWrapEnabled && !isLargeFileMode, textView: textView, scrollView: scrollView)

        // Seed initial text (strip control pictures when invisibles are hidden)
        let seeded = sanitizedForExternalSet(text)
        let seededLength = (seeded as NSString).length
        if shouldUseChunkedLargeFileInstall(isLargeFileMode: isLargeFileMode, textLength: seededLength) {
            textView.string = ""
            DispatchQueue.main.async {
                _ = context.coordinator.installLargeTextIfNeeded(
                    on: textView,
                    target: seeded,
                    preserveViewport: false
                )
            }
        } else {
            textView.string = seeded
            if seeded != text {
                // Keep binding clean of control-picture glyphs.
                DispatchQueue.main.async {
                    if self.text != seeded {
                        self.text = seeded
                    }
                }
            }
            context.coordinator.scheduleHighlightIfNeeded(currentText: text, immediate: true)
        }

        // Keep container width in sync when the scroll view resizes (coalesced and guarded in coordinator).
        context.coordinator.installWrapResizeObserver(for: textView, scrollView: scrollView)

        context.coordinator.textView = textView
        return scrollView
    }

    // Keep NSTextView in sync with SwiftUI state and schedule highlighting when needed.
    func updateNSView(_ nsView: NSScrollView, context: Context) {
        if let textView = nsView.documentView as? NSTextView {
            var needsLayoutRefresh = false
            var didChangeRulerConfiguration = false
            textView.isEditable = !isReadOnly
            textView.isSelectable = true
            let acceptingView = textView as? AcceptingTextView
            let isDropApplyInFlight = acceptingView?.isApplyingDroppedContent ?? false
            context.coordinator.installWrapResizeObserver(for: textView, scrollView: nsView)
            let didSwitchDocument = context.coordinator.lastDocumentID != documentID
            let didFinishTabLoad = (context.coordinator.lastTabLoadingContent == true) && !isTabLoadingContent
            let didReceiveExternalEdit = context.coordinator.lastExternalEditRevision != externalEditRevision
            let didTransitionDocumentState = didSwitchDocument || didFinishTabLoad || didReceiveExternalEdit
            let isInteractionSuppressed = context.coordinator.isInInteractionSuppressionWindow()
            if didSwitchDocument {
                context.coordinator.lastDocumentID = documentID
                context.coordinator.cancelPendingBindingSync()
                context.coordinator.clearPendingTextMutation()
                context.coordinator.invalidateHighlightCache()
            }
            context.coordinator.lastTabLoadingContent = isTabLoadingContent
            context.coordinator.lastExternalEditRevision = externalEditRevision

            // Sanitize and avoid publishing binding during update
            let target = sanitizedForExternalSet(text)
            let targetLength = (target as NSString).length
            let shouldSkipLargeFileResync =
                isLargeFileMode &&
                targetLength >= EditorRuntimeLimits.syntaxMinimalUTF16Length &&
                !didSwitchDocument &&
                !didFinishTabLoad &&
                !didReceiveExternalEdit &&
                !context.coordinator.hasPendingBindingSync
            if textView.string != target {
                if !shouldSkipLargeFileResync {
                    let hasFocus = (textView.window?.firstResponder as? NSTextView) === textView
                    let shouldPreferEditorBuffer =
                        hasFocus &&
                        !isTabLoadingContent &&
                        !didSwitchDocument &&
                        !didFinishTabLoad &&
                        !didReceiveExternalEdit
                    let shouldDeferToEditorBuffer =
                        shouldPreferEditorBuffer ||
                        (!didTransitionDocumentState && isInteractionSuppressed)
                    if shouldDeferToEditorBuffer {
                        context.coordinator.syncBindingTextImmediately(textView.string)
                    } else {
                        context.coordinator.cancelPendingBindingSync()
                        let didInstallLargeText = context.coordinator.installLargeTextIfNeeded(
                            on: textView,
                            target: target,
                            preserveViewport: !didSwitchDocument,
                            preserveHorizontalOffset: !didTransitionDocumentState
                        )
                        if !didInstallLargeText {
                            replaceTextPreservingSelectionAndFocus(
                                textView,
                                with: target,
                                preserveViewport: !didSwitchDocument,
                                preserveHorizontalOffset: !didTransitionDocumentState
                            )
                            needsLayoutRefresh = true
                        }
                        context.coordinator.invalidateHighlightCache()
                        DispatchQueue.main.async {
                            if self.text != target {
                                self.text = target
                            }
                        }
                    }
                }
            }

            let targetFont = resolvedFont()
            let currentFont = textView.font
            let fontChanged = currentFont?.fontName != targetFont.fontName ||
                abs((currentFont?.pointSize ?? -1) - targetFont.pointSize) > 0.001
            if fontChanged {
                textView.font = targetFont
                needsLayoutRefresh = true
                context.coordinator.invalidateHighlightCache()
            }
            if textView.textContainerInset.width != 6 || textView.textContainerInset.height != 8 {
                textView.textContainerInset = NSSize(width: 6, height: 8)
                needsLayoutRefresh = true
            }
            if textView.textContainer?.lineFragmentPadding != 4 {
                textView.textContainer?.lineFragmentPadding = 4
                needsLayoutRefresh = true
            }
            let style = paragraphStyle()
            let currentLineHeight = textView.defaultParagraphStyle?.lineHeightMultiple ?? 1.0
            if abs(currentLineHeight - style.lineHeightMultiple) > 0.0001 {
                textView.defaultParagraphStyle = style
                textView.typingAttributes[.paragraphStyle] = style
                needsLayoutRefresh = true
                let nsLen = (textView.string as NSString).length
                if nsLen <= 200_000, let storage = textView.textStorage {
                    let undoWasEnabled = textView.undoManager?.isUndoRegistrationEnabled ?? false
                    if undoWasEnabled {
                        textView.undoManager?.disableUndoRegistration()
                    }
                    storage.beginEditing()
                    storage.addAttribute(.paragraphStyle, value: style, range: NSRange(location: 0, length: nsLen))
                    storage.endEditing()
                    if undoWasEnabled {
                        textView.undoManager?.enableUndoRegistration()
                    }
                }
            }

            // Defensive sanitize pass only for smaller documents to avoid heavy full-buffer scans.
            let currentLength = (textView.string as NSString).length
            if currentLength <= 300_000 {
                let sanitized = AcceptingTextView.sanitizePlainText(textView.string)
                if sanitized != textView.string, !isInteractionSuppressed {
                    replaceTextPreservingSelectionAndFocus(
                        textView,
                        with: sanitized,
                        preserveViewport: !didSwitchDocument,
                        preserveHorizontalOffset: !didTransitionDocumentState
                    )
                    needsLayoutRefresh = true
                    context.coordinator.invalidateHighlightCache()
                    DispatchQueue.main.async {
                        if self.text != sanitized {
                            self.text = sanitized
                        }
                    }
                }
            }

            let theme = currentEditorTheme(colorScheme: colorScheme)

            let effectiveHighlightCurrentLine = highlightCurrentLine
            let effectiveWrap = (isLineWrapEnabled && !isLargeFileMode)
            if #available(macOS 15.0, *) {
                if textView.writingToolsBehavior != .none {
                    textView.writingToolsBehavior = .none
                }
            }

            // Background color adjustments for translucency
            if translucentBackgroundEnabled {
                nsView.drawsBackground = false
                textView.backgroundColor = .clear
                textView.drawsBackground = false
            } else {
                nsView.drawsBackground = false
                textView.backgroundColor = NSColor(theme.background)
                textView.drawsBackground = true
            }
            let baseTextColor = effectiveBaseTextColor()
            let caretColor = NSColor(theme.cursor)
            if textView.insertionPointColor != caretColor {
                textView.insertionPointColor = caretColor
            }
            textView.typingAttributes[.foregroundColor] = baseTextColor
            textView.selectedTextAttributes = [
                .backgroundColor: resolvedSelectionColor(for: theme)
            ]
            let showLineNumbersByDefault = showLineNumbers
            if textView.usesRuler != showLineNumbersByDefault {
                textView.usesRuler = showLineNumbersByDefault
                didChangeRulerConfiguration = true
            }
            if textView.isRulerVisible != showLineNumbersByDefault {
                textView.isRulerVisible = showLineNumbersByDefault
                didChangeRulerConfiguration = true
            }
            if nsView.hasHorizontalRuler {
                nsView.hasHorizontalRuler = false
                didChangeRulerConfiguration = true
            }
            if nsView.horizontalRulerView != nil {
                nsView.horizontalRulerView = nil
                didChangeRulerConfiguration = true
            }
            if nsView.hasVerticalRuler != showLineNumbersByDefault {
                nsView.hasVerticalRuler = showLineNumbersByDefault
                didChangeRulerConfiguration = true
            }
            if nsView.rulersVisible != showLineNumbersByDefault {
                nsView.rulersVisible = showLineNumbersByDefault
                didChangeRulerConfiguration = true
            }
            if showLineNumbersByDefault {
                if !(nsView.verticalRulerView is LineNumberRulerView) {
                    nsView.verticalRulerView = LineNumberRulerView(textView: textView)
                    didChangeRulerConfiguration = true
                }
            } else {
                if nsView.verticalRulerView != nil {
                    nsView.verticalRulerView = nil
                    didChangeRulerConfiguration = true
                }
            }

            // Re-apply invisible-character visibility preference after style updates.
            applyInvisibleCharacterPreference(textView)

            // Keep the text container width in sync & relayout
            acceptingView?.autoIndentEnabled = autoIndentEnabled
            acceptingView?.autoCloseBracketsEnabled = autoCloseBracketsEnabled
            acceptingView?.emmetLanguage = language
            acceptingView?.indentStyle = indentStyle
            acceptingView?.indentWidth = indentWidth
            acceptingView?.highlightCurrentLine = effectiveHighlightCurrentLine
            if context.coordinator.lastAppliedWrapMode != effectiveWrap {
                applyWrapMode(isWrapped: effectiveWrap, textView: textView, scrollView: nsView)
                context.coordinator.lastAppliedWrapMode = effectiveWrap
                needsLayoutRefresh = true
            }

            if showLineNumbersByDefault && didTransitionDocumentState {
                if let ruler = nsView.verticalRulerView as? LineNumberRulerView {
                    ruler.forceRulerLayoutRefresh()
                } else {
                    context.coordinator.scheduleDeferredRulerTile(for: nsView)
                }
            } else if didChangeRulerConfiguration {
                context.coordinator.scheduleDeferredRulerTile(for: nsView)
            }
            if needsLayoutRefresh, let container = textView.textContainer {
                context.coordinator.scheduleDeferredEnsureLayout(for: textView, container: container)
            }
            if didTransitionDocumentState {
                context.coordinator.normalizeHorizontalScrollOffset(for: nsView)
            }

            // Only schedule highlight if needed (e.g., language/color scheme changes or external text updates)
            context.coordinator.parent = self

            if !isDropApplyInFlight {
                if didTransitionDocumentState {
                    context.coordinator.scheduleHighlightIfNeeded(currentText: textView.string, immediate: true)
                } else {
                    let shouldSchedule = context.coordinator.shouldScheduleHighlightFromUpdate(
                        currentText: textView.string,
                        language: language,
                        colorScheme: colorScheme,
                        lineHeightValue: lineHeightMultiple,
                        token: highlightRefreshToken,
                        translucencyEnabled: translucentBackgroundEnabled
                    )
                    if shouldSchedule {
                        context.coordinator.scheduleHighlightIfNeeded()
                    }
                }
            }
        }
    }

    private func resolvedSelectionColor(for theme: EditorTheme) -> NSColor {
        let base = NSColor(theme.selection)
        return base.blended(withFraction: colorScheme == .dark ? 0.18 : 0.12, of: .white) ?? base
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }


    // Coordinator: NSTextViewDelegate that bridges NSText changes to SwiftUI and manages highlighting.
    class Coordinator: NSObject, NSTextViewDelegate {
        var parent: CustomTextEditor
        weak var textView: NSTextView?

        // Background queue + debouncer for regex-based highlighting
        private let highlightQueue = DispatchQueue(label: "NeonVision.SyntaxHighlight", qos: .userInitiated)
        // Snapshots of last highlighted state to avoid redundant work
        private var pendingHighlight: DispatchWorkItem?
        private var lastHighlightedText: String = ""
        private var lastLanguage: String?
        private var lastColorScheme: ColorScheme?
        var lastLineHeight: CGFloat?
        private var lastHighlightToken: Int = 0
        private var lastSelectionLocation: Int = -1
        private var lastHighlightViewportAnchor: Int = -1
        private var lastTranslucencyEnabled: Bool?
        private var isApplyingHighlight = false
        private var highlightGeneration: Int = 0
        private var pendingEditedRange: NSRange?
        private var pendingBindingSync: DispatchWorkItem?
        private var pendingTextMutation: (range: NSRange, replacement: String)?
        private var pendingDeferredRulerTile = false
        private var pendingDeferredLayoutEnsure = false
        private var wrapResizeObserver: TextViewObserverToken?
        private weak var observedWrapContentView: NSClipView?
        private var lastObservedWrapContentWidth: CGFloat = -1
        private var isInstallingLargeText = false
        private var largeTextInstallGeneration: Int = 0
        private var interactionSuppressionDeadline: TimeInterval = 0
        var lastAppliedWrapMode: Bool?
        var lastDocumentID: UUID?
        var lastTabLoadingContent: Bool?
        var lastExternalEditRevision: Int?
        var hasPendingBindingSync: Bool { pendingBindingSync != nil }

        init(_ parent: CustomTextEditor) {
            self.parent = parent
            super.init()
            NotificationCenter.default.addObserver(self, selector: #selector(moveToLine(_:)), name: .moveCursorToLine, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(moveToRange(_:)), name: .moveCursorToRange, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(handlePointerInteraction(_:)), name: .editorPointerInteraction, object: nil)
        }

        deinit {
            if let wrapResizeObserver {
                NotificationCenter.default.removeObserver(wrapResizeObserver.raw)
            }
            NotificationCenter.default.removeObserver(self)
        }

        func invalidateHighlightCache() {
            lastHighlightedText = ""
            lastLanguage = nil
            lastColorScheme = nil
            lastLineHeight = nil
            lastHighlightToken = 0
            lastSelectionLocation = -1
            lastHighlightViewportAnchor = -1
            lastTranslucencyEnabled = nil
            largeTextInstallGeneration &+= 1
            isInstallingLargeText = false
        }

        private func syncBindingText(_ text: String, immediate: Bool = false) {
            if parent.isTabLoadingContent || isInstallingLargeText {
                return
            }
            pendingBindingSync?.cancel()
            pendingBindingSync = nil
            if immediate || (text as NSString).length < EditorRuntimeLimits.bindingDebounceUTF16Length {
                parent.text = text
                return
            }
            let work = DispatchWorkItem { [weak self] in
                guard let self else { return }
                self.pendingBindingSync = nil
                if self.textView?.string == text {
                    self.parent.text = text
                }
            }
            pendingBindingSync = work
            DispatchQueue.main.asyncAfter(deadline: .now() + EditorRuntimeLimits.bindingDebounceDelay, execute: work)
        }

        func cancelPendingBindingSync() {
            pendingBindingSync?.cancel()
            pendingBindingSync = nil
        }

        func clearPendingTextMutation() {
            pendingTextMutation = nil
            pendingEditedRange = nil
        }

        fileprivate func installLargeTextIfNeeded(
            on textView: NSTextView,
            target: String,
            preserveViewport: Bool,
            preserveHorizontalOffset: Bool = true
        ) -> Bool {
            guard parent.isLargeFileMode else { return false }
            let openMode = currentLargeFileOpenMode()
            guard openMode != .standard else { return false }
            let targetLength = (target as NSString).length
            guard targetLength >= EditorRuntimeLimits.syntaxMinimalUTF16Length else { return false }

            largeTextInstallGeneration &+= 1
            let generation = largeTextInstallGeneration
            isInstallingLargeText = true
            pendingHighlight?.cancel()
            pendingHighlight = nil

            let previousSelection = textView.selectedRange()
            let hadFocus = (textView.window?.firstResponder as? NSTextView) === textView
            let priorOrigin = textView.enclosingScrollView?.contentView.bounds.origin ?? .zero
            textView.isEditable = false
            textView.string = ""

            let nsTarget = target as NSString

            func applyChunk(from location: Int) {
                guard generation == self.largeTextInstallGeneration else { return }
                let remaining = targetLength - location
                guard remaining > 0 else {
                    self.isInstallingLargeText = false
                    textView.isEditable = !parent.isReadOnly
                    let safeLocation = min(max(0, previousSelection.location), targetLength)
                    let safeLength = min(max(0, previousSelection.length), max(0, targetLength - safeLocation))
                    textView.setSelectedRange(NSRange(location: safeLocation, length: safeLength))
                    if let clipView = textView.enclosingScrollView?.contentView {
                        let targetOrigin: CGPoint
                        if preserveViewport {
                            targetOrigin = CGPoint(
                                x: preserveHorizontalOffset ? priorOrigin.x : 0,
                                y: priorOrigin.y
                            )
                        } else {
                            targetOrigin = .zero
                        }
                        clipView.scroll(to: targetOrigin)
                        textView.enclosingScrollView?.reflectScrolledClipView(clipView)
                    }
                    if hadFocus {
                        textView.window?.makeFirstResponder(textView)
                    }
                    self.scheduleHighlightIfNeeded(currentText: target, immediate: true)
                    return
                }

                let chunkLength = min(LargeFileInstallRuntime.chunkUTF16, remaining)
                let chunk = nsTarget.substring(with: NSRange(location: location, length: chunkLength))
                textView.textStorage?.beginEditing()
                textView.textStorage?.append(NSAttributedString(string: chunk))
                textView.textStorage?.endEditing()
                DispatchQueue.main.async {
                    applyChunk(from: location + chunkLength)
                }
            }

            applyChunk(from: 0)
            return true
        }

        func normalizeHorizontalScrollOffset(for scrollView: NSScrollView) {
            let clipView = scrollView.contentView
            let origin = clipView.bounds.origin
            guard abs(origin.x) > 0.5 else { return }
            clipView.scroll(to: CGPoint(x: 0, y: origin.y))
            scrollView.reflectScrolledClipView(clipView)
        }

        private func debugViewportTrace(_ source: String, textView: NSTextView? = nil) {
#if DEBUG
            let tv = textView ?? self.textView
            let sel = tv?.selectedRange().location ?? -1
            let origin = tv?.enclosingScrollView?.contentView.bounds.origin ?? .zero
            print("[ViewportTrace] \(source) wrap=\(parent.isLineWrapEnabled) sel=\(sel) origin=(\(Int(origin.x)),\(Int(origin.y)))")
#endif
        }

        private func noteRecentInteraction(source: String, duration: TimeInterval = 0.24) {
            let now = ProcessInfo.processInfo.systemUptime
            interactionSuppressionDeadline = max(interactionSuppressionDeadline, now + duration)
            pendingHighlight?.cancel()
            pendingHighlight = nil
            highlightGeneration &+= 1
            debugViewportTrace("interaction:\(source)")
        }

        func isInInteractionSuppressionWindow() -> Bool {
            ProcessInfo.processInfo.systemUptime < interactionSuppressionDeadline
        }

        func shouldScheduleHighlightFromUpdate(
            currentText: String,
            language: String,
            colorScheme: ColorScheme,
            lineHeightValue: CGFloat,
            token: Int,
            translucencyEnabled: Bool
        ) -> Bool {
            let textLength = (currentText as NSString).length
            let viewportAnchor = currentViewportAnchor(
                textLength: textLength,
                language: language
            )
            if isInInteractionSuppressionWindow() {
                return false
            }
            if parent.isLargeFileMode && !supportsResponsiveLargeFileHighlight(language: language, textLength: textLength) {
                return false
            }
            return !(currentText == lastHighlightedText &&
                     language == lastLanguage &&
                     colorScheme == lastColorScheme &&
                     abs((lastLineHeight ?? lineHeightValue) - lineHeightValue) <= 0.0001 &&
                     token == lastHighlightToken &&
                     viewportAnchor == lastHighlightViewportAnchor &&
                     translucencyEnabled == lastTranslucencyEnabled)
        }

        private func currentViewportAnchor(textLength: Int, language: String) -> Int {
            guard let textView,
                  supportsResponsiveLargeFileHighlight(language: language, textLength: textLength),
                  textLength >= 100_000,
                  let layoutManager = textView.layoutManager,
                  let textContainer = textView.textContainer else { return -1 }
            let glyphRange = layoutManager.glyphRange(forBoundingRect: textView.visibleRect, in: textContainer)
            let charRange = layoutManager.characterRange(forGlyphRange: glyphRange, actualGlyphRange: nil)
            guard charRange.length > 0 else { return -1 }
            return charRange.location
        }

        func installWrapResizeObserver(for textView: NSTextView, scrollView: NSScrollView) {
            guard observedWrapContentView !== scrollView.contentView else { return }
            if let wrapResizeObserver {
                NotificationCenter.default.removeObserver(wrapResizeObserver.raw)
            }
            observedWrapContentView = scrollView.contentView
            lastObservedWrapContentWidth = -1
            let tokenRaw = NotificationCenter.default.addObserver(
                forName: NSView.boundsDidChangeNotification,
                object: scrollView.contentView,
                queue: .main
            ) { [weak self, weak textView, weak scrollView] _ in
                guard let self, let tv = textView, let sv = scrollView else { return }
                if tv.textContainer?.widthTracksTextView == true {
                    let targetWidth = sv.contentSize.width
                    guard targetWidth > 0 else { return }
                    if abs(self.lastObservedWrapContentWidth - targetWidth) > 0.5 {
                        self.lastObservedWrapContentWidth = targetWidth
                        let currentWidth = tv.textContainer?.containerSize.width ?? 0
                        if abs(currentWidth - targetWidth) > 0.5 {
                            tv.textContainer?.containerSize.width = targetWidth
                            self.debugViewportTrace("wrapWidthChanged", textView: tv)
                        }
                    }
                }
                let textLength = (tv.string as NSString).length
                if textLength >= 100_000 && supportsResponsiveLargeFileHighlight(language: self.parent.language, textLength: textLength) {
                    self.scheduleHighlightIfNeeded(currentText: tv.string)
                }
            }
            wrapResizeObserver = TextViewObserverToken(raw: tokenRaw)
        }

        @objc private func handlePointerInteraction(_ notification: Notification) {
            guard let interactedTextView = notification.object as? NSTextView else { return }
            guard let activeTextView = textView, interactedTextView === activeTextView else { return }
            noteRecentInteraction(source: "mouseDown")
        }

        func scheduleDeferredRulerTile(for scrollView: NSScrollView) {
            guard !pendingDeferredRulerTile else { return }
            pendingDeferredRulerTile = true
            DispatchQueue.main.async { [weak self, weak scrollView] in
                guard let self else { return }
                self.pendingDeferredRulerTile = false
                scrollView?.tile()
            }
        }

        func scheduleDeferredEnsureLayout(for textView: NSTextView, container: NSTextContainer) {
            guard !pendingDeferredLayoutEnsure else { return }
            pendingDeferredLayoutEnsure = true
            DispatchQueue.main.async { [weak self, weak textView] in
                guard let self else { return }
                self.pendingDeferredLayoutEnsure = false
                guard let textView else { return }
                textView.layoutManager?.ensureLayout(for: container)
            }
        }

        func syncBindingTextImmediately(_ text: String) {
            syncBindingText(text, immediate: true)
        }

        func textView(
            _ textView: NSTextView,
            shouldChangeTextIn affectedCharRange: NSRange,
            replacementString: String?
        ) -> Bool {
            EditorPerformanceMonitor.shared.markFirstKeystroke()
            guard !parent.isTabLoadingContent,
                  parent.documentID != nil,
                  let replacementString else {
                pendingTextMutation = nil
                return true
            }
            pendingTextMutation = (
                range: affectedCharRange,
                replacement: AcceptingTextView.sanitizePlainText(replacementString)
            )
            return true
        }

        func scheduleHighlightIfNeeded(currentText: String? = nil, immediate: Bool = false) {
            guard textView != nil else { return }

            // Query NSApp.modalWindow on the main thread to avoid thread-check warnings
            let isModalPresented: Bool = {
                if Thread.isMainThread {
                    return NSApp.modalWindow != nil
                } else {
                    var result = false
                    DispatchQueue.main.sync { result = (NSApp.modalWindow != nil) }
                    return result
                }
            }()

            if isModalPresented {
                pendingHighlight?.cancel()
                let work = DispatchWorkItem { [weak self] in
                    self?.scheduleHighlightIfNeeded(currentText: currentText)
                }
                pendingHighlight = work
                highlightQueue.asyncAfter(deadline: .now() + 0.3, execute: work)
                return
            }

            let lang = parent.language
            let scheme = parent.colorScheme
            let lineHeightValue: CGFloat = parent.lineHeightMultiple
            let token = parent.highlightRefreshToken
            let translucencyEnabled = parent.translucentBackgroundEnabled
            let selectionLocation: Int = {
                if Thread.isMainThread {
                    return textView?.selectedRange().location ?? 0
                }
                var result = 0
                DispatchQueue.main.sync {
                    result = textView?.selectedRange().location ?? 0
                }
                return result
            }()
            let text: String = {
                if let currentText = currentText {
                    return currentText
                }

                if Thread.isMainThread {
                    return textView?.string ?? ""
                }

                var result = ""
                DispatchQueue.main.sync {
                    result = textView?.string ?? ""
                }
                return result
            }()
            let textLength = (text as NSString).length
            let viewportAnchor = currentViewportAnchor(
                textLength: textLength,
                language: lang
            )

            if !immediate && isInInteractionSuppressionWindow() {
                lastSelectionLocation = selectionLocation
                debugViewportTrace("highlightSuppressedInteraction")
                return
            }

            if parent.isLargeFileMode && !supportsResponsiveLargeFileHighlight(language: lang, textLength: textLength) {
                self.lastHighlightedText = text
                self.lastLanguage = lang
                self.lastColorScheme = scheme
                self.lastLineHeight = lineHeightValue
                self.lastHighlightToken = token
                self.lastSelectionLocation = selectionLocation
                self.lastHighlightViewportAnchor = viewportAnchor
                self.lastTranslucencyEnabled = self.parent.translucentBackgroundEnabled
                return
            }
            if textLength >= EditorRuntimeLimits.syntaxMinimalUTF16Length &&
                !supportsResponsiveLargeFileHighlight(language: lang, textLength: textLength) {
                self.lastHighlightedText = text
                self.lastLanguage = lang
                self.lastColorScheme = scheme
                self.lastLineHeight = lineHeightValue
                self.lastHighlightToken = token
                self.lastSelectionLocation = selectionLocation
                self.lastHighlightViewportAnchor = viewportAnchor
                self.lastTranslucencyEnabled = self.parent.translucentBackgroundEnabled
                return
            }

            if text == lastHighlightedText &&
                lastLanguage == lang &&
                lastColorScheme == scheme &&
                lastLineHeight == lineHeightValue &&
                lastHighlightToken == token &&
                lastSelectionLocation == selectionLocation &&
                lastHighlightViewportAnchor == viewportAnchor &&
                lastTranslucencyEnabled == translucencyEnabled {
                return
            }
            let styleStateUnchanged = lang == lastLanguage &&
                scheme == lastColorScheme &&
                lastLineHeight == lineHeightValue &&
                lastHighlightToken == token &&
                lastTranslucencyEnabled == translucencyEnabled
            let selectionOnlyChange = text == lastHighlightedText &&
                styleStateUnchanged &&
                lastSelectionLocation != selectionLocation
            if selectionOnlyChange && (parent.isLineWrapEnabled || textLength >= EditorRuntimeLimits.cursorRehighlightMaxUTF16Length) {
                // Avoid running stale highlight work that can re-apply an outdated viewport in wrapped mode.
                pendingHighlight?.cancel()
                pendingHighlight = nil
                highlightGeneration &+= 1
                lastSelectionLocation = selectionLocation
                return
            }
            let incrementalRange: NSRange? = {
                guard token == lastHighlightToken,
                      lang == lastLanguage,
                      scheme == lastColorScheme,
                      !immediate,
                      let edit = pendingEditedRange else { return nil }
                let supportsLargeFileJSON = parent.isLargeFileMode && supportsResponsiveLargeFileHighlight(language: lang, textLength: textLength)
                if !supportsLargeFileJSON && text.utf16.count >= 120_000 {
                    return nil
                }
                let padding = supportsLargeFileJSON
                    ? EditorRuntimeLimits.largeFileJSONIncrementalPaddingUTF16
                    : 6_000
                return expandedHighlightRange(around: edit, in: text as NSString, maxUTF16Padding: padding)
            }()
            pendingEditedRange = nil
            let shouldRunImmediate = immediate || lastHighlightedText.isEmpty || lastHighlightToken != token
            highlightGeneration &+= 1
            let generation = highlightGeneration
            rehighlight(token: token, generation: generation, immediate: shouldRunImmediate, targetRange: incrementalRange)
        }

        private func expandedHighlightRange(around range: NSRange, in text: NSString, maxUTF16Padding: Int = 6000) -> NSRange {
            let start = max(0, range.location - maxUTF16Padding)
            let end = min(text.length, NSMaxRange(range) + maxUTF16Padding)
            let startLine = text.lineRange(for: NSRange(location: start, length: 0)).location
            let endAnchor = max(startLine, min(text.length - 1, max(0, end - 1)))
            let endLine = NSMaxRange(text.lineRange(for: NSRange(location: endAnchor, length: 0)))
            return NSRange(location: startLine, length: max(0, endLine - startLine))
        }

        private func preferredHighlightRange(
            in textView: NSTextView,
            text: NSString,
            explicitRange: NSRange?,
            immediate: Bool
        ) -> NSRange {
            let fullRange = NSRange(location: 0, length: text.length)
            if let explicitRange {
                return explicitRange
            }
            // Restrict to visible range only for responsive large-file profiles.
            let supportsResponsiveRange =
                parent.isLargeFileMode &&
                supportsResponsiveLargeFileHighlight(language: parent.language, textLength: text.length)
            guard supportsResponsiveRange, text.length >= 100_000 else { return fullRange }
            guard let layoutManager = textView.layoutManager,
                  let textContainer = textView.textContainer else { return fullRange }
            let visibleGlyphRange = layoutManager.glyphRange(forBoundingRect: textView.visibleRect, in: textContainer)
            let visibleCharacterRange = layoutManager.characterRange(forGlyphRange: visibleGlyphRange, actualGlyphRange: nil)
            guard visibleCharacterRange.length > 0 else { return fullRange }
            let padding = EditorRuntimeLimits.largeFileJSONVisiblePaddingUTF16
            return expandedHighlightRange(around: visibleCharacterRange, in: text, maxUTF16Padding: padding)
        }

        func rehighlight(token: Int, generation: Int, immediate: Bool = false, targetRange: NSRange? = nil) {
            if !Thread.isMainThread {
                DispatchQueue.main.async { [weak self] in
                    self?.rehighlight(token: token, generation: generation, immediate: immediate, targetRange: targetRange)
                }
                return
            }
            guard let textView = textView else { return }
            // Snapshot current state
            let textSnapshot = textView.string
            let language = parent.language
            let scheme = parent.colorScheme
            let lineHeightValue: CGFloat = parent.lineHeightMultiple
            let selected = textView.selectedRange()
            let theme = currentEditorTheme(colorScheme: scheme)
            let nsText = textSnapshot as NSString
            let syntaxProfile = syntaxProfile(for: language, text: nsText)
            let colors = SyntaxColors(
                keyword: theme.syntax.keyword,
                string: theme.syntax.string,
                number: theme.syntax.number,
                comment: theme.syntax.comment,
                attribute: theme.syntax.attribute,
                variable: theme.syntax.variable,
                def: theme.syntax.def,
                property: theme.syntax.property,
                meta: theme.syntax.meta,
                tag: theme.syntax.tag,
                atom: theme.syntax.atom,
                builtin: theme.syntax.builtin,
                type: theme.syntax.type
            )
            let patterns = getSyntaxPatterns(for: language, colors: colors, profile: syntaxProfile)
            let fullRange = NSRange(location: 0, length: nsText.length)
            let applyRange = preferredHighlightRange(
                in: textView,
                text: nsText,
                explicitRange: targetRange,
                immediate: immediate
            )
            let emphasisPatterns = syntaxEmphasisPatterns(for: language, profile: syntaxProfile)

            // Cancel any in-flight work
            pendingHighlight?.cancel()

            let work = DispatchWorkItem { [weak self] in
                let interval = syntaxHighlightSignposter.beginInterval("rehighlight_macos")
                // Compute matches off the main thread
                var coloredRanges: [(NSRange, Color)] = []
                var emphasizedRanges: [(NSRange, SyntaxFontEmphasis)] = []
                if let fastRanges = fastSyntaxColorRanges(
                    language: language,
                    profile: syntaxProfile,
                    text: nsText,
                    in: applyRange,
                    colors: colors
                ) {
                    coloredRanges = fastRanges
                } else {
                    for (pattern, color) in patterns {
                        guard let regex = cachedSyntaxRegex(pattern: pattern, options: [.anchorsMatchLines]) else { continue }
                        let matches = regex.matches(in: textSnapshot, range: applyRange)
                        for match in matches {
                            coloredRanges.append((match.range, color))
                        }
                    }
                }

                if theme.boldKeywords {
                    for pattern in emphasisPatterns.keyword {
                        guard let regex = cachedSyntaxRegex(pattern: pattern, options: [.anchorsMatchLines]) else { continue }
                        let matches = regex.matches(in: textSnapshot, range: applyRange)
                        for match in matches {
                            emphasizedRanges.append((match.range, .keyword))
                        }
                    }
                }
                if theme.italicComments {
                    for pattern in emphasisPatterns.comment {
                        guard let regex = cachedSyntaxRegex(pattern: pattern, options: [.anchorsMatchLines]) else { continue }
                        let matches = regex.matches(in: textSnapshot, range: applyRange)
                        for match in matches {
                            emphasizedRanges.append((match.range, .comment))
                        }
                    }
                }

                DispatchQueue.main.async { [weak self] in
                    guard let self = self, let tv = self.textView else {
                        syntaxHighlightSignposter.endInterval("rehighlight_macos", interval)
                        return
                    }
                    defer { syntaxHighlightSignposter.endInterval("rehighlight_macos", interval) }
                    guard generation == self.highlightGeneration else { return }
                    // Discard if text changed since we started
                    guard tv.string == textSnapshot else { return }
                    let viewportAnchor = self.currentViewportAnchor(
                        textLength: nsText.length,
                        language: language
                    )
                    let baseColor = self.parent.effectiveBaseTextColor()
                    let priorSelectedRange = tv.selectedRange()
                    let selectionBeforeApply = priorSelectedRange
                    self.isApplyingHighlight = true
                    defer { self.isApplyingHighlight = false }
                    let undoWasEnabled = tv.undoManager?.isUndoRegistrationEnabled ?? false
                    if undoWasEnabled {
                        tv.undoManager?.disableUndoRegistration()
                    }
                    defer {
                        if undoWasEnabled {
                            tv.undoManager?.enableUndoRegistration()
                        }
                    }

                    tv.textStorage?.beginEditing()
                    tv.textStorage?.removeAttribute(.foregroundColor, range: applyRange)
                    tv.textStorage?.removeAttribute(.backgroundColor, range: applyRange)
                    tv.textStorage?.removeAttribute(.underlineStyle, range: applyRange)
                    tv.textStorage?.removeAttribute(.font, range: applyRange)
                    tv.textStorage?.addAttribute(.foregroundColor, value: baseColor, range: applyRange)
                    let baseFont = self.parent.resolvedFont()
                    tv.textStorage?.addAttribute(.font, value: baseFont, range: applyRange)
                    let boldKeywordFont = fontWithSymbolicTrait(baseFont, trait: .bold)
                    let italicCommentFont = fontWithSymbolicTrait(baseFont, trait: .italic)
                    // Apply colored ranges
                    for (range, color) in coloredRanges {
                        tv.textStorage?.addAttribute(.foregroundColor, value: NSColor(color), range: range)
                    }
                    for (range, emphasis) in emphasizedRanges {
                        let font: NSFont
                        switch emphasis {
                        case .keyword:
                            font = boldKeywordFont
                        case .comment:
                            font = italicCommentFont
                        }
                        tv.textStorage?.addAttribute(.font, value: font, range: range)
                    }

                    let nsTextMain = textSnapshot as NSString
                    let selectedLocation = min(max(0, selected.location), max(0, fullRange.length))
                    let suppressLargeFileExtras = self.parent.isLargeFileMode
                    let wantsBracketTokens = self.parent.highlightMatchingBrackets && !suppressLargeFileExtras
                    let wantsScopeBackground = self.parent.highlightScopeBackground && !suppressLargeFileExtras
                    let wantsScopeGuides = self.parent.showScopeGuides && !suppressLargeFileExtras && !self.parent.isLineWrapEnabled && self.parent.language.lowercased() != "swift"
                    let needsScopeComputation = (wantsBracketTokens || wantsScopeBackground || wantsScopeGuides)
                        && nsTextMain.length < EditorRuntimeLimits.scopeComputationMaxUTF16Length
                    let bracketMatch = needsScopeComputation ? computeBracketScopeMatch(text: textSnapshot, caretLocation: selectedLocation) : nil
                    let indentationMatch: IndentationScopeMatch? = {
                        guard needsScopeComputation, supportsIndentationScopes(language: self.parent.language) else { return nil }
                        return computeIndentationScopeMatch(text: textSnapshot, caretLocation: selectedLocation)
                    }()

                    if wantsBracketTokens, let match = bracketMatch {
                        let textLength = fullRange.length
                        let tokenColor = NSColor.systemOrange
                        if isValidRange(match.openRange, utf16Length: textLength) {
                            tv.textStorage?.addAttribute(.foregroundColor, value: tokenColor, range: match.openRange)
                            tv.textStorage?.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: match.openRange)
                            tv.textStorage?.addAttribute(.backgroundColor, value: NSColor.systemOrange.withAlphaComponent(0.22), range: match.openRange)
                        }
                        if isValidRange(match.closeRange, utf16Length: textLength) {
                            tv.textStorage?.addAttribute(.foregroundColor, value: tokenColor, range: match.closeRange)
                            tv.textStorage?.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: match.closeRange)
                            tv.textStorage?.addAttribute(.backgroundColor, value: NSColor.systemOrange.withAlphaComponent(0.22), range: match.closeRange)
                        }
                    }

                    if wantsScopeBackground || wantsScopeGuides {
                        let textLength = fullRange.length
                        let scopeRange = bracketMatch?.scopeRange ?? indentationMatch?.scopeRange
                        let guideRanges = bracketMatch?.guideMarkerRanges ?? indentationMatch?.guideMarkerRanges ?? []

                        if wantsScopeBackground, let scope = scopeRange, isValidRange(scope, utf16Length: textLength) {
                            tv.textStorage?.addAttribute(.backgroundColor, value: NSColor.systemOrange.withAlphaComponent(0.18), range: scope)
                        }

                        if wantsScopeGuides {
                            for marker in guideRanges {
                                if isValidRange(marker, utf16Length: textLength) {
                                    tv.textStorage?.addAttribute(.backgroundColor, value: NSColor.systemBlue.withAlphaComponent(0.36), range: marker)
                                }
                            }
                        }
                    }

                    if self.parent.highlightCurrentLine && !suppressLargeFileExtras {
                        let caret = NSRange(location: selectedLocation, length: 0)
                        let lineRange = nsTextMain.lineRange(for: caret)
                        tv.textStorage?.addAttribute(.backgroundColor, value: NSColor.selectedTextBackgroundColor.withAlphaComponent(0.12), range: lineRange)
                    }
                    tv.textStorage?.endEditing()
                    let textLength = (tv.string as NSString).length
                    let safeLocation = min(max(0, priorSelectedRange.location), textLength)
                    let safeLength = min(max(0, priorSelectedRange.length), max(0, textLength - safeLocation))
                    let safeRange = NSRange(location: safeLocation, length: safeLength)
                    let currentRange = tv.selectedRange()
                    let selectionUnchangedDuringApply =
                        currentRange.location == selectionBeforeApply.location &&
                        currentRange.length == selectionBeforeApply.length
                    if selectionUnchangedDuringApply &&
                        (currentRange.location != safeRange.location || currentRange.length != safeRange.length) {
                        tv.setSelectedRange(safeRange)
                    }
                    tv.typingAttributes[.foregroundColor] = baseColor

                    self.parent.applyInvisibleCharacterPreference(tv)

                    // Update last highlighted state
                    self.lastHighlightedText = textSnapshot
                    self.lastLanguage = language
                    self.lastColorScheme = scheme
                    self.lastLineHeight = lineHeightValue
                    self.lastHighlightToken = token
                    self.lastSelectionLocation = selectedLocation
                    self.lastHighlightViewportAnchor = viewportAnchor
                    self.lastTranslucencyEnabled = self.parent.translucentBackgroundEnabled
                }
            }

            pendingHighlight = work
            // Run immediately on first paint/explicit refresh, debounce while typing.
            if immediate {
                highlightQueue.async(execute: work)
            } else {
                let delay: TimeInterval
                if targetRange != nil {
                    delay = 0.08
                } else if textSnapshot.utf16.count >= 120_000 {
                    delay = 0.22
                } else {
                    delay = 0.12
                }
                highlightQueue.asyncAfter(deadline: .now() + delay, execute: work)
            }
        }

        func textDidChange(_ notification: Notification) {
            guard let textView = notification.object as? NSTextView else { return }
            if let accepting = textView as? AcceptingTextView, accepting.isApplyingDroppedContent {
                // Drop-import chunking mutates storage many times; defer expensive binding/highlight work
                // until the final didChangeText emitted after import completion.
                return
            }
            let currentText = textView.string
            let currentLength = (currentText as NSString).length
            let sanitized: String
            if currentLength > 300_000 {
                // Fast path while editing very large files.
                if currentText.contains("\0") || currentText.contains("\r") {
                    sanitized = currentText
                        .replacingOccurrences(of: "\0", with: "")
                        .replacingOccurrences(of: "\r\n", with: "\n")
                        .replacingOccurrences(of: "\r", with: "\n")
                } else {
                    sanitized = currentText
                }
            } else {
                sanitized = AcceptingTextView.sanitizePlainText(currentText)
            }
            if sanitized != currentText {
                pendingTextMutation = nil
                replaceTextPreservingSelectionAndFocus(textView, with: sanitized)
            }
            let normalizedStyle = NSMutableParagraphStyle()
            normalizedStyle.lineHeightMultiple = max(0.9, parent.lineHeightMultiple)
            textView.defaultParagraphStyle = normalizedStyle
            textView.typingAttributes[.paragraphStyle] = normalizedStyle
            if let storage = textView.textStorage {
                let len = storage.length
                if len <= 200_000 {
                    let undoWasEnabled = textView.undoManager?.isUndoRegistrationEnabled ?? false
                    if undoWasEnabled {
                        textView.undoManager?.disableUndoRegistration()
                    }
                    storage.beginEditing()
                    storage.addAttribute(.paragraphStyle, value: normalizedStyle, range: NSRange(location: 0, length: len))
                    storage.endEditing()
                    if undoWasEnabled {
                        textView.undoManager?.enableUndoRegistration()
                    }
                }
            }
            let didApplyIncrementalMutation = applyPendingTextMutationIfPossible()
            if !didApplyIncrementalMutation {
                syncBindingText(sanitized)
            }
            parent.applyInvisibleCharacterPreference(textView)
            if let accepting = textView as? AcceptingTextView, accepting.isApplyingPaste {
                parent.applyInvisibleCharacterPreference(textView)
                let snapshot = textView.string
                highlightQueue.asyncAfter(deadline: .now() + 0.2) { [weak self] in
                    DispatchQueue.main.async {
                        self?.syncBindingText(snapshot, immediate: true)
                        self?.scheduleHighlightIfNeeded(currentText: snapshot)
                    }
                }
                return
            }
            parent.applyInvisibleCharacterPreference(textView)
            // Update SwiftUI binding, caret status, and rehighlight.
            let nsText = textView.string as NSString
            let caretLocation = min(nsText.length, textView.selectedRange().location)
            pendingEditedRange = nsText.lineRange(for: NSRange(location: caretLocation, length: 0))
            updateCaretStatusAndHighlight(triggerHighlight: false)
            scheduleHighlightIfNeeded(currentText: sanitized)
        }

        private func applyPendingTextMutationIfPossible() -> Bool {
            defer { pendingTextMutation = nil }
            guard !parent.isTabLoadingContent,
                  let pendingTextMutation,
                  let documentID = parent.documentID,
                  let onTextMutation = parent.onTextMutation else {
                return false
            }
            onTextMutation(
                EditorTextMutation(
                    documentID: documentID,
                    range: pendingTextMutation.range,
                    replacement: pendingTextMutation.replacement
                )
            )
            return true
        }

        func textViewDidChangeSelection(_ notification: Notification) {
            if isApplyingHighlight { return }
            if let tv = notification.object as? AcceptingTextView {
                tv.clearInlineSuggestion()
                if let eventType = tv.window?.currentEvent?.type,
                   eventType == .leftMouseDown || eventType == .leftMouseDragged || eventType == .leftMouseUp {
                    noteRecentInteraction(source: "selection")
                }
                publishSelectionSnapshot(from: tv.string as NSString, selectedRange: tv.selectedRange())
            }
            updateCaretStatusAndHighlight(triggerHighlight: !parent.isLineWrapEnabled)
        }

        func textView(_ textView: NSTextView, menu: NSMenu, for event: NSEvent, at charIndex: Int) -> NSMenu? {
            let selectedRange = textView.selectedRange()
            guard selectedRange.location != NSNotFound,
                  selectedRange.length > 0 else {
                return menu
            }
            let snapshotItem = NSMenuItem(
                title: "Create Code Snapshot",
                action: #selector(createCodeSnapshotFromContextMenu(_:)),
                keyEquivalent: ""
            )
            snapshotItem.target = self
            snapshotItem.image = NSImage(systemSymbolName: "camera.viewfinder", accessibilityDescription: "Create Code Snapshot")
            menu.addItem(.separator())
            menu.addItem(snapshotItem)
            return menu
        }

        @objc private func createCodeSnapshotFromContextMenu(_ sender: Any?) {
            guard let tv = textView else { return }
            let ns = tv.string as NSString
            let selectedRange = tv.selectedRange()
            guard selectedRange.location != NSNotFound,
                  selectedRange.length > 0,
                  NSMaxRange(selectedRange) <= ns.length else { return }
            publishSelectionSnapshot(from: ns, selectedRange: selectedRange)
            NotificationCenter.default.post(name: .editorRequestCodeSnapshotFromSelection, object: nil)
        }

        private func publishSelectionSnapshot(from text: NSString, selectedRange: NSRange) {
            guard selectedRange.location != NSNotFound,
                  selectedRange.length > 0,
                  NSMaxRange(selectedRange) <= text.length else {
                NotificationCenter.default.post(name: .editorSelectionDidChange, object: "")
                return
            }
            let cappedLength = min(selectedRange.length, 20_000)
            let snippet = text.substring(with: NSRange(location: selectedRange.location, length: cappedLength))
            NotificationCenter.default.post(name: .editorSelectionDidChange, object: snippet)
        }

        // Compute (line, column), broadcast, and highlight the current line.
        private func updateCaretStatusAndHighlight(triggerHighlight: Bool = true) {
            guard let tv = textView else { return }
            let ns = tv.string as NSString
            let sel = tv.selectedRange()
            let location = sel.location
            if parent.isLargeFileMode || ns.length > 300_000 {
                NotificationCenter.default.post(
                    name: .caretPositionDidChange,
                    object: nil,
                    userInfo: ["line": 0, "column": location, "location": location]
                )
                return
            }
            let prefix = ns.substring(to: min(location, ns.length))
            let line = prefix.reduce(1) { $1 == "\n" ? $0 + 1 : $0 }
            let col: Int = {
                if let lastNL = prefix.lastIndex(of: "\n") {
                    return prefix.distance(from: lastNL, to: prefix.endIndex) - 1
                } else {
                    return prefix.count
                }
            }()
            NotificationCenter.default.post(
                name: .caretPositionDidChange,
                object: nil,
                userInfo: ["line": line, "column": col, "location": location]
            )
            if triggerHighlight {
                // For very large files, avoid immediate full caret-triggered passes to keep UI responsive.
                let immediateHighlight = ns.length < 200_000
                scheduleHighlightIfNeeded(currentText: tv.string, immediate: immediateHighlight)
            }
        }

        @objc func moveToLine(_ notification: Notification) {
            if let targetWindow = notification.userInfo?[EditorCommandUserInfo.windowNumber] as? Int,
               let ownWindow = textView?.window?.windowNumber,
               targetWindow != ownWindow {
                return
            }
            guard let lineOneBased = notification.object as? Int,
                  let textView = textView else { return }

            // If there's no text, nothing to do
            let currentText = textView.string
            guard !currentText.isEmpty else { return }

            // Cancel any in-flight highlight to prevent it from restoring an old selection
            pendingHighlight?.cancel()

            // Work with NSString/UTF-16 indices to match NSTextView expectations
            let ns = currentText as NSString
            let totalLength = ns.length

            // Clamp target line to available line count (1-based input)
            let linesArray = currentText.components(separatedBy: .newlines)
            let clampedLineIndex = max(1, min(lineOneBased, linesArray.count)) - 1 // 0-based index

            // Compute the UTF-16 location by summing UTF-16 lengths of preceding lines + newline characters
            var location = 0
            if clampedLineIndex > 0 {
                for i in 0..<(clampedLineIndex) {
                    let lineNSString = linesArray[i] as NSString
                    location += lineNSString.length
                    // Add one for the newline that separates lines, as components(separatedBy:) drops separators
                    location += 1
                }
            }
            // Safety clamp
            location = max(0, min(location, totalLength))

            // Move caret and scroll into view on the main thread
            DispatchQueue.main.async { [weak self] in
                guard let self = self, let tv = self.textView else { return }
                tv.window?.makeFirstResponder(tv)
                // Ensure layout is up-to-date before scrolling
                if let textContainer = tv.textContainer {
                    tv.layoutManager?.ensureLayout(for: textContainer)
                }
                tv.setSelectedRange(NSRange(location: location, length: 0))
                tv.scrollRangeToVisible(NSRange(location: location, length: 0))

                self.scheduleHighlightIfNeeded(currentText: tv.string, immediate: true)
            }
        }

        @objc func moveToRange(_ notification: Notification) {
            if let targetWindow = notification.userInfo?[EditorCommandUserInfo.windowNumber] as? Int,
               let ownWindow = textView?.window?.windowNumber,
               targetWindow != ownWindow {
                return
            }
            guard let textView = textView else { return }
            guard let location = notification.userInfo?[EditorCommandUserInfo.rangeLocation] as? Int,
                  let length = notification.userInfo?[EditorCommandUserInfo.rangeLength] as? Int else { return }
            let textLength = (textView.string as NSString).length
            guard location >= 0, length >= 0, location + length <= textLength else { return }

            let range = NSRange(location: location, length: length)
            pendingHighlight?.cancel()
            textView.window?.makeFirstResponder(textView)
            if let textContainer = textView.textContainer {
                textView.layoutManager?.ensureLayout(for: textContainer)
            }
            textView.setSelectedRange(range)
            textView.scrollRangeToVisible(range)
            scheduleHighlightIfNeeded(currentText: textView.string, immediate: true)
        }
    }
}
#else
import UIKit

final class EditorInputTextView: UITextView {
    private let vimModeDefaultsKey = "EditorVimModeEnabled"
    private let vimInterceptionDefaultsKey = "EditorVimInterceptionEnabled"
    private let bracketTokens: [String] = ["(", ")", "{", "}", "[", "]", "<", ">", "'", "\"", "`", "()", "{}", "[]", "\"\"", "''"]
    private var isVimInsertMode: Bool = true
    private var pendingDeleteCurrentLineCommand = false

    private lazy var bracketAccessoryView: UIView = {
        let host = UIView()
        host.backgroundColor = UIColor.secondarySystemBackground.withAlphaComponent(0.95)
        host.translatesAutoresizingMaskIntoConstraints = false

        let scroll = UIScrollView()
        scroll.showsHorizontalScrollIndicator = false
        scroll.translatesAutoresizingMaskIntoConstraints = false

        let stack = UIStackView()
        stack.axis = .horizontal
        stack.spacing = 8
        stack.alignment = .center
        stack.translatesAutoresizingMaskIntoConstraints = false

        for token in bracketTokens {
            let button = UIButton(type: .system)
            button.titleLabel?.font = UIFont.monospacedSystemFont(ofSize: 15, weight: .semibold)
            button.accessibilityIdentifier = token
            if #available(iOS 15.0, *) {
                var config = UIButton.Configuration.plain()
                config.title = token
                config.baseForegroundColor = .label
                config.contentInsets = NSDirectionalEdgeInsets(top: 6, leading: 10, bottom: 6, trailing: 10)
                config.background.cornerRadius = 8
                config.background.backgroundColor = UIColor.systemBlue.withAlphaComponent(0.14)
                button.configuration = config
            } else {
                button.setTitle(token, for: .normal)
                button.setTitleColor(.label, for: .normal)
                button.contentEdgeInsets = UIEdgeInsets(top: 6, left: 10, bottom: 6, right: 10)
            }
            button.tintColor = .label
            button.layer.cornerRadius = 8
            button.layer.masksToBounds = true
            button.backgroundColor = UIColor.systemBlue.withAlphaComponent(0.14)
            button.addTarget(self, action: #selector(insertBracketToken(_:)), for: .touchUpInside)
            stack.addArrangedSubview(button)
        }

        host.addSubview(scroll)
        scroll.addSubview(stack)

        NSLayoutConstraint.activate([
            host.heightAnchor.constraint(equalToConstant: 46),

            scroll.leadingAnchor.constraint(equalTo: host.leadingAnchor, constant: 10),
            scroll.trailingAnchor.constraint(equalTo: host.trailingAnchor, constant: -10),
            scroll.topAnchor.constraint(equalTo: host.topAnchor, constant: 6),
            scroll.bottomAnchor.constraint(equalTo: host.bottomAnchor, constant: -6),

            stack.leadingAnchor.constraint(equalTo: scroll.contentLayoutGuide.leadingAnchor),
            stack.trailingAnchor.constraint(equalTo: scroll.contentLayoutGuide.trailingAnchor),
            stack.topAnchor.constraint(equalTo: scroll.contentLayoutGuide.topAnchor),
            stack.bottomAnchor.constraint(equalTo: scroll.contentLayoutGuide.bottomAnchor),
            stack.heightAnchor.constraint(equalTo: scroll.frameLayoutGuide.heightAnchor)
        ])

        return host
    }()
    private var isBracketAccessoryVisible: Bool = true

    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        inputAccessoryView = bracketAccessoryView
        syncVimModeFromDefaults()
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleVimModeStateDidChange(_:)),
            name: .vimModeStateDidChange,
            object: nil
        )
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        inputAccessoryView = bracketAccessoryView
        syncVimModeFromDefaults()
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleVimModeStateDidChange(_:)),
            name: .vimModeStateDidChange,
            object: nil
        )
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    func setBracketAccessoryVisible(_ visible: Bool) {
        guard isBracketAccessoryVisible != visible else { return }
        isBracketAccessoryVisible = visible
        inputAccessoryView = visible ? bracketAccessoryView : nil
        if isFirstResponder {
            reloadInputViews()
        }
    }

    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        if action == #selector(paste(_:)) {
            return isEditable && (UIPasteboard.general.hasStrings || UIPasteboard.general.hasURLs)
        }
        return super.canPerformAction(action, withSender: sender)
    }

    override var keyCommands: [UIKeyCommand]? {
        guard UIDevice.current.userInterfaceIdiom == .pad else { return super.keyCommands }
        guard UserDefaults.standard.bool(forKey: vimInterceptionDefaultsKey),
              UserDefaults.standard.bool(forKey: vimModeDefaultsKey) else {
            return super.keyCommands
        }

        var commands = super.keyCommands ?? []
        if isVimInsertMode {
            commands.append(vimCommand(input: UIKeyCommand.inputEscape, action: #selector(vimEscapeToNormalMode), title: "Vim: Normal Mode"))
            return commands
        }

        commands.append(vimCommand(input: "h", action: #selector(vimMoveLeft), title: "Vim: Move Left"))
        commands.append(vimCommand(input: "j", action: #selector(vimMoveDown), title: "Vim: Move Down"))
        commands.append(vimCommand(input: "k", action: #selector(vimMoveUp), title: "Vim: Move Up"))
        commands.append(vimCommand(input: "l", action: #selector(vimMoveRight), title: "Vim: Move Right"))
        commands.append(vimCommand(input: "w", action: #selector(vimMoveWordForward), title: "Vim: Next Word"))
        commands.append(vimCommand(input: "b", action: #selector(vimMoveWordBackward), title: "Vim: Previous Word"))
        commands.append(vimCommand(input: "0", action: #selector(vimMoveToLineStart), title: "Vim: Line Start"))
        commands.append(vimCommand(input: UIKeyCommand.inputEscape, action: #selector(vimEscapeToNormalMode), title: "Vim: Stay in Normal Mode"))
        commands.append(vimCommand(input: "x", action: #selector(vimDeleteForward), title: "Vim: Delete Character"))
        commands.append(vimCommand(input: "i", action: #selector(vimEnterInsertMode), title: "Vim: Insert Mode"))
        commands.append(vimCommand(input: "a", action: #selector(vimAppendInsertMode), title: "Vim: Append Mode"))
        commands.append(vimCommand(input: "d", action: #selector(vimDeleteLineStep), title: "Vim: Delete Line"))
        commands.append(vimCommand(input: "$", modifiers: [.shift], action: #selector(vimMoveToLineEnd), title: "Vim: Line End"))
        return commands
    }

    override func paste(_ sender: Any?) {
        // Force plain-text fallback so simulator/device paste remains reliable
        // even when the pasteboard advertises rich content first.
        if let raw = UIPasteboard.general.string, !raw.isEmpty {
            let sanitized = EditorTextSanitizer.sanitize(raw)
            if let selection = selectedTextRange {
                replace(selection, withText: sanitized)
            } else {
                insertText(sanitized)
            }
            DispatchQueue.main.async { [weak self] in
                guard let self else { return }
                self.selectedRange = NSRange(location: 0, length: 0)
                self.scrollRangeToVisible(NSRange(location: 0, length: 0))
            }
            return
        }
        super.paste(sender)
        DispatchQueue.main.async { [weak self] in
            guard let self else { return }
            self.selectedRange = NSRange(location: 0, length: 0)
            self.scrollRangeToVisible(NSRange(location: 0, length: 0))
        }
    }

    @objc private func insertBracketToken(_ sender: UIButton) {
        guard isEditable, let token = sender.accessibilityIdentifier else { return }
        becomeFirstResponder()

        let selection = selectedRange
        if let pair = pairForToken(token) {
            textStorage.replaceCharacters(in: selection, with: pair.open + pair.close)
            selectedRange = NSRange(location: selection.location + pair.open.count, length: 0)
            delegate?.textViewDidChange?(self)
            return
        }

        textStorage.replaceCharacters(in: selection, with: token)
        selectedRange = NSRange(location: selection.location + token.count, length: 0)
        delegate?.textViewDidChange?(self)
    }

    private func pairForToken(_ token: String) -> (open: String, close: String)? {
        switch token {
        case "()": return ("(", ")")
        case "{}": return ("{", "}")
        case "[]": return ("[", "]")
        case "\"\"": return ("\"", "\"")
        case "''": return ("'", "'")
        default: return nil
        }
    }

    private func vimCommand(
        input: String,
        modifiers: UIKeyModifierFlags = [],
        action: Selector,
        title: String
    ) -> UIKeyCommand {
        let command = UIKeyCommand(input: input, modifierFlags: modifiers, action: action)
        command.discoverabilityTitle = title
        if #available(iOS 15.0, *) {
            command.wantsPriorityOverSystemBehavior = true
        }
        return command
    }

    private func syncVimModeFromDefaults() {
        let enabled = UserDefaults.standard.bool(forKey: vimModeDefaultsKey)
        let interceptionEnabled = UserDefaults.standard.bool(forKey: vimInterceptionDefaultsKey)
        if !enabled || !interceptionEnabled {
            pendingDeleteCurrentLineCommand = false
            if !isVimInsertMode {
                setVimInsertMode(true)
            }
        }
    }

    private func setVimInsertMode(_ isInsertMode: Bool) {
        isVimInsertMode = isInsertMode
        pendingDeleteCurrentLineCommand = false
        NotificationCenter.default.post(
            name: .vimModeStateDidChange,
            object: nil,
            userInfo: ["insertMode": isInsertMode]
        )
    }

    @objc private func handleVimModeStateDidChange(_ notification: Notification) {
        if let insertMode = notification.userInfo?["insertMode"] as? Bool {
            isVimInsertMode = insertMode
            pendingDeleteCurrentLineCommand = false
        } else {
            syncVimModeFromDefaults()
        }
    }

    private func vimText() -> NSString {
        (text ?? "") as NSString
    }

    private func collapseSelection() -> NSRange {
        let current = selectedRange
        if current.length == 0 {
            return current
        }
        let collapsed = NSRange(location: current.location, length: 0)
        selectedRange = collapsed
        delegate?.textViewDidChangeSelection?(self)
        return collapsed
    }

    private func moveCaret(to location: Int) {
        let length = vimText().length
        selectedRange = NSRange(location: max(0, min(location, length)), length: 0)
        scrollRangeToVisible(selectedRange)
        delegate?.textViewDidChangeSelection?(self)
    }

    private func currentLineRange(for range: NSRange? = nil) -> NSRange {
        let target = range ?? collapseSelection()
        return vimText().lineRange(for: NSRange(location: target.location, length: 0))
    }

    private func currentColumn(in lineRange: NSRange, location: Int) -> Int {
        max(0, location - lineRange.location)
    }

    private func lineStartLocations() -> [Int] {
        let nsText = vimText()
        var starts: [Int] = [0]
        var location = 0
        while location < nsText.length {
            let lineRange = nsText.lineRange(for: NSRange(location: location, length: 0))
            let nextLocation = NSMaxRange(lineRange)
            if nextLocation >= nsText.length {
                break
            }
            starts.append(nextLocation)
            location = nextLocation
        }
        return starts
    }

    private func wordCharacterSetContains(_ scalar: UnicodeScalar) -> Bool {
        CharacterSet.alphanumerics.contains(scalar) || scalar == "_"
    }

    private func moveWordForwardLocation(from location: Int) -> Int {
        let nsText = vimText()
        let length = nsText.length
        var index = min(max(0, location), length)
        while index < length {
            let codeUnit = nsText.character(at: index)
            guard let scalar = UnicodeScalar(codeUnit) else {
                index += 1
                continue
            }
            if wordCharacterSetContains(scalar) {
                break
            }
            index += 1
        }
        while index < length {
            let codeUnit = nsText.character(at: index)
            guard let scalar = UnicodeScalar(codeUnit) else {
                index += 1
                continue
            }
            if !wordCharacterSetContains(scalar) {
                break
            }
            index += 1
        }
        while index < length {
            let codeUnit = nsText.character(at: index)
            guard let scalar = UnicodeScalar(codeUnit) else {
                index += 1
                continue
            }
            if wordCharacterSetContains(scalar) {
                break
            }
            index += 1
        }
        return min(index, length)
    }

    private func moveWordBackwardLocation(from location: Int) -> Int {
        let nsText = vimText()
        var index = max(0, min(location, nsText.length))
        if index > 0 {
            index -= 1
        }
        while index > 0 {
            let codeUnit = nsText.character(at: index)
            guard let scalar = UnicodeScalar(codeUnit) else {
                index -= 1
                continue
            }
            if wordCharacterSetContains(scalar) {
                break
            }
            index -= 1
        }
        while index > 0 {
            let previous = nsText.character(at: index - 1)
            guard let scalar = UnicodeScalar(previous) else {
                index -= 1
                continue
            }
            if !wordCharacterSetContains(scalar) {
                break
            }
            index -= 1
        }
        return index
    }

    private func deleteText(in range: NSRange) {
        guard range.length > 0 else { return }
        textStorage.replaceCharacters(in: range, with: "")
        selectedRange = NSRange(location: min(range.location, vimText().length), length: 0)
        delegate?.textViewDidChange?(self)
        delegate?.textViewDidChangeSelection?(self)
    }

    @objc private func vimEscapeToNormalMode() {
        if isVimInsertMode {
            setVimInsertMode(false)
        }
    }

    @objc private func vimEnterInsertMode() {
        setVimInsertMode(true)
    }

    @objc private func vimAppendInsertMode() {
        let current = collapseSelection()
        if current.location < vimText().length {
            moveCaret(to: current.location + 1)
        }
        setVimInsertMode(true)
    }

    @objc private func vimMoveLeft() {
        let current = collapseSelection()
        moveCaret(to: current.location - 1)
    }

    @objc private func vimMoveRight() {
        let current = collapseSelection()
        moveCaret(to: current.location + 1)
    }

    @objc private func vimMoveUp() {
        let current = collapseSelection()
        let starts = lineStartLocations()
        guard let lineIndex = starts.lastIndex(where: { $0 <= current.location }), lineIndex > 0 else { return }
        let currentLine = currentLineRange(for: current)
        let column = currentColumn(in: currentLine, location: current.location)
        let previousStart = starts[lineIndex - 1]
        let previousLine = vimText().lineRange(for: NSRange(location: previousStart, length: 0))
        let previousLineEnd = max(previousLine.location, previousLine.location + max(0, previousLine.length - 1))
        moveCaret(to: min(previousStart + column, previousLineEnd))
    }

    @objc private func vimMoveDown() {
        let current = collapseSelection()
        let starts = lineStartLocations()
        guard let lineIndex = starts.lastIndex(where: { $0 <= current.location }), lineIndex + 1 < starts.count else { return }
        let currentLine = currentLineRange(for: current)
        let column = currentColumn(in: currentLine, location: current.location)
        let nextStart = starts[lineIndex + 1]
        let nextLine = vimText().lineRange(for: NSRange(location: nextStart, length: 0))
        let nextLineEnd = max(nextLine.location, nextLine.location + max(0, nextLine.length - 1))
        moveCaret(to: min(nextStart + column, nextLineEnd))
    }

    @objc private func vimMoveWordForward() {
        moveCaret(to: moveWordForwardLocation(from: collapseSelection().location))
    }

    @objc private func vimMoveWordBackward() {
        moveCaret(to: moveWordBackwardLocation(from: collapseSelection().location))
    }

    @objc private func vimMoveToLineStart() {
        let lineRange = currentLineRange()
        moveCaret(to: lineRange.location)
    }

    @objc private func vimMoveToLineEnd() {
        let lineRange = currentLineRange()
        let lineEnd = max(lineRange.location, lineRange.location + max(0, lineRange.length - 1))
        moveCaret(to: lineEnd)
    }

    @objc private func vimDeleteForward() {
        let current = collapseSelection()
        guard current.location < vimText().length else { return }
        deleteText(in: NSRange(location: current.location, length: 1))
    }

    @objc private func vimDeleteLineStep() {
        if pendingDeleteCurrentLineCommand {
            pendingDeleteCurrentLineCommand = false
            let lineRange = currentLineRange()
            deleteText(in: lineRange)
            return
        }
        pendingDeleteCurrentLineCommand = true
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) { [weak self] in
            self?.pendingDeleteCurrentLineCommand = false
        }
    }
}

final class LineNumberGutterView: UIView {
    weak var textView: UITextView?
    var lineStarts: [Int] = [0]
    var font: UIFont = UIFont.monospacedDigitSystemFont(ofSize: 12, weight: .regular)
    var textColor: UIColor = .secondaryLabel

    override func draw(_ rect: CGRect) {
        guard let textView else { return }
        let layoutManager = textView.layoutManager
        guard !lineStarts.isEmpty else { return }

        let visibleRect = CGRect(origin: textView.contentOffset, size: textView.bounds.size).insetBy(dx: 0, dy: -80)
        let glyphRange = layoutManager.glyphRange(forBoundingRect: visibleRect, in: textView.textContainer)
        if glyphRange.length == 0 { return }

        let paragraph = NSMutableParagraphStyle()
        paragraph.alignment = .right
        let attrs: [NSAttributedString.Key: Any] = [
            .font: font,
            .foregroundColor: textColor,
            .paragraphStyle: paragraph
        ]
        let rightPadding: CGFloat = 6
        let textContainerTop = textView.textContainerInset.top
        let contentOffsetY = textView.contentOffset.y
        let stickyTopY = textContainerTop + 1
        let visibleStartChar = layoutManager.characterIndexForGlyph(at: glyphRange.location)
        let stickyLineIndex = lineNumberForCharacterIndex(visibleStartChar)
        let stickyLineStart = lineStarts[stickyLineIndex]
        let shouldShowStickyLineNumber = stickyLineStart < visibleStartChar
        var drawnLineIndices = Set<Int>()

        layoutManager.enumerateLineFragments(forGlyphRange: glyphRange) { _, usedRect, _, glyphRange, _ in
            let charIndex = layoutManager.characterIndexForGlyph(at: glyphRange.location)
            let lineIndex = self.lineNumberForCharacterIndex(charIndex)
            if shouldShowStickyLineNumber && lineIndex == stickyLineIndex {
                return
            }
            if drawnLineIndices.contains(lineIndex) {
                return
            }
            drawnLineIndices.insert(lineIndex)

            let lineNumber = lineIndex + 1
            let drawY = usedRect.minY + textContainerTop - contentOffsetY
            let drawRect = CGRect(x: 0, y: drawY, width: self.bounds.width - rightPadding, height: usedRect.height)
            NSString(string: String(lineNumber)).draw(in: drawRect, withAttributes: attrs)
        }

        if shouldShowStickyLineNumber {
            let lineNumber = stickyLineIndex + 1
            let drawRect = CGRect(x: 0, y: stickyTopY, width: bounds.width - rightPadding, height: font.lineHeight)
            NSString(string: String(lineNumber)).draw(in: drawRect, withAttributes: attrs)
        }
    }

    private func lineNumberForCharacterIndex(_ index: Int) -> Int {
        var low = 0
        var high = lineStarts.count - 1
        while low <= high {
            let mid = (low + high) / 2
            if lineStarts[mid] <= index {
                low = mid + 1
            } else {
                high = mid - 1
            }
        }
        return max(0, min(high, lineStarts.count - 1))
    }
}

final class LineNumberedTextViewContainer: UIView {
    let lineNumberView = LineNumberGutterView()
    let textView = EditorInputTextView()
    private var lineNumberWidthConstraint: NSLayoutConstraint?
    private var cachedLineStarts: [Int] = [0]
    private var cachedFontPointSize: CGFloat = 0
    private var cachedLineNumberWidth: CGFloat = 46

    override init(frame: CGRect) {
        super.init(frame: frame)
        configureViews()
    }

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

    private func configureViews() {
        lineNumberView.translatesAutoresizingMaskIntoConstraints = false
        textView.translatesAutoresizingMaskIntoConstraints = false
        lineNumberView.textView = textView

        lineNumberView.backgroundColor = UIColor.secondarySystemBackground.withAlphaComponent(0.65)
        lineNumberView.textColor = .secondaryLabel
        lineNumberView.isUserInteractionEnabled = false

        textView.contentInsetAdjustmentBehavior = .never
        textView.keyboardDismissMode = .onDrag
        textView.textContainerInset = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)

        let divider = UIView()
        divider.translatesAutoresizingMaskIntoConstraints = false
        divider.backgroundColor = UIColor.separator.withAlphaComponent(0.6)

        addSubview(lineNumberView)
        addSubview(divider)
        addSubview(textView)

        NSLayoutConstraint.activate([
            lineNumberView.leadingAnchor.constraint(equalTo: leadingAnchor),
            lineNumberView.topAnchor.constraint(equalTo: topAnchor),
            lineNumberView.bottomAnchor.constraint(equalTo: bottomAnchor),

            divider.leadingAnchor.constraint(equalTo: lineNumberView.trailingAnchor),
            divider.topAnchor.constraint(equalTo: topAnchor),
            divider.bottomAnchor.constraint(equalTo: bottomAnchor),
            divider.widthAnchor.constraint(equalToConstant: 1),

            textView.leadingAnchor.constraint(equalTo: divider.trailingAnchor),
            textView.trailingAnchor.constraint(equalTo: trailingAnchor),
            textView.topAnchor.constraint(equalTo: topAnchor),
            textView.bottomAnchor.constraint(equalTo: bottomAnchor)
        ])

        let widthConstraint = lineNumberView.widthAnchor.constraint(equalToConstant: 46)
        widthConstraint.isActive = true
        lineNumberWidthConstraint = widthConstraint
    }

    func updateLineNumbers(for text: String, fontSize: CGFloat) {
        var needsDisplayRefresh = false
        let numberFont = UIFont.monospacedDigitSystemFont(ofSize: max(11, fontSize - 1), weight: .regular)
        if abs(cachedFontPointSize - numberFont.pointSize) > 0.01 {
            lineNumberView.font = numberFont
            cachedFontPointSize = numberFont.pointSize
            needsDisplayRefresh = true
        }
        let lineStarts = lineStartOffsets(for: text)
        if lineStarts != cachedLineStarts {
            cachedLineStarts = lineStarts
            lineNumberView.lineStarts = lineStarts
            needsDisplayRefresh = true
        }
        let lineCount = max(1, lineStarts.count)
        let digits = max(2, String(lineCount).count)
        let glyphWidth = NSString(string: "8").size(withAttributes: [.font: numberFont]).width
        let targetWidth = ceil((glyphWidth * CGFloat(digits)) + 14)
        if abs(cachedLineNumberWidth - targetWidth) > 0.5 {
            cachedLineNumberWidth = targetWidth
            lineNumberWidthConstraint?.constant = targetWidth
            setNeedsLayout()
            layoutIfNeeded()
            needsDisplayRefresh = true
        }
        if needsDisplayRefresh {
            lineNumberView.setNeedsDisplay()
        }
    }

    private func lineStartOffsets(for text: String) -> [Int] {
        var starts: [Int] = [0]
        let utf16 = text.utf16
        starts.reserveCapacity(max(32, utf16.count / 24))
        var idx = 0
        for codeUnit in utf16 {
            idx += 1
            if codeUnit == 10 { // '\n'
                starts.append(idx)
            }
        }
        return starts
    }
}

struct CustomTextEditor: UIViewRepresentable {
    @Binding var text: String
    let documentID: UUID?
    let externalEditRevision: Int
    let language: String
    let colorScheme: ColorScheme
    let fontSize: CGFloat
    @Binding var isLineWrapEnabled: Bool
    let isLargeFileMode: Bool
    let translucentBackgroundEnabled: Bool
    let showKeyboardAccessoryBar: Bool
    let showLineNumbers: Bool
    let showInvisibleCharacters: Bool
    let highlightCurrentLine: Bool
    let highlightMatchingBrackets: Bool
    let showScopeGuides: Bool
    let highlightScopeBackground: Bool
    let indentStyle: String
    let indentWidth: Int
    let autoIndentEnabled: Bool
    let autoCloseBracketsEnabled: Bool
    let highlightRefreshToken: Int
    let isTabLoadingContent: Bool
    let isReadOnly: Bool
    let onTextMutation: ((EditorTextMutation) -> Void)?

    private var fontName: String {
        UserDefaults.standard.string(forKey: "SettingsEditorFontName") ?? ""
    }

    private var useSystemFont: Bool {
        UserDefaults.standard.bool(forKey: "SettingsUseSystemFont")
    }

    private var lineHeightMultiple: CGFloat {
        let stored = UserDefaults.standard.double(forKey: "SettingsLineHeight")
        return CGFloat(stored > 0 ? stored : 1.0)
    }

    private func resolvedUIFont(size: CGFloat? = nil) -> UIFont {
        let targetSize = size ?? fontSize
        if useSystemFont {
            return UIFont.systemFont(ofSize: targetSize)
        }
        if let named = UIFont(name: fontName, size: targetSize) {
            return named
        }
        return UIFont.monospacedSystemFont(ofSize: targetSize, weight: .regular)
    }

    private func applyInvisibleCharacterPreference(_ textView: UITextView) {
        let shouldShow = showInvisibleCharacters
        let defaults = UserDefaults.standard
        defaults.set(shouldShow, forKey: "SettingsShowInvisibleCharacters")
        defaults.set(shouldShow, forKey: "NSShowAllInvisibles")
        defaults.set(shouldShow, forKey: "NSShowControlCharacters")
        textView.layoutManager.invalidateDisplay(forCharacterRange: NSRange(location: 0, length: textView.textStorage.length))
        textView.setNeedsDisplay()
    }

    func makeUIView(context: Context) -> LineNumberedTextViewContainer {
        let container = LineNumberedTextViewContainer()
        let textView = container.textView
        let theme = currentEditorTheme(colorScheme: colorScheme)

        textView.delegate = context.coordinator
        textView.isEditable = !isReadOnly
        let initialFont = resolvedUIFont()
        textView.font = initialFont
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineHeightMultiple = max(0.9, lineHeightMultiple)
        let baseColor = UIColor(theme.text)
        var typing = textView.typingAttributes
        typing[.paragraphStyle] = paragraphStyle
        typing[.foregroundColor] = baseColor
        typing[.font] = textView.font ?? initialFont
        textView.typingAttributes = typing
        let initialLength = (text as NSString).length
        if shouldUseChunkedLargeFileInstall(isLargeFileMode: isLargeFileMode, textLength: initialLength) {
            textView.text = ""
        } else {
            textView.text = text
        }
        if text.count <= 200_000 {
            textView.textStorage.beginEditing()
            textView.textStorage.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: textView.textStorage.length))
            textView.textStorage.endEditing()
        }
        textView.autocorrectionType = .no
        textView.autocapitalizationType = .none
        textView.smartDashesType = .no
        textView.smartQuotesType = .no
        textView.smartInsertDeleteType = .no
        textView.allowsEditingTextAttributes = false
        if #available(iOS 18.0, *) {
            textView.writingToolsBehavior = .none
        }
        applyInvisibleCharacterPreference(textView)
        textView.backgroundColor = translucentBackgroundEnabled ? .clear : .systemBackground
        textView.setBracketAccessoryVisible(showKeyboardAccessoryBar)
        let shouldWrapText = isLineWrapEnabled && !isLargeFileMode
        let desiredLineBreakMode: NSLineBreakMode = shouldWrapText ? .byWordWrapping : .byClipping
        if textView.textContainer.lineBreakMode != desiredLineBreakMode
            || textView.textContainer.widthTracksTextView != shouldWrapText {
            let priorOffset = textView.contentOffset
            textView.textContainer.lineBreakMode = desiredLineBreakMode
            textView.textContainer.widthTracksTextView = shouldWrapText
            if (textView.text as NSString?)?.length ?? 0 <= 300_000 {
                textView.layoutManager.ensureLayout(for: textView.textContainer)
            }
            let inset = textView.adjustedContentInset
            let minY = -inset.top
            let maxY = max(minY, textView.contentSize.height - textView.bounds.height + inset.bottom)
            let clampedY = min(max(priorOffset.y, minY), maxY)
            textView.setContentOffset(CGPoint(x: priorOffset.x, y: clampedY), animated: false)
        }

        if !showLineNumbers {
            container.lineNumberView.isHidden = true
        } else {
            container.lineNumberView.isHidden = false
            container.updateLineNumbers(for: text, fontSize: fontSize)
        }
        context.coordinator.container = container
        context.coordinator.textView = textView
        if shouldUseChunkedLargeFileInstall(isLargeFileMode: isLargeFileMode, textLength: initialLength) {
            DispatchQueue.main.async {
                _ = context.coordinator.installLargeTextIfNeeded(on: textView, target: text)
            }
        } else {
            context.coordinator.scheduleHighlightIfNeeded(currentText: text, immediate: true)
        }
        return container
    }

    func updateUIView(_ uiView: LineNumberedTextViewContainer, context: Context) {
        let textView = uiView.textView
        context.coordinator.parent = self
        textView.isEditable = !isReadOnly
        let didSwitchDocument = context.coordinator.lastDocumentID != documentID
        let didFinishTabLoad = (context.coordinator.lastTabLoadingContent == true) && !isTabLoadingContent
        let didReceiveExternalEdit = context.coordinator.lastExternalEditRevision != externalEditRevision
        let didTransitionDocumentState = didSwitchDocument || didFinishTabLoad || didReceiveExternalEdit
        if didSwitchDocument {
            context.coordinator.lastDocumentID = documentID
            context.coordinator.cancelPendingBindingSync()
            context.coordinator.clearPendingTextMutation()
            context.coordinator.invalidateHighlightCache()
        }
        context.coordinator.lastTabLoadingContent = isTabLoadingContent
        context.coordinator.lastExternalEditRevision = externalEditRevision
        let targetLength = (text as NSString).length
        let shouldSkipLargeFileResync =
            isLargeFileMode &&
            targetLength >= EditorRuntimeLimits.syntaxMinimalUTF16Length &&
            !didSwitchDocument &&
            !didFinishTabLoad &&
            !didReceiveExternalEdit &&
            !context.coordinator.hasPendingBindingSync
        if textView.text != text {
            if !shouldSkipLargeFileResync {
                let shouldPreferEditorBuffer =
                    textView.isFirstResponder &&
                    !isTabLoadingContent &&
                    !didSwitchDocument &&
                    !didFinishTabLoad &&
                    !didReceiveExternalEdit
                if shouldPreferEditorBuffer {
                    context.coordinator.syncBindingTextImmediately(textView.text)
                } else {
                    context.coordinator.cancelPendingBindingSync()
                    let priorSelection = textView.selectedRange
                    let priorOffset = textView.contentOffset
                    let didInstallLargeText = context.coordinator.installLargeTextIfNeeded(on: textView, target: text)
                    if !didInstallLargeText {
                        textView.text = text
                        let length = (textView.text as NSString).length
                        let clampedLocation = min(priorSelection.location, length)
                        let clampedLength = min(priorSelection.length, max(0, length - clampedLocation))
                        textView.selectedRange = NSRange(location: clampedLocation, length: clampedLength)
                        textView.setContentOffset(priorOffset, animated: false)
                    }
                }
            }
        }
        let targetFont = resolvedUIFont()
        if textView.font?.fontName != targetFont.fontName || textView.font?.pointSize != targetFont.pointSize {
            textView.font = targetFont
        }
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineHeightMultiple = max(0.9, lineHeightMultiple)
        textView.typingAttributes[.paragraphStyle] = paragraphStyle
        if context.coordinator.lastLineHeight != lineHeightMultiple {
            let len = textView.textStorage.length
            if len > 0 && len <= 200_000 {
                let undoWasEnabled = textView.undoManager?.isUndoRegistrationEnabled ?? false
                if undoWasEnabled {
                    textView.undoManager?.disableUndoRegistration()
                }
                textView.textStorage.beginEditing()
                textView.textStorage.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: len))
                textView.textStorage.endEditing()
                if undoWasEnabled {
                    textView.undoManager?.enableUndoRegistration()
                }
            }
            context.coordinator.lastLineHeight = lineHeightMultiple
        }
        let theme = currentEditorTheme(colorScheme: colorScheme)
        let baseColor = UIColor(theme.text)
        textView.tintColor = UIColor(theme.cursor)
        textView.backgroundColor = translucentBackgroundEnabled ? .clear : UIColor(theme.background)
        textView.setBracketAccessoryVisible(showKeyboardAccessoryBar)
        let shouldWrapText = isLineWrapEnabled && !isLargeFileMode
        let desiredLineBreakMode: NSLineBreakMode = shouldWrapText ? .byWordWrapping : .byClipping
        if textView.textContainer.lineBreakMode != desiredLineBreakMode
            || textView.textContainer.widthTracksTextView != shouldWrapText {
            let priorOffset = textView.contentOffset
            textView.textContainer.lineBreakMode = desiredLineBreakMode
            textView.textContainer.widthTracksTextView = shouldWrapText
            if (textView.text as NSString?)?.length ?? 0 <= 300_000 {
                textView.layoutManager.ensureLayout(for: textView.textContainer)
            }
            let inset = textView.adjustedContentInset
            let minY = -inset.top
            let maxY = max(minY, textView.contentSize.height - textView.bounds.height + inset.bottom)
            let clampedY = min(max(priorOffset.y, minY), maxY)
            textView.setContentOffset(CGPoint(x: priorOffset.x, y: clampedY), animated: false)
        }
        textView.layoutManager.allowsNonContiguousLayout = true
        textView.keyboardDismissMode = .onDrag
        if #available(iOS 18.0, *) {
            if textView.writingToolsBehavior != .none {
                textView.writingToolsBehavior = .none
            }
        }
        applyInvisibleCharacterPreference(textView)
        textView.typingAttributes[.foregroundColor] = baseColor
        if !showLineNumbers {
            uiView.lineNumberView.isHidden = true
        } else {
            uiView.lineNumberView.isHidden = false
            uiView.updateLineNumbers(for: text, fontSize: fontSize)
        }
        context.coordinator.syncLineNumberScroll()
        if didTransitionDocumentState {
            context.coordinator.scheduleHighlightIfNeeded(currentText: textView.text ?? text, immediate: true)
        } else {
            context.coordinator.scheduleHighlightIfNeeded(currentText: text)
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, UITextViewDelegate {
        var parent: CustomTextEditor
        weak var container: LineNumberedTextViewContainer?
        weak var textView: EditorInputTextView?
        private let highlightQueue = DispatchQueue(label: "NeonVision.iOS.SyntaxHighlight", qos: .userInitiated)
        private var pendingHighlight: DispatchWorkItem?
        private var pendingBindingSync: DispatchWorkItem?
        private var pendingTextMutation: (range: NSRange, replacement: String)?
        private var pendingEditedRange: NSRange?
        private var isInstallingLargeText = false
        private var largeTextInstallGeneration: Int = 0
        private var lastHighlightedText: String = ""
        private var lastLanguage: String?
        private var lastColorScheme: ColorScheme?
        var lastLineHeight: CGFloat?
        private var lastHighlightToken: Int = 0
        private var lastSelectionLocation: Int = -1
        private var lastHighlightViewportAnchor: Int = -1
        private var lastTranslucencyEnabled: Bool?
        private var lastLineNumberContentOffsetY: CGFloat = .greatestFiniteMagnitude
        private var isApplyingHighlight = false
        private var highlightGeneration: Int = 0
        var lastDocumentID: UUID?
        var lastTabLoadingContent: Bool?
        var lastExternalEditRevision: Int?
        var hasPendingBindingSync: Bool { pendingBindingSync != nil }

        init(_ parent: CustomTextEditor) {
            self.parent = parent
            super.init()
            NotificationCenter.default.addObserver(self, selector: #selector(moveToLine(_:)), name: .moveCursorToLine, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(moveToRange(_:)), name: .moveCursorToRange, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(updateKeyboardAccessoryVisibility(_:)), name: .keyboardAccessoryBarVisibilityChanged, object: nil)
        }

        deinit {
            pendingBindingSync?.cancel()
            NotificationCenter.default.removeObserver(self)
        }

        private func shouldRenderLineNumbers() -> Bool {
            guard let lineView = container?.lineNumberView else { return false }
            return parent.showLineNumbers && !lineView.isHidden && !isInstallingLargeText
        }

        func invalidateHighlightCache() {
            lastHighlightedText = ""
            lastLanguage = nil
            lastColorScheme = nil
            lastLineHeight = nil
            lastHighlightToken = 0
            lastSelectionLocation = -1
            lastHighlightViewportAnchor = -1
            lastTranslucencyEnabled = nil
            lastLineNumberContentOffsetY = .greatestFiniteMagnitude
            largeTextInstallGeneration &+= 1
            isInstallingLargeText = false
        }

        private func currentViewportAnchor(textLength: Int, language: String) -> Int {
            guard let textView,
                  supportsResponsiveLargeFileHighlight(language: language, textLength: textLength),
                  textLength >= 100_000 else { return -1 }
            let visibleRect = CGRect(origin: textView.contentOffset, size: textView.bounds.size).insetBy(dx: 0, dy: -80)
            let glyphRange = textView.layoutManager.glyphRange(forBoundingRect: visibleRect, in: textView.textContainer)
            let charRange = textView.layoutManager.characterRange(forGlyphRange: glyphRange, actualGlyphRange: nil)
            guard charRange.length > 0 else { return -1 }
            return charRange.location
        }

        private func syncBindingText(_ text: String, immediate: Bool = false) {
            if parent.isTabLoadingContent || isInstallingLargeText {
                return
            }
            pendingBindingSync?.cancel()
            pendingBindingSync = nil
            if immediate || (text as NSString).length < EditorRuntimeLimits.bindingDebounceUTF16Length {
                parent.text = text
                return
            }
            let work = DispatchWorkItem { [weak self] in
                guard let self else { return }
                self.pendingBindingSync = nil
                if self.textView?.text == text {
                    self.parent.text = text
                }
            }
            pendingBindingSync = work
            DispatchQueue.main.asyncAfter(deadline: .now() + EditorRuntimeLimits.bindingDebounceDelay, execute: work)
        }

        func cancelPendingBindingSync() {
            pendingBindingSync?.cancel()
            pendingBindingSync = nil
        }

        func clearPendingTextMutation() {
            pendingTextMutation = nil
            pendingEditedRange = nil
        }

        func syncBindingTextImmediately(_ text: String) {
            guard !isInstallingLargeText else { return }
            syncBindingText(text, immediate: true)
        }

        fileprivate func installLargeTextIfNeeded(
            on textView: EditorInputTextView,
            target: String
        ) -> Bool {
            guard parent.isLargeFileMode else { return false }
            let openMode = currentLargeFileOpenMode()
            guard openMode != .standard else { return false }
            let targetLength = (target as NSString).length
            guard targetLength >= EditorRuntimeLimits.syntaxMinimalUTF16Length else { return false }

            largeTextInstallGeneration &+= 1
            let generation = largeTextInstallGeneration
            isInstallingLargeText = true
            pendingHighlight?.cancel()
            pendingHighlight = nil

            let previousSelection = textView.selectedRange
            let priorOffset = textView.contentOffset
            let wasFirstResponder = textView.isFirstResponder
            textView.isEditable = false
            textView.text = ""

            let nsTarget = target as NSString

            func applyChunk(from location: Int) {
                guard generation == self.largeTextInstallGeneration else { return }
                let remaining = targetLength - location
                guard remaining > 0 else {
                    self.isInstallingLargeText = false
                    textView.isEditable = !parent.isReadOnly
                    let safeLocation = min(max(0, previousSelection.location), targetLength)
                    let safeLength = min(max(0, previousSelection.length), max(0, targetLength - safeLocation))
                    textView.selectedRange = NSRange(location: safeLocation, length: safeLength)
                    textView.setContentOffset(priorOffset, animated: false)
                    if wasFirstResponder {
                        textView.becomeFirstResponder()
                    }
                    self.scheduleHighlightIfNeeded(currentText: target, immediate: true)
                    return
                }

                let chunkLength = min(LargeFileInstallRuntime.chunkUTF16, remaining)
                let chunk = nsTarget.substring(with: NSRange(location: location, length: chunkLength))
                textView.textStorage.beginEditing()
                textView.textStorage.append(NSAttributedString(string: chunk))
                textView.textStorage.endEditing()
                DispatchQueue.main.async {
                    applyChunk(from: location + chunkLength)
                }
            }

            applyChunk(from: 0)
            return true
        }

        private func setPendingTextMutation(range: NSRange, replacement: String) {
            guard !parent.isTabLoadingContent, parent.documentID != nil else {
                pendingTextMutation = nil
                return
            }
            pendingTextMutation = (range: range, replacement: replacement)
        }

        private func applyPendingTextMutationIfPossible() -> Bool {
            defer { pendingTextMutation = nil }
            guard !parent.isTabLoadingContent,
                  let pendingTextMutation,
                  let documentID = parent.documentID,
                  let onTextMutation = parent.onTextMutation else {
                return false
            }
            onTextMutation(
                EditorTextMutation(
                    documentID: documentID,
                    range: pendingTextMutation.range,
                    replacement: pendingTextMutation.replacement
                )
            )
            return true
        }

        @objc private func updateKeyboardAccessoryVisibility(_ notification: Notification) {
            guard let textView else { return }
            let isVisible: Bool
            if let explicit = notification.object as? Bool {
                isVisible = explicit
            } else {
                isVisible = UserDefaults.standard.object(forKey: "SettingsShowKeyboardAccessoryBarIOS") as? Bool ?? false
            }
            textView.setBracketAccessoryVisible(isVisible)
            if isVisible && !textView.isFirstResponder {
                textView.becomeFirstResponder()
            }
            textView.reloadInputViews()
        }

        @objc private func moveToRange(_ notification: Notification) {
            guard let textView else { return }
            guard let location = notification.userInfo?[EditorCommandUserInfo.rangeLocation] as? Int,
                  let length = notification.userInfo?[EditorCommandUserInfo.rangeLength] as? Int else { return }
            let textLength = (textView.text as NSString?)?.length ?? 0
            guard location >= 0, length >= 0, location + length <= textLength else { return }
            let range = NSRange(location: location, length: length)
            let shouldFocusEditor = notification.userInfo?[EditorCommandUserInfo.focusEditor] as? Bool ?? true
            DispatchQueue.main.async {
                if shouldFocusEditor {
                    textView.becomeFirstResponder()
                }
                textView.selectedRange = range
                textView.scrollRangeToVisible(range)
            }
        }

        @objc private func moveToLine(_ notification: Notification) {
            guard let lineOneBased = notification.object as? Int, lineOneBased > 0 else { return }
            guard let textView else { return }
            let nsText = (textView.text ?? "") as NSString
            guard nsText.length > 0 else { return }

            let lineFragments = (textView.text ?? "").components(separatedBy: .newlines)
            let clampedLineIndex = max(1, min(lineOneBased, lineFragments.count)) - 1
            var location = 0
            if clampedLineIndex > 0 {
                for i in 0..<clampedLineIndex {
                    location += (lineFragments[i] as NSString).length + 1
                }
            }
            location = max(0, min(location, nsText.length))
            let target = NSRange(location: location, length: 0)
            textView.becomeFirstResponder()
            textView.selectedRange = target
            textView.scrollRangeToVisible(target)
            scheduleHighlightIfNeeded(currentText: textView.text ?? "", immediate: true)
        }

        func scheduleHighlightIfNeeded(currentText: String? = nil, immediate: Bool = false) {
            guard let textView else { return }
            let text = currentText ?? textView.text ?? ""
            let lang = parent.language
            let scheme = parent.colorScheme
            let lineHeight = parent.lineHeightMultiple
            let token = parent.highlightRefreshToken
            let translucencyEnabled = parent.translucentBackgroundEnabled
            let selectionLocation = textView.selectedRange.location
            let textLength = (text as NSString).length
            let viewportAnchor = currentViewportAnchor(
                textLength: textLength,
                language: lang
            )

            if parent.isLargeFileMode && !supportsResponsiveLargeFileHighlight(language: lang, textLength: textLength) {
                lastHighlightedText = text
                lastLanguage = lang
                lastColorScheme = scheme
                lastLineHeight = lineHeight
                lastHighlightToken = token
                lastSelectionLocation = selectionLocation
                lastHighlightViewportAnchor = viewportAnchor
                lastTranslucencyEnabled = translucencyEnabled
                return
            }
            if textLength >= EditorRuntimeLimits.syntaxMinimalUTF16Length &&
                !supportsResponsiveLargeFileHighlight(language: lang, textLength: textLength) {
                lastHighlightedText = text
                lastLanguage = lang
                lastColorScheme = scheme
                lastLineHeight = lineHeight
                lastHighlightToken = token
                lastSelectionLocation = selectionLocation
                lastHighlightViewportAnchor = viewportAnchor
                lastTranslucencyEnabled = translucencyEnabled
                return
            }

            if text == lastHighlightedText &&
                lang == lastLanguage &&
                scheme == lastColorScheme &&
                lineHeight == lastLineHeight &&
                lastHighlightToken == token &&
                lastSelectionLocation == selectionLocation &&
                lastHighlightViewportAnchor == viewportAnchor &&
                lastTranslucencyEnabled == translucencyEnabled {
                return
            }

            let styleStateUnchanged = lang == lastLanguage &&
                scheme == lastColorScheme &&
                lineHeight == lastLineHeight &&
                lastHighlightToken == token &&
                lastTranslucencyEnabled == translucencyEnabled
            let selectionOnlyChange = text == lastHighlightedText &&
                styleStateUnchanged &&
                lastSelectionLocation != selectionLocation
            if selectionOnlyChange && parent.isLineWrapEnabled {
                pendingHighlight?.cancel()
                pendingHighlight = nil
                lastSelectionLocation = selectionLocation
                return
            }
            if selectionOnlyChange && textLength >= EditorRuntimeLimits.cursorRehighlightMaxUTF16Length {
                lastSelectionLocation = selectionLocation
                return
            }

            let incrementalRange: NSRange? = {
                guard token == lastHighlightToken,
                      lang == lastLanguage,
                      scheme == lastColorScheme,
                      !immediate,
                      let edit = pendingEditedRange else { return nil }
                let supportsLargeFileJSON = parent.isLargeFileMode && supportsResponsiveLargeFileHighlight(language: lang, textLength: textLength)
                if !supportsLargeFileJSON && text.utf16.count >= 120_000 {
                    return nil
                }
                let padding = supportsLargeFileJSON
                    ? EditorRuntimeLimits.largeFileJSONIncrementalPaddingUTF16
                    : 6_000
                return expandedRange(around: edit, in: text as NSString, maxUTF16Padding: padding)
            }()
            pendingEditedRange = nil
            pendingHighlight?.cancel()
            highlightGeneration &+= 1
            let generation = highlightGeneration
            let applyRange = incrementalRange ?? preferredHighlightRange(textView: textView, text: text as NSString, immediate: immediate)
            let work = DispatchWorkItem { [weak self] in
                self?.rehighlight(
                    text: text,
                    language: lang,
                    colorScheme: scheme,
                    token: token,
                    generation: generation,
                    applyRange: applyRange
                )
            }
            pendingHighlight = work
            let allowImmediate = textLength < EditorRuntimeLimits.nonImmediateHighlightMaxUTF16Length
            if (immediate || lastHighlightedText.isEmpty || lastHighlightToken != token) && allowImmediate {
                highlightQueue.async(execute: work)
            } else {
                let delay: TimeInterval
                if text.utf16.count >= 120_000 {
                    delay = 0.24
                } else if text.utf16.count >= 80_000 {
                    delay = 0.18
                } else {
                    delay = 0.1
                }
                highlightQueue.asyncAfter(deadline: .now() + delay, execute: work)
            }
        }

        private func expandedRange(around range: NSRange, in text: NSString, maxUTF16Padding: Int = 8000) -> NSRange {
            let start = max(0, range.location - maxUTF16Padding)
            let end = min(text.length, NSMaxRange(range) + maxUTF16Padding)
            let startLine = text.lineRange(for: NSRange(location: start, length: 0)).location
            let endAnchor = max(startLine, min(text.length - 1, max(0, end - 1)))
            let endLine = NSMaxRange(text.lineRange(for: NSRange(location: endAnchor, length: 0)))
            return NSRange(location: startLine, length: max(0, endLine - startLine))
        }

        private func preferredHighlightRange(
            textView: UITextView,
            text: NSString,
            immediate: Bool
        ) -> NSRange {
            let fullRange = NSRange(location: 0, length: text.length)
            // Restrict to visible range only for responsive large-file profiles.
            let supportsResponsiveRange =
                parent.isLargeFileMode &&
                supportsResponsiveLargeFileHighlight(language: parent.language, textLength: text.length)
            guard supportsResponsiveRange, text.length >= 100_000 else { return fullRange }
            let visibleRect = CGRect(origin: textView.contentOffset, size: textView.bounds.size).insetBy(dx: 0, dy: -80)
            let glyphRange = textView.layoutManager.glyphRange(forBoundingRect: visibleRect, in: textView.textContainer)
            let charRange = textView.layoutManager.characterRange(forGlyphRange: glyphRange, actualGlyphRange: nil)
            guard charRange.length > 0 else { return fullRange }
            let padding = EditorRuntimeLimits.largeFileJSONVisiblePaddingUTF16
            return expandedRange(around: charRange, in: text, maxUTF16Padding: padding)
        }

        private func rehighlight(
            text: String,
            language: String,
            colorScheme: ColorScheme,
            token: Int,
            generation: Int,
            applyRange: NSRange
        ) {
            let interval = syntaxHighlightSignposter.beginInterval("rehighlight_ios")
            defer { syntaxHighlightSignposter.endInterval("rehighlight_ios", interval) }
            let nsText = text as NSString
            let fullRange = NSRange(location: 0, length: nsText.length)
            let theme = currentEditorTheme(colorScheme: colorScheme)
            let baseColor = UIColor(theme.text)
            let baseFont: UIFont
            if parent.useSystemFont {
                baseFont = UIFont.systemFont(ofSize: parent.fontSize)
            } else if let named = UIFont(name: parent.fontName, size: parent.fontSize) {
                baseFont = named
            } else {
                baseFont = UIFont.monospacedSystemFont(ofSize: parent.fontSize, weight: .regular)
            }

            let colors = SyntaxColors(
                keyword: theme.syntax.keyword,
                string: theme.syntax.string,
                number: theme.syntax.number,
                comment: theme.syntax.comment,
                attribute: theme.syntax.attribute,
                variable: theme.syntax.variable,
                def: theme.syntax.def,
                property: theme.syntax.property,
                meta: theme.syntax.meta,
                tag: theme.syntax.tag,
                atom: theme.syntax.atom,
                builtin: theme.syntax.builtin,
                type: theme.syntax.type
            )
            let syntaxProfile = syntaxProfile(for: language, text: nsText)
            let patterns = getSyntaxPatterns(for: language, colors: colors, profile: syntaxProfile)
            let emphasisPatterns = syntaxEmphasisPatterns(for: language, profile: syntaxProfile)
            var coloredRanges: [(NSRange, UIColor)] = []
            var emphasizedRanges: [(NSRange, SyntaxFontEmphasis)] = []

            if let fastRanges = fastSyntaxColorRanges(
                language: language,
                profile: syntaxProfile,
                text: nsText,
                in: applyRange,
                colors: colors
            ) {
                for (range, color) in fastRanges {
                    guard isValidRange(range, utf16Length: fullRange.length) else { continue }
                    coloredRanges.append((range, UIColor(color)))
                }
            } else {
                for (pattern, color) in patterns {
                    guard let regex = cachedSyntaxRegex(pattern: pattern, options: [.anchorsMatchLines]) else { continue }
                    let matches = regex.matches(in: text, range: applyRange)
                    let uiColor = UIColor(color)
                    for match in matches {
                        guard isValidRange(match.range, utf16Length: fullRange.length) else { continue }
                        coloredRanges.append((match.range, uiColor))
                    }
                }
            }

            if theme.boldKeywords {
                for pattern in emphasisPatterns.keyword {
                    guard let regex = cachedSyntaxRegex(pattern: pattern, options: [.anchorsMatchLines]) else { continue }
                    let matches = regex.matches(in: text, range: applyRange)
                    for match in matches {
                        guard isValidRange(match.range, utf16Length: fullRange.length) else { continue }
                        emphasizedRanges.append((match.range, .keyword))
                    }
                }
            }

            if theme.italicComments {
                for pattern in emphasisPatterns.comment {
                    guard let regex = cachedSyntaxRegex(pattern: pattern, options: [.anchorsMatchLines]) else { continue }
                    let matches = regex.matches(in: text, range: applyRange)
                    for match in matches {
                        guard isValidRange(match.range, utf16Length: fullRange.length) else { continue }
                        emphasizedRanges.append((match.range, .comment))
                    }
                }
            }

            DispatchQueue.main.async { [weak self] in
                guard let self, let textView = self.textView else { return }
                guard generation == self.highlightGeneration else { return }
                guard textView.text == text else { return }
                let selectedRange = textView.selectedRange
                let viewportAnchor = self.currentViewportAnchor(
                    textLength: (text as NSString).length,
                    language: language
                )
                let priorOffset = textView.contentOffset
                let wasFirstResponder = textView.isFirstResponder
                self.isApplyingHighlight = true
                let undoWasEnabled = textView.undoManager?.isUndoRegistrationEnabled ?? false
                if undoWasEnabled {
                    textView.undoManager?.disableUndoRegistration()
                }
                defer {
                    if undoWasEnabled {
                        textView.undoManager?.enableUndoRegistration()
                    }
                }
                textView.textStorage.beginEditing()
                textView.textStorage.removeAttribute(.foregroundColor, range: applyRange)
                textView.textStorage.removeAttribute(.backgroundColor, range: applyRange)
                textView.textStorage.removeAttribute(.underlineStyle, range: applyRange)
                textView.textStorage.addAttribute(.foregroundColor, value: baseColor, range: applyRange)
                textView.textStorage.addAttribute(.font, value: baseFont, range: applyRange)
                let boldKeywordFont = fontWithSymbolicTrait(baseFont, trait: .traitBold)
                let italicCommentFont = fontWithSymbolicTrait(baseFont, trait: .traitItalic)
                for (range, color) in coloredRanges {
                    textView.textStorage.addAttribute(.foregroundColor, value: color, range: range)
                }
                for (range, emphasis) in emphasizedRanges {
                    let font: UIFont
                    switch emphasis {
                    case .keyword:
                        font = boldKeywordFont
                    case .comment:
                        font = italicCommentFont
                    }
                    textView.textStorage.addAttribute(.font, value: font, range: range)
                }
                let suppressLargeFileExtras = self.parent.isLargeFileMode
                let wantsBracketTokens = self.parent.highlightMatchingBrackets && !suppressLargeFileExtras
                let wantsScopeBackground = self.parent.highlightScopeBackground && !suppressLargeFileExtras
                let wantsScopeGuides = self.parent.showScopeGuides && !suppressLargeFileExtras && !self.parent.isLineWrapEnabled && self.parent.language.lowercased() != "swift"
                let needsScopeComputation = (wantsBracketTokens || wantsScopeBackground || wantsScopeGuides)
                    && nsText.length < EditorRuntimeLimits.scopeComputationMaxUTF16Length
                let bracketMatch = needsScopeComputation ? computeBracketScopeMatch(text: text, caretLocation: selectedRange.location) : nil
                let indentationMatch: IndentationScopeMatch? = {
                    guard needsScopeComputation, supportsIndentationScopes(language: self.parent.language) else { return nil }
                    return computeIndentationScopeMatch(text: text, caretLocation: selectedRange.location)
                }()

                if wantsBracketTokens, let match = bracketMatch {
                    let textLength = fullRange.length
                    if isValidRange(match.openRange, utf16Length: textLength) {
                        textView.textStorage.addAttribute(.foregroundColor, value: UIColor.systemOrange, range: match.openRange)
                        textView.textStorage.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: match.openRange)
                        textView.textStorage.addAttribute(.backgroundColor, value: UIColor.systemOrange.withAlphaComponent(0.22), range: match.openRange)
                    }
                    if isValidRange(match.closeRange, utf16Length: textLength) {
                        textView.textStorage.addAttribute(.foregroundColor, value: UIColor.systemOrange, range: match.closeRange)
                        textView.textStorage.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: match.closeRange)
                        textView.textStorage.addAttribute(.backgroundColor, value: UIColor.systemOrange.withAlphaComponent(0.22), range: match.closeRange)
                    }
                }

                if wantsScopeBackground || wantsScopeGuides {
                    let textLength = fullRange.length
                    let scopeRange = bracketMatch?.scopeRange ?? indentationMatch?.scopeRange
                    let guideRanges = bracketMatch?.guideMarkerRanges ?? indentationMatch?.guideMarkerRanges ?? []

                    if wantsScopeBackground, let scope = scopeRange, isValidRange(scope, utf16Length: textLength) {
                        textView.textStorage.addAttribute(.backgroundColor, value: UIColor.systemOrange.withAlphaComponent(0.18), range: scope)
                    }
                    if wantsScopeGuides {
                        for marker in guideRanges {
                            if isValidRange(marker, utf16Length: textLength) {
                                textView.textStorage.addAttribute(.backgroundColor, value: UIColor.systemBlue.withAlphaComponent(0.36), range: marker)
                            }
                        }
                    }
                }
                if self.parent.highlightCurrentLine && !suppressLargeFileExtras {
                    let ns = text as NSString
                    let lineRange = ns.lineRange(for: selectedRange)
                    textView.textStorage.addAttribute(.backgroundColor, value: UIColor.secondarySystemFill, range: lineRange)
                }
                textView.textStorage.endEditing()
                textView.selectedRange = selectedRange
                if wasFirstResponder {
                    textView.setContentOffset(priorOffset, animated: false)
                }
                textView.typingAttributes = [
                    .foregroundColor: baseColor,
                    .font: baseFont
                ]
                self.isApplyingHighlight = false
                self.lastHighlightedText = text
                self.lastLanguage = language
                self.lastColorScheme = colorScheme
                self.lastLineHeight = self.parent.lineHeightMultiple
                self.lastHighlightToken = token
                self.lastSelectionLocation = selectedRange.location
                self.lastHighlightViewportAnchor = viewportAnchor
                self.lastTranslucencyEnabled = self.parent.translucentBackgroundEnabled
                self.syncLineNumberScroll()
            }
        }

        func textViewDidChange(_ textView: UITextView) {
            guard !isApplyingHighlight else { return }
            let didApplyIncrementalMutation = applyPendingTextMutationIfPossible()
            if !didApplyIncrementalMutation {
                syncBindingText(textView.text)
            }
            if shouldRenderLineNumbers() {
                container?.updateLineNumbers(for: textView.text, fontSize: parent.fontSize)
            }
            let nsText = (textView.text ?? "") as NSString
            let caretLocation = min(nsText.length, textView.selectedRange.location)
            pendingEditedRange = nsText.lineRange(for: NSRange(location: caretLocation, length: 0))
            scheduleHighlightIfNeeded(currentText: textView.text)
        }

        func textViewDidChangeSelection(_ textView: UITextView) {
            guard !isApplyingHighlight else { return }
            let nsText = (textView.text ?? "") as NSString
            publishSelectionSnapshot(from: nsText, selectedRange: textView.selectedRange)
            let nsLength = (textView.text as NSString?)?.length ?? 0
            let immediateHighlight = nsLength < 200_000
            scheduleHighlightIfNeeded(currentText: textView.text, immediate: immediateHighlight)
        }

        @available(iOS 16.0, *)
        func textView(
            _ textView: UITextView,
            editMenuForTextIn range: NSRange,
            suggestedActions: [UIMenuElement]
        ) -> UIMenu? {
            guard range.length > 0 else { return UIMenu(children: suggestedActions) }
            let snapshotAction = UIAction(
                title: "Create Code Snapshot",
                image: UIImage(systemName: "camera.viewfinder")
            ) { [weak self, weak textView] _ in
                guard let self, let textView else { return }
                let nsText = (textView.text ?? "") as NSString
                self.publishSelectionSnapshot(from: nsText, selectedRange: textView.selectedRange)
                NotificationCenter.default.post(name: .editorRequestCodeSnapshotFromSelection, object: nil)
            }
            return UIMenu(children: suggestedActions + [snapshotAction])
        }

        private func publishSelectionSnapshot(from text: NSString, selectedRange: NSRange) {
            guard selectedRange.location != NSNotFound,
                  selectedRange.length > 0,
                  NSMaxRange(selectedRange) <= text.length else {
                NotificationCenter.default.post(name: .editorSelectionDidChange, object: "")
                return
            }
            let cappedLength = min(selectedRange.length, 20_000)
            let snippet = text.substring(with: NSRange(location: selectedRange.location, length: cappedLength))
            NotificationCenter.default.post(name: .editorSelectionDidChange, object: snippet)
        }

        func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
            EditorPerformanceMonitor.shared.markFirstKeystroke()
            if text == "\t" {
                if let expansion = EmmetExpander.expansionIfPossible(
                    in: textView.text ?? "",
                    cursorUTF16Location: range.location,
                    language: parent.language
                ) {
                    setPendingTextMutation(range: expansion.range, replacement: expansion.expansion)
                    textView.textStorage.replaceCharacters(in: expansion.range, with: expansion.expansion)
                    let caretLocation = expansion.range.location + expansion.caretOffset
                    textView.selectedRange = NSRange(location: caretLocation, length: 0)
                    textViewDidChange(textView)
                    return false
                }
                let insertion: String
                if parent.indentStyle == "tabs" {
                    insertion = "\t"
                } else {
                    insertion = String(repeating: " ", count: max(1, parent.indentWidth))
                }
                setPendingTextMutation(range: range, replacement: insertion)
                textView.textStorage.replaceCharacters(in: range, with: insertion)
                textView.selectedRange = NSRange(location: range.location + insertion.count, length: 0)
                textViewDidChange(textView)
                return false
            }

            if text == "\n", parent.autoIndentEnabled {
                let ns = textView.text as NSString
                let lineRange = ns.lineRange(for: NSRange(location: range.location, length: 0))
                let currentLine = ns.substring(with: NSRange(
                    location: lineRange.location,
                    length: max(0, range.location - lineRange.location)
                ))
                let indent = currentLine.prefix { $0 == " " || $0 == "\t" }
                let normalized = normalizedIndentation(String(indent))
                let replacement = "\n" + normalized
                setPendingTextMutation(range: range, replacement: replacement)
                textView.textStorage.replaceCharacters(in: range, with: replacement)
                textView.selectedRange = NSRange(location: range.location + replacement.count, length: 0)
                textViewDidChange(textView)
                return false
            }

            if parent.autoCloseBracketsEnabled, text.count == 1 {
                let pairs: [String: String] = ["(": ")", "[": "]", "{": "}", "\"": "\"", "'": "'"]
                if let closing = pairs[text] {
                    let insertion = text + closing
                    setPendingTextMutation(range: range, replacement: insertion)
                    textView.textStorage.replaceCharacters(in: range, with: insertion)
                    textView.selectedRange = NSRange(location: range.location + 1, length: 0)
                    textViewDidChange(textView)
                    return false
                }
            }

            setPendingTextMutation(range: range, replacement: text)
            return true
        }

        private func normalizedIndentation(_ indent: String) -> String {
            let width = max(1, parent.indentWidth)
            switch parent.indentStyle {
            case "tabs":
                let spacesCount = indent.filter { $0 == " " }.count
                let tabsCount = indent.filter { $0 == "\t" }.count
                let totalSpaces = spacesCount + (tabsCount * width)
                let tabs = String(repeating: "\t", count: totalSpaces / width)
                let leftover = String(repeating: " ", count: totalSpaces % width)
                return tabs + leftover
            default:
                let tabsCount = indent.filter { $0 == "\t" }.count
                let spacesCount = indent.filter { $0 == " " }.count
                let totalSpaces = spacesCount + (tabsCount * width)
                return String(repeating: " ", count: totalSpaces)
            }
        }

        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            syncLineNumberScroll()
            guard let textView else { return }
            let textLength = (textView.text as NSString?)?.length ?? 0
            if textLength >= 100_000 && supportsResponsiveLargeFileHighlight(language: parent.language, textLength: textLength) {
                scheduleHighlightIfNeeded(currentText: textView.text)
            }
        }

        func syncLineNumberScroll() {
            guard shouldRenderLineNumbers(), let textView else { return }
            let offsetY = textView.contentOffset.y
            if abs(lastLineNumberContentOffsetY - offsetY) <= 0.5 {
                return
            }
            lastLineNumberContentOffsetY = offsetY
            container?.lineNumberView.setNeedsDisplay()
        }
    }
}
#endif
