import Foundation

// MARK: - Field Validation Helpers

struct ValidationHelpers {
    // MARK: - Email Validation

    static func validateEmail(_ email: String) -> ValidationResult {
        guard !email.isBlank else {
            return .invalid("Email is required")
        }

        guard email.isValidEmail else {
            return .invalid("Please enter a valid email address")
        }

        return .valid
    }

    // MARK: - Password Validation

    static func validatePassword(_ password: String, minLength: Int = 8) -> ValidationResult {
        guard !password.isEmpty else {
            return .invalid("Password is required")
        }

        guard password.count >= minLength else {
            return .invalid("Password must be at least \(minLength) characters")
        }

        return .valid
    }

    static func validatePasswordConfirmation(_ password: String, confirmation: String) -> ValidationResult {
        guard password == confirmation else {
            return .invalid("Passwords do not match")
        }

        return .valid
    }

    // MARK: - Name Validation

    static func validateName(_ name: String, fieldName: String = "Name") -> ValidationResult {
        guard !name.isBlank else {
            return .invalid("\(fieldName) is required")
        }

        guard name.count >= 2 else {
            return .invalid("\(fieldName) must be at least 2 characters")
        }

        return .valid
    }

    // MARK: - Phone Validation

    static func validatePhone(_ phone: String) -> ValidationResult {
        guard !phone.isBlank else {
            return .invalid("Phone number is required")
        }

        guard phone.isValidPhone else {
            return .invalid("Please enter a valid phone number")
        }

        return .valid
    }

    // MARK: - Required Field Validation

    static func validateRequired(_ value: String, fieldName: String) -> ValidationResult {
        guard !value.isBlank else {
            return .invalid("\(fieldName) is required")
        }

        return .valid
    }

    // MARK: - Number Validation

    static func validateNumber(_ value: String, fieldName: String, min: Double? = nil, max: Double? = nil) -> ValidationResult {
        guard !value.isBlank else {
            return .invalid("\(fieldName) is required")
        }

        guard let number = Double(value) else {
            return .invalid("\(fieldName) must be a valid number")
        }

        if let min = min, number < min {
            return .invalid("\(fieldName) must be at least \(min)")
        }

        if let max = max, number > max {
            return .invalid("\(fieldName) must be at most \(max)")
        }

        return .valid
    }

    // MARK: - Integer Validation

    static func validateInteger(_ value: String, fieldName: String, min: Int? = nil, max: Int? = nil) -> ValidationResult {
        guard !value.isBlank else {
            return .invalid("\(fieldName) is required")
        }

        guard let number = Int(value) else {
            return .invalid("\(fieldName) must be a whole number")
        }

        if let min = min, number < min {
            return .invalid("\(fieldName) must be at least \(min)")
        }

        if let max = max, number > max {
            return .invalid("\(fieldName) must be at most \(max)")
        }

        return .valid
    }

    // MARK: - Length Validation

    static func validateLength(_ value: String, fieldName: String, min: Int? = nil, max: Int? = nil) -> ValidationResult {
        if let min = min, value.count < min {
            return .invalid("\(fieldName) must be at least \(min) characters")
        }

        if let max = max, value.count > max {
            return .invalid("\(fieldName) must be at most \(max) characters")
        }

        return .valid
    }

    // MARK: - URL Validation

    static func validateURL(_ urlString: String) -> ValidationResult {
        guard !urlString.isBlank else {
            return .invalid("URL is required")
        }

        guard URL(string: urlString) != nil else {
            return .invalid("Please enter a valid URL")
        }

        return .valid
    }

    // MARK: - Custom Validation

    static func validateCustom(_ value: String, fieldName: String, validator: (String) -> Bool, errorMessage: String) -> ValidationResult {
        guard !value.isBlank else {
            return .invalid("\(fieldName) is required")
        }

        guard validator(value) else {
            return .invalid(errorMessage)
        }

        return .valid
    }
}

// MARK: - Validation Result

enum ValidationResult {
    case valid
    case invalid(String)

    var isValid: Bool {
        if case .valid = self {
            return true
        }
        return false
    }

    var errorMessage: String? {
        if case .invalid(let message) = self {
            return message
        }
        return nil
    }
}

// MARK: - Form Validator Class

class FormValidator {
    private var validations: [(String, () -> ValidationResult)] = []

    func add(fieldName: String, validation: @escaping () -> ValidationResult) {
        validations.append((fieldName, validation))
    }

    func validate() -> FormValidationResult {
        var errors: [String: String] = [:]

        for (fieldName, validation) in validations {
            let result = validation()
            if case .invalid(let message) = result {
                errors[fieldName] = message
            }
        }

        return errors.isEmpty ? .valid : .invalid(errors)
    }

    func clear() {
        validations.removeAll()
    }
}

enum FormValidationResult {
    case valid
    case invalid([String: String])

    var isValid: Bool {
        if case .valid = self {
            return true
        }
        return false
    }

    var errors: [String: String] {
        if case .invalid(let errors) = self {
            return errors
        }
        return [:]
    }
}
