import Foundation
import SwiftData

class WordReplacementService {
    static let shared = WordReplacementService()

    private init() {}

    func applyReplacements(to text: String, using context: ModelContext) -> String {
        let descriptor = FetchDescriptor<WordReplacement>(
            predicate: #Predicate { $0.isEnabled }
        )

        guard let replacements = try? context.fetch(descriptor), !replacements.isEmpty else {
            return text // No replacements to apply
        }

        var modifiedText = text
        ProatDebugLog.write("REPLACE | regels=\(replacements.count) | in=\(String(text.prefix(80)))")

        // Longest-first so specific triggers match before shorter overlapping ones
        let sortedReplacements = replacements.sorted {
            $0.originalText.count > $1.originalText.count
        }

        // Apply replacements (case-insensitive)
        for replacement in sortedReplacements {
            let originalGroup = replacement.originalText
            let replacementText = replacement.replacementText

            // Regex-regel ZÉÉR EERST detecteren — vóór de komma-split. Anders
            // knipt `split(separator: ",")` een quantifier als {1,6} kapot
            // (die bevat een komma) en is het patroon onbruikbaar.
            if let regexPattern = Self.regexPattern(from: originalGroup.trimmingCharacters(in: .whitespacesAndNewlines)) {
                if let regex = try? NSRegularExpression(pattern: regexPattern, options: .caseInsensitive) {
                    let range = NSRange(modifiedText.startIndex..., in: modifiedText)
                    let hits = regex.numberOfMatches(in: modifiedText, options: [], range: range)
                    modifiedText = regex.stringByReplacingMatches(
                        in: modifiedText,
                        options: [],
                        range: range,
                        withTemplate: NSRegularExpression.escapedTemplate(for: replacementText)
                    )
                    ProatDebugLog.write("REPLACE regex | /\(regexPattern)/ | hits=\(hits) | →\(replacementText)")
                } else {
                    ProatDebugLog.write("REPLACE regex ONGELDIG | /\(regexPattern)/")
                }
                continue
            }

            // Gewone (niet-regex) regel: komma-gescheiden varianten.
            let variants = originalGroup
                .split(separator: ",")
                .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
                .filter { !$0.isEmpty }
                .sorted { $0.count > $1.count }

            for original in variants {
                let usesBoundaries = usesWordBoundaries(for: original)

                if usesBoundaries {
                    // Lookarounds instead of \b so punctuation acts as a word boundary
                    let escaped = NSRegularExpression.escapedPattern(for: original)
                    let pattern = "(?<![a-zA-Z0-9])\(escaped)(?![a-zA-Z0-9])"
                    if let regex = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive) {
                        let range = NSRange(modifiedText.startIndex..., in: modifiedText)
                        modifiedText = regex.stringByReplacingMatches(
                            in: modifiedText,
                            options: [],
                            range: range,
                            withTemplate: replacementText
                        )
                    }
                } else {
                    // Fallback substring replace for non-spaced scripts
                    modifiedText = modifiedText.replacingOccurrences(of: original, with: replacementText, options: .caseInsensitive)
                }
            }
        }

        return modifiedText
    }

    /// Herkent een regex-trigger van de vorm `/patroon/` of `/patroon/i`.
    /// Geeft het kale patroon terug (zonder slashes/flag), of nil bij een
    /// gewone letterlijke trigger. Let op: kommas in een patroon werken niet
    /// (de triggerlijst splitst op komma) — gebruik tekenklassen i.p.v. `,`.
    static func regexPattern(from trigger: String) -> String? {
        guard trigger.count >= 3, trigger.hasPrefix("/") else { return nil }
        if trigger.hasSuffix("/") {
            return String(trigger.dropFirst().dropLast())
        }
        if trigger.hasSuffix("/i") {
            return String(trigger.dropFirst().dropLast(2))
        }
        return nil
    }

    private func usesWordBoundaries(for text: String) -> Bool {
        // Returns false for languages without spaces (CJK, Thai), true for spaced languages
        let nonSpacedScripts: [ClosedRange<UInt32>] = [
            0x3040...0x309F, // Hiragana
            0x30A0...0x30FF, // Katakana
            0x4E00...0x9FFF, // CJK Unified Ideographs
            0xAC00...0xD7AF, // Hangul Syllables
            0x0E00...0x0E7F, // Thai
        ]

        for scalar in text.unicodeScalars {
            for range in nonSpacedScripts {
                if range.contains(scalar.value) {
                    return false
                }
            }
        }

        return true
    }
}
