import Foundation

/// Client-side validation for display name and username fields.
/// Used in profile editing (SettingsView / ProfileEditView).
enum ProfileValidator {

    // MARK: - Display Name

    enum DisplayNameError: LocalizedError {
        case empty
        case tooLong
        case tooManyWords

        var errorDescription: String? {
            switch self {
            case .empty: return "Name cannot be empty"
            case .tooLong: return "Name cannot exceed 64 characters"
            case .tooManyWords: return "Maximum two words (first and last name)"
            }
        }
    }

    static func validateDisplayName(_ name: String) -> DisplayNameError? {
        let trimmed = name.trimmingCharacters(in: .whitespaces)
        if trimmed.isEmpty { return .empty }
        if trimmed.count > 64 { return .tooLong }
        // Maximum 2 words (first name + last name)
        let words = trimmed.split(whereSeparator: { $0.isWhitespace })
        if words.count > 2 { return .tooManyWords }
        return nil
    }

    /// Sanitizes display name input: collapses multiple spaces,
    /// prevents more than one space (two words max).
    static func sanitizeDisplayName(_ name: String) -> String {
        // Collapse multiple consecutive spaces into one
        let collapsed = name.replacingOccurrences(
            of: "\\s{2,}", with: " ", options: .regularExpression
        )
        // If already has one space and user tries to add another, block it
        let spaceCount = collapsed.filter { $0 == " " }.count
        if spaceCount > 1 {
            let parts = collapsed.split(separator: " ", maxSplits: 1)
            return parts.joined(separator: " ")
        }
        return collapsed
    }

    // MARK: - Username

    enum UsernameError: LocalizedError {
        case tooShort
        case tooLong
        case invalidCharacters
        case mustStartWithLetter
        case reserved

        var errorDescription: String? {
            switch self {
            case .tooShort: return "Username must be at least 5 characters"
            case .tooLong: return "Username cannot exceed 32 characters"
            case .invalidCharacters: return "Only lowercase letters, numbers, and underscores"
            case .mustStartWithLetter: return "Must start with a letter"
            case .reserved: return "This username is not available"
            }
        }
    }

    private static let reservedNames: Set<String> = [
        "rosetta", "admin", "support", "help", "system",
        "moderator", "official", "staff", "bot", "service",
    ]

    /// Validate username. Returns `nil` if valid, or the first error found.
    /// Empty username is allowed (user may not have chosen one yet).
    static func validateUsername(_ username: String) -> UsernameError? {
        let lowered = username.lowercased().trimmingCharacters(in: .whitespaces)
        guard !lowered.isEmpty else { return nil } // empty is OK
        if lowered.count < 5 { return .tooShort }
        if lowered.count > 32 { return .tooLong }
        guard let first = lowered.first, first.isLetter else { return .mustStartWithLetter }
        if lowered.range(of: "^[a-z][a-z0-9_]{4,31}$", options: .regularExpression) == nil {
            return .invalidCharacters
        }
        if reservedNames.contains(lowered) { return .reserved }
        return nil
    }
}
