//
//  String+Extensions.swift
//  oAI
//
//  String utility extensions
//
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2026 Rune Olsen
//
// This file is part of oAI.
//
// oAI is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// oAI is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
// Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with oAI. If not, see <https://www.gnu.org/licenses/>.


import Foundation

extension String {
    // MARK: - Command Parsing
    
    var isSlashCommand: Bool {
        hasPrefix("/")
    }
    
    func parseCommand() -> (command: String, args: [String])? {
        guard isSlashCommand else { return nil }
        
        let parts = self.split(separator: " ", omittingEmptySubsequences: true)
            .map(String.init)
        
        guard let command = parts.first else { return nil }
        let args = Array(parts.dropFirst())
        
        return (command, args)
    }
    
    // MARK: - File Attachment Parsing
    
    func parseFileAttachments() -> (cleanText: String, filePaths: [String]) {
        var cleanText = self
        var filePaths: [String] = []
        
        // Pattern 1: @<filepath>
        let anglePattern = #"@<([^>]+)>"#
        if let regex = try? NSRegularExpression(pattern: anglePattern) {
            let matches = regex.matches(in: self, range: NSRange(self.startIndex..., in: self))
            for match in matches.reversed() {
                if let range = Range(match.range(at: 1), in: self) {
                    let path = String(self[range])
                    filePaths.insert(path, at: 0)
                }
                if let fullRange = Range(match.range, in: self) {
                    cleanText.removeSubrange(fullRange)
                }
            }
        }
        
        // Pattern 2: @filepath (starting with /, ~, ., or drive letter)
        let directPattern = #"@([~/.][\S]+|[A-Za-z]:[\\\/][\S]+)"#
        if let regex = try? NSRegularExpression(pattern: directPattern) {
            let matches = regex.matches(in: cleanText, range: NSRange(cleanText.startIndex..., in: cleanText))
            for match in matches.reversed() {
                if let range = Range(match.range(at: 1), in: cleanText) {
                    let path = String(cleanText[range])
                    if !filePaths.contains(path) {
                        filePaths.insert(path, at: 0)
                    }
                }
                if let fullRange = Range(match.range, in: cleanText) {
                    cleanText.removeSubrange(fullRange)
                }
            }
        }
        
        return (cleanText.trimmingCharacters(in: .whitespaces), filePaths)
    }
    
    // MARK: - Token Estimation
    
    func estimateTokens() -> Int {
        // Rough estimation: ~4 characters per token
        // This is approximate; Phase 2 will use proper tokenizer
        return max(1, count / 4)
    }
    
    // MARK: - Nil coalescing helpers

    /// Returns nil if the string is empty, otherwise self.
    var nonEmptyOrNil: String? {
        isEmpty ? nil : self
    }

    // MARK: - Truncation
    
    func truncated(to length: Int, trailing: String = "...") -> String {
        if count <= length {
            return self
        }
        let endIndex = index(startIndex, offsetBy: length - trailing.count)
        return String(self[..<endIndex]) + trailing
    }
}
