use crate::ir::tag::Tag;
use crate::ir::value_type::ValueType;
use num_bigint::BigInt;
use regex::Regex;
use std::any::Any;
use std::fmt::Debug;
use std::sync::LazyLock;

#[derive(Debug, Clone)]
pub struct ValidationResult {
    pub is_valid: bool,
    pub errors: Vec<String>,
}

impl ValidationResult {
    pub fn new() -> Self {
        Self {
            is_valid: true,
            errors: Vec::new(),
        }
    }
}

impl Default for ValidationResult {
    fn default() -> Self {
        Self::new()
    }
}

impl ValidationResult {
    pub fn add_error(&mut self, error: String) {
        self.is_valid = false;
        self.errors.push(error);
    }
}

pub struct MmValidator {
    email_regex: &'static Regex,
}

impl Default for MmValidator {
    fn default() -> Self {
        Self {
            email_regex: &EMAIL_REGEX,
        }
    }
}

impl MmValidator {
    pub fn new() -> Self {
        Default::default()
    }

    pub fn validate(&self, value: &dyn Any, tag: &Tag) -> ValidationResult {
        let mut result = ValidationResult::new();

        match tag.value_type {
            ValueType::Bool => self.validate_bool(value, tag, &mut result),
            ValueType::I => self.validate_i(value, tag, &mut result),
            ValueType::I8 => self.validate_i8(value, tag, &mut result),
            ValueType::I16 => self.validate_i16(value, tag, &mut result),
            ValueType::I32 => self.validate_i32(value, tag, &mut result),
            ValueType::I64 => self.validate_i64(value, tag, &mut result),
            ValueType::U => self.validate_u(value, tag, &mut result),
            ValueType::U8 => self.validate_u8(value, tag, &mut result),
            ValueType::U16 => self.validate_u16(value, tag, &mut result),
            ValueType::U32 => self.validate_u32(value, tag, &mut result),
            ValueType::U64 => self.validate_u64(value, tag, &mut result),
            ValueType::Bigint => self.validate_bigint(value, tag, &mut result),
            ValueType::F32 => self.validate_f32(value, tag, &mut result),
            ValueType::F64 => self.validate_f64(value, tag, &mut result),
            ValueType::Decimal => self.validate_f(value, tag, &mut result),
            ValueType::Str => self.validate_str(value, tag, &mut result),
            ValueType::Email => self.validate_email(value, tag, &mut result),
            ValueType::Url => self.validate_url(value, tag, &mut result),
            ValueType::Bytes => self.validate_bytes(value, tag, &mut result),
            ValueType::Uuid => self.validate_uuid(value, tag, &mut result),
            ValueType::Datetime | ValueType::Date | ValueType::Time => {
                self.validate_datetime(value, tag, &mut result)
            }
            ValueType::Enum => self.validate_enum(value, tag, &mut result),
            ValueType::Arr | ValueType::Vec => self.validate_arr(value, tag, &mut result),
            ValueType::Obj => self.validate_obj(value, tag, &mut result),
            _ => {}
        }

        result
    }

    fn validate_bool(&self, value: &dyn Any, _tag: &Tag, result: &mut ValidationResult) {
        if value.downcast_ref::<bool>().is_some() {
        } else {
            result.add_error("value must be a boolean".to_string());
        }
    }

    fn validate_i(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(int_value) = value.downcast_ref::<i64>() {
            if *int_value == 0 {
                result.add_error("type int not allow empty value 0".to_string());
                return;
            }
            let val64 = *int_value;
            if let Some(ref min_str) = tag.min {
                if let Ok(mini) = min_str.parse::<i64>() {
                    if val64 < mini {
                        result.add_error(format!(
                            "value {} is less than the minimum limit {}",
                            val64, mini
                        ));
                    }
                }
            }
            if let Some(ref max_str) = tag.max {
                if let Ok(maxi) = max_str.parse::<i64>() {
                    if val64 > maxi {
                        result.add_error(format!(
                            "value {} exceeds the maximum limit {}",
                            val64, maxi
                        ));
                    }
                }
            }
        } else {
            result.add_error("value must be a number".to_string());
        }
    }

    fn validate_i8(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(int_value) = value.downcast_ref::<i8>() {
            if *int_value == 0 {
                result.add_error("type int8 not allow empty value 0".to_string());
                return;
            }
            let val64 = *int_value as i64;
            if let Some(ref min_str) = tag.min {
                match min_str.parse::<i64>() {
                    Ok(mini) => {
                        if mini < i8::MIN as i64 || mini > i8::MAX as i64 {
                            result
                                .add_error(format!("failed to parse tag.min as int8: {}", min_str));
                        } else if val64 < mini {
                            result.add_error(format!(
                                "value {} is less than the minimum limit {}",
                                val64, mini
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.min as int8: {}", min_str));
                    }
                }
            }
            if let Some(ref max_str) = tag.max {
                match max_str.parse::<i64>() {
                    Ok(maxi) => {
                        if maxi < i8::MIN as i64 || maxi > i8::MAX as i64 {
                            result
                                .add_error(format!("failed to parse tag.max as int8: {}", max_str));
                        } else if val64 > maxi {
                            result.add_error(format!(
                                "value {} exceeds the maximum limit {}",
                                val64, maxi
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.max as int8: {}", max_str));
                    }
                }
            }
        } else {
            result.add_error("value must be an int8".to_string());
        }
    }

    fn validate_i16(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(int_value) = value.downcast_ref::<i16>() {
            if *int_value == 0 {
                result.add_error("type int16 not allow empty value 0".to_string());
                return;
            }
            let val64 = *int_value as i64;
            if let Some(ref min_str) = tag.min {
                match min_str.parse::<i64>() {
                    Ok(mini) => {
                        if mini < i16::MIN as i64 || mini > i16::MAX as i64 {
                            result.add_error(format!(
                                "failed to parse tag.min as int16: {}",
                                min_str
                            ));
                        } else if val64 < mini {
                            result.add_error(format!(
                                "value {} is less than the minimum limit {}",
                                val64, mini
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.min as int16: {}", min_str));
                    }
                }
            }
            if let Some(ref max_str) = tag.max {
                match max_str.parse::<i64>() {
                    Ok(maxi) => {
                        if maxi < i16::MIN as i64 || maxi > i16::MAX as i64 {
                            result.add_error(format!(
                                "failed to parse tag.max as int16: {}",
                                max_str
                            ));
                        } else if val64 > maxi {
                            result.add_error(format!(
                                "value {} exceeds the maximum limit {}",
                                val64, maxi
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.max as int16: {}", max_str));
                    }
                }
            }
        } else {
            result.add_error("value must be an int16".to_string());
        }
    }

    fn validate_i32(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(int_value) = value.downcast_ref::<i32>() {
            if *int_value == 0 {
                result.add_error("type int32 not allow empty value 0".to_string());
                return;
            }
            let val64 = *int_value as i64;
            if let Some(ref min_str) = tag.min {
                match min_str.parse::<i64>() {
                    Ok(mini) => {
                        if mini < i32::MIN as i64 || mini > i32::MAX as i64 {
                            result.add_error(format!(
                                "failed to parse tag.min as int32: {}",
                                min_str
                            ));
                        } else if val64 < mini {
                            result.add_error(format!(
                                "value {} is less than the minimum limit {}",
                                val64, mini
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.min as int32: {}", min_str));
                    }
                }
            }
            if let Some(ref max_str) = tag.max {
                match max_str.parse::<i64>() {
                    Ok(maxi) => {
                        if maxi < i32::MIN as i64 || maxi > i32::MAX as i64 {
                            result.add_error(format!(
                                "failed to parse tag.max as int32: {}",
                                max_str
                            ));
                        } else if val64 > maxi {
                            result.add_error(format!(
                                "value {} exceeds the maximum limit {}",
                                val64, maxi
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.max as int32: {}", max_str));
                    }
                }
            }
        } else {
            result.add_error("value must be an int32".to_string());
        }
    }

    fn validate_i64(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(int_value) = value.downcast_ref::<i64>() {
            if *int_value == 0 {
                result.add_error("type int64 not allow empty value 0".to_string());
                return;
            }
            let val = *int_value;
            if let Some(ref min_str) = tag.min {
                match min_str.parse::<i64>() {
                    Ok(mini) => {
                        if val < mini {
                            result.add_error(format!(
                                "value {} is less than the minimum limit {}",
                                val, mini
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.min as int64: {}", min_str));
                    }
                }
            }
            if let Some(ref max_str) = tag.max {
                match max_str.parse::<i64>() {
                    Ok(maxi) => {
                        if val > maxi {
                            result.add_error(format!(
                                "value {} exceeds the maximum limit {}",
                                val, maxi
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.max as int64: {}", max_str));
                    }
                }
            }
        } else {
            result.add_error("value must be an int64".to_string());
        }
    }

    fn validate_u(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(int_value) = value.downcast_ref::<u32>() {
            if *int_value == 0 {
                result.add_error("type uint not allow empty value 0".to_string());
                return;
            }
            let val64 = *int_value as u64;
            if let Some(ref min_str) = tag.min {
                if let Ok(mini) = min_str.parse::<u64>() {
                    if val64 < mini {
                        result.add_error(format!(
                            "value {} is less than the minimum limit {}",
                            val64, mini
                        ));
                    }
                }
            }
            if let Some(ref max_str) = tag.max {
                if let Ok(maxi) = max_str.parse::<u64>() {
                    if val64 > maxi {
                        result.add_error(format!(
                            "value {} exceeds the maximum limit {}",
                            val64, maxi
                        ));
                    }
                }
            }
        } else {
            result.add_error("value must be a uint".to_string());
        }
    }

    fn validate_u8(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(int_value) = value.downcast_ref::<u8>() {
            if *int_value == 0 {
                result.add_error("type uint8 not allow empty value 0".to_string());
                return;
            }
            let val64 = *int_value as u64;
            if let Some(ref min_str) = tag.min {
                match min_str.parse::<u64>() {
                    Ok(mini) => {
                        if mini < u8::MIN as u64 || mini > u8::MAX as u64 {
                            result.add_error(format!(
                                "failed to parse tag.min as uint8: {}",
                                min_str
                            ));
                        } else if val64 < mini {
                            result.add_error(format!(
                                "value {} is less than the minimum limit {}",
                                val64, mini
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.min as uint8: {}", min_str));
                    }
                }
            }
            if let Some(ref max_str) = tag.max {
                match max_str.parse::<u64>() {
                    Ok(maxi) => {
                        if maxi < u8::MIN as u64 || maxi > u8::MAX as u64 {
                            result.add_error(format!(
                                "failed to parse tag.max as uint8: {}",
                                max_str
                            ));
                        } else if val64 > maxi {
                            result.add_error(format!(
                                "value {} exceeds the maximum limit {}",
                                val64, maxi
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.max as uint8: {}", max_str));
                    }
                }
            }
        } else {
            result.add_error("value must be a uint8".to_string());
        }
    }

    fn validate_u16(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(int_value) = value.downcast_ref::<u16>() {
            if *int_value == 0 {
                result.add_error("type uint16 not allow empty value 0".to_string());
                return;
            }
            let val64 = *int_value as u64;
            if let Some(ref min_str) = tag.min {
                match min_str.parse::<u64>() {
                    Ok(mini) => {
                        if mini < u16::MIN as u64 || mini > u16::MAX as u64 {
                            result.add_error(format!(
                                "failed to parse tag.min as uint16: {}",
                                min_str
                            ));
                        } else if val64 < mini {
                            result.add_error(format!(
                                "value {} is less than the minimum limit {}",
                                val64, mini
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.min as uint16: {}", min_str));
                    }
                }
            }
            if let Some(ref max_str) = tag.max {
                match max_str.parse::<u64>() {
                    Ok(maxi) => {
                        if maxi < u16::MIN as u64 || maxi > u16::MAX as u64 {
                            result.add_error(format!(
                                "failed to parse tag.max as uint16: {}",
                                max_str
                            ));
                        } else if val64 > maxi {
                            result.add_error(format!(
                                "value {} exceeds the maximum limit {}",
                                val64, maxi
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.max as uint16: {}", max_str));
                    }
                }
            }
        } else {
            result.add_error("value must be a uint16".to_string());
        }
    }

    fn validate_u32(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(int_value) = value.downcast_ref::<u32>() {
            if *int_value == 0 {
                result.add_error("type uint32 not allow empty value 0".to_string());
                return;
            }
            let val64 = *int_value as u64;
            if let Some(ref min_str) = tag.min {
                match min_str.parse::<u64>() {
                    Ok(mini) => {
                        if mini < u32::MIN as u64 || mini > u32::MAX as u64 {
                            result.add_error(format!(
                                "failed to parse tag.min as uint32: {}",
                                min_str
                            ));
                        } else if val64 < mini {
                            result.add_error(format!(
                                "value {} is less than the minimum limit {}",
                                val64, mini
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.min as uint32: {}", min_str));
                    }
                }
            }
            if let Some(ref max_str) = tag.max {
                match max_str.parse::<u64>() {
                    Ok(maxi) => {
                        if maxi < u32::MIN as u64 || maxi > u32::MAX as u64 {
                            result.add_error(format!(
                                "failed to parse tag.max as uint32: {}",
                                max_str
                            ));
                        } else if val64 > maxi {
                            result.add_error(format!(
                                "value {} exceeds the maximum limit {}",
                                val64, maxi
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.max as uint32: {}", max_str));
                    }
                }
            }
        } else {
            result.add_error("value must be a uint32".to_string());
        }
    }

    fn validate_u64(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(int_value) = value.downcast_ref::<u64>() {
            if *int_value == 0 {
                result.add_error("type uint64 not allow empty value 0".to_string());
                return;
            }
            let val = *int_value;
            if let Some(ref min_str) = tag.min {
                match min_str.parse::<u64>() {
                    Ok(mini) => {
                        if val < mini {
                            result.add_error(format!(
                                "value {} is less than the minimum limit {}",
                                val, mini
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.min as uint64: {}", min_str));
                    }
                }
            }
            if let Some(ref max_str) = tag.max {
                match max_str.parse::<u64>() {
                    Ok(maxi) => {
                        if val > maxi {
                            result.add_error(format!(
                                "value {} exceeds the maximum limit {}",
                                val, maxi
                            ));
                        }
                    }
                    Err(_) => {
                        result.add_error(format!("failed to parse tag.max as uint64: {}", max_str));
                    }
                }
            }
        } else {
            result.add_error("value must be a uint64".to_string());
        }
    }

    fn validate_bigint(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(big_int) = value.downcast_ref::<BigInt>() {
            if big_int.sign() == num_bigint::Sign::NoSign {
                result.add_error("type big.Int not allow empty value 0".to_string());
                return;
            }
            if let Some(ref min_str) = tag.min {
                if let Ok(mini) = min_str.parse::<BigInt>() {
                    if big_int < &mini {
                        result.add_error(format!("big.Int length {} < min {}", big_int, mini));
                    }
                }
            }
            if let Some(ref max_str) = tag.max {
                if let Ok(maxi) = max_str.parse::<BigInt>() {
                    if big_int > &maxi {
                        result.add_error(format!("big.Int length {} > max {}", big_int, maxi));
                    }
                }
            }
        } else {
            result.add_error("value must be a big.Int".to_string());
        }
    }

    fn validate_f32(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(float_value) = value.downcast_ref::<f32>() {
            if *float_value == 0.0 {
                result.add_error("type float32 not allow empty value 0.0".to_string());
                return;
            }
            let val64 = *float_value as f64;
            if let Some(ref min_str) = tag.min {
                match min_str.parse::<f64>() {
                    Ok(mini) => {
                        if mini < f32::MIN as f64 || mini > f32::MAX as f64 {
                            result.add_error(format!(
                                "failed to parse tag.min as float32: {}",
                                min_str
                            ));
                        } else if val64 < mini {
                            result.add_error(format!("{} < min {}", val64, mini));
                        }
                    }
                    Err(_) => {
                        result
                            .add_error(format!("failed to parse tag.min as float32: {}", min_str));
                    }
                }
            }
            if let Some(ref max_str) = tag.max {
                match max_str.parse::<f64>() {
                    Ok(maxi) => {
                        if maxi < f32::MIN as f64 || maxi > f32::MAX as f64 {
                            result.add_error(format!(
                                "failed to parse tag.max as float32: {}",
                                max_str
                            ));
                        } else if val64 > maxi {
                            result.add_error(format!("{} > max {}", val64, maxi));
                        }
                    }
                    Err(_) => {
                        result
                            .add_error(format!("failed to parse tag.max as float32: {}", max_str));
                    }
                }
            }
        } else {
            result.add_error("value must be a float32".to_string());
        }
    }

    fn validate_f64(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(float_value) = value.downcast_ref::<f64>() {
            if *float_value == 0.0 {
                result.add_error("type float64 not allow empty value 0.0".to_string());
                return;
            }
            let val = *float_value;
            if let Some(ref min_str) = tag.min {
                match min_str.parse::<f64>() {
                    Ok(mini) => {
                        if !(f64::MIN..=f64::MAX).contains(&mini) {
                            result.add_error(format!(
                                "failed to parse tag.min as float64: {}",
                                min_str
                            ));
                        } else if val < mini {
                            result.add_error(format!("{} < min {}", val, mini));
                        }
                    }
                    Err(_) => {
                        result
                            .add_error(format!("failed to parse tag.min as float64: {}", min_str));
                    }
                }
            }
            if let Some(ref max_str) = tag.max {
                match max_str.parse::<f64>() {
                    Ok(maxi) => {
                        if !(f64::MIN..=f64::MAX).contains(&maxi) {
                            result.add_error(format!(
                                "failed to parse tag.max as float64: {}",
                                max_str
                            ));
                        } else if val > maxi {
                            result.add_error(format!("{} > max {}", val, maxi));
                        }
                    }
                    Err(_) => {
                        result
                            .add_error(format!("failed to parse tag.max as float64: {}", max_str));
                    }
                }
            }
        } else {
            result.add_error("value must be a float64".to_string());
        }
    }

    fn validate_f(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(float_value) = value.downcast_ref::<f64>() {
            match tag.value_type {
                ValueType::F32 => {
                    if *float_value < f32::MIN as f64 || *float_value > f32::MAX as f64 {
                        result.add_error("value out of range for float32".to_string());
                    }
                }
                ValueType::F64 => {
                    if *float_value < f64::MIN || *float_value > f64::MAX {
                        result.add_error("value out of range for float64".to_string());
                    }
                }
                ValueType::Decimal => {
                    if let Some(ref min_str) = tag.min {
                        if let Ok(mini) = min_str.parse::<f64>() {
                            if *float_value < mini {
                                result.add_error(format!("{} < min {}", float_value, mini));
                            }
                        }
                    }
                    if let Some(ref max_str) = tag.max {
                        if let Ok(maxi) = max_str.parse::<f64>() {
                            if *float_value > maxi {
                                result.add_error(format!("{} > max {}", float_value, maxi));
                            }
                        }
                    }
                }
                _ => {}
            }
        } else {
            result.add_error("value must be a float".to_string());
        }
    }

    fn validate_str(&self, value: &dyn Any, _tag: &Tag, result: &mut ValidationResult) {
        if let Some(str_value) = value.downcast_ref::<String>() {
            if str_value.is_empty() {
                result.add_error("value is empty".to_string());
            }
        } else {
            result.add_error("value must be a string".to_string());
        }
    }

    fn validate_email(&self, value: &dyn Any, _tag: &Tag, result: &mut ValidationResult) {
        if let Some(email) = value.downcast_ref::<String>() {
            if email.is_empty() {
                result.add_error("value is empty".to_string());
            } else if !self.email_regex.is_match(email) {
                result.add_error("value is not a valid email".to_string());
            }
        } else {
            result.add_error("value must be a string".to_string());
        }
    }

    fn validate_url(&self, value: &dyn Any, _tag: &Tag, result: &mut ValidationResult) {
        if let Some(url) = value.downcast_ref::<String>() {
            if url.is_empty() {
                result.add_error("value is empty".to_string());
            } else if !url.starts_with("http://") && !url.starts_with("https://") {
                result.add_error("value is not a valid url".to_string());
            }
        } else {
            result.add_error("value must be a string".to_string());
        }
    }

    fn validate_bytes(&self, value: &dyn Any, _tag: &Tag, result: &mut ValidationResult) {
        if let Some(bytes) = value.downcast_ref::<Vec<u8>>() {
            if bytes.is_empty() {
                result.add_error("value is empty".to_string());
            }
        } else {
            result.add_error("value must be a byte array".to_string());
        }
    }

    fn validate_uuid(&self, value: &dyn Any, _tag: &Tag, result: &mut ValidationResult) {
        if let Some(uuid) = value.downcast_ref::<String>() {
            if uuid.is_empty() {
                result.add_error("value is empty".to_string());
            } else if uuid.len() != 36 {
                result.add_error("value is not a valid uuid".to_string());
            }
        } else {
            result.add_error("value must be a string".to_string());
        }
    }

    fn validate_datetime(&self, value: &dyn Any, _tag: &Tag, result: &mut ValidationResult) {
        if let Some(datetime) = value.downcast_ref::<String>() {
            if datetime.is_empty() {
                result.add_error("value is empty".to_string());
            }
        } else {
            result.add_error("value must be a string".to_string());
        }
    }

    fn validate_enum(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(enum_value) = value.downcast_ref::<String>() {
            if enum_value.is_empty() {
                result.add_error("value is empty".to_string());
            } else if let Some(enum_values) = &tag.enums {
                if !enum_values.contains(enum_value) {
                    result.add_error("value is not in enum".to_string());
                }
            }
        } else {
            result.add_error("value must be a string".to_string());
        }
    }

    fn validate_arr(&self, value: &dyn Any, tag: &Tag, result: &mut ValidationResult) {
        if let Some(array) = value.downcast_ref::<Vec<Box<dyn Any>>>() {
            if array.is_empty() {
                result.add_error("value is empty".to_string());
            }
            for (index, item) in array.iter().enumerate() {
                let child_tag = Tag {
                    value_type: tag.child_type,
                    ..tag.clone()
                };
                let item_result = self.validate(item.as_ref(), &child_tag);
                if !item_result.is_valid {
                    for error in item_result.errors {
                        result.add_error(format!("item {}: {}", index, error));
                    }
                }
            }
        } else {
            result.add_error("value must be an array".to_string());
        }
    }

    fn validate_obj(&self, _value: &dyn Any, _tag: &Tag, _result: &mut ValidationResult) {}
}

static EMAIL_REGEX: LazyLock<Regex> =
    LazyLock::new(|| Regex::new(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").unwrap());

pub static VALIDATOR: LazyLock<MmValidator> = LazyLock::new(MmValidator::new);

pub fn validate(value: &dyn Any, tag: &Tag) -> ValidationResult {
    VALIDATOR.validate(value, tag)
}
