package org.xyzh.common.utils;

import java.lang.reflect.Array;
import java.util.*;
import java.util.function.Predicate;

/**
 * @description NonUtils.java文件描述 空值判断工具类
 * @filename NonUtils.java
 * @author yslg
 * @copyright xyzh
 * @since 2025-09-28
 */
public class NonUtils {

    private NonUtils() {
        throw new UnsupportedOperationException("工具类不能被实例化");
    }

    // ======================== 基础null判断 ========================

    /**
     * 判断对象是否为null
     *
     * @param obj 待判断的对象
     * @return true-对象为null，false-对象不为null
     */
    public static boolean isNull(Object obj) {
        return obj == null;
    }

    /**
     * 判断对象是否不为null
     *
     * @param obj 待判断的对象
     * @return true-对象不为null，false-对象为null
     */
    public static boolean isNotNull(Object obj) {
        return obj != null;
    }

    /**
     * 判断多个对象是否都为null
     *
     * @param objects 待判断的对象数组
     * @return true-所有对象都为null，false-至少有一个对象不为null
     */
    public static boolean isAllNull(Object... objects) {
        if (objects == null || objects.length == 0) {
            return true;
        }
        for (Object obj : objects) {
            if (isNotNull(obj)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断多个对象是否都不为null
     *
     * @param objects 待判断的对象数组
     * @return true-所有对象都不为null，false-至少有一个对象为null
     */
    public static boolean isAllNotNull(Object... objects) {
        if (objects == null || objects.length == 0) {
            return false;
        }
        for (Object obj : objects) {
            if (isNull(obj)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断多个对象中是否存在null
     *
     * @param objects 待判断的对象数组
     * @return true-存在null对象，false-不存在null对象
     */
    public static boolean hasNull(Object... objects) {
        if (objects == null || objects.length == 0) {
            return true;
        }
        for (Object obj : objects) {
            if (isNull(obj)) {
                return true;
            }
        }
        return false;
    }

    // ======================== 空值判断（包含null、空字符串、空集合等） ========================

    /**
     * 判断对象是否为空
     * - null -> true
     * - "" -> true
     * - "   " -> true (仅包含空白字符)
     * - 空集合 -> true
     * - 空数组 -> true
     *
     * @param obj 待判断的对象
     * @return true-对象为空，false-对象不为空
     */
    public static boolean isEmpty(Object obj) {
        if (isNull(obj)) {
            return true;
        }

        // 字符串判断
        if (obj instanceof CharSequence) {
            return ((CharSequence) obj).length() == 0 || obj.toString().trim().isEmpty();
        }

        // 集合判断
        if (obj instanceof Collection) {
            return ((Collection<?>) obj).isEmpty();
        }

        // Map判断
        if (obj instanceof Map) {
            return ((Map<?, ?>) obj).isEmpty();
        }

        // 数组判断
        if (obj.getClass().isArray()) {
            return Array.getLength(obj) == 0;
        }

        // Optional判断
        if (obj instanceof Optional) {
            return !((Optional<?>) obj).isPresent();
        }

        return false;
    }

    /**
     * 判断对象是否不为空
     *
     * @param obj 待判断的对象
     * @return true-对象不为空，false-对象为空
     */
    public static boolean isNotEmpty(Object obj) {
        return !isEmpty(obj);
    }

    /**
     * 判断多个对象是否都为空
     *
     * @param objects 待判断的对象数组
     * @return true-所有对象都为空，false-至少有一个对象不为空
     */
    public static boolean isAllEmpty(Object... objects) {
        if (objects == null || objects.length == 0) {
            return true;
        }
        for (Object obj : objects) {
            if (isNotEmpty(obj)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断多个对象是否都不为空
     *
     * @param objects 待判断的对象数组
     * @return true-所有对象都不为空，false-至少有一个对象为空
     */
    public static boolean isAllNotEmpty(Object... objects) {
        if (objects == null || objects.length == 0) {
            return false;
        }
        for (Object obj : objects) {
            if (isEmpty(obj)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断多个对象中是否存在空值
     *
     * @param objects 待判断的对象数组
     * @return true-存在空值，false-不存在空值
     */
    public static boolean hasEmpty(Object... objects) {
        if (objects == null || objects.length == 0) {
            return true;
        }
        for (Object obj : objects) {
            if (isEmpty(obj)) {
                return true;
            }
        }
        return false;
    }

    // ======================== 深度递归判断 ========================

    /**
     * 深度判断对象是否为空（递归检查）
     * 对于集合、数组等容器类型，会递归检查其内部元素
     *
     * @param obj 待判断的对象
     * @return true-对象为空（包括递归检查），false-对象不为空
     */
    public static boolean isDeepEmpty(Object obj) {
        return isDeepEmpty(obj, new HashSet<>());
    }

    /**
     * 深度判断对象是否为空（递归检查，防止循环引用）
     *
     * @param obj 待判断的对象
     * @param visited 已访问对象集合，用于防止循环引用
     * @return true-对象为空（包括递归检查），false-对象不为空
     */
    private static boolean isDeepEmpty(Object obj, Set<Object> visited) {
        if (isEmpty(obj)) {
            return true;
        }

        // 防止循环引用
        if (visited.contains(obj)) {
            return false;
        }
        visited.add(obj);

        try {
            // 集合类型递归检查
            if (obj instanceof Collection) {
                Collection<?> collection = (Collection<?>) obj;
                for (Object item : collection) {
                    if (!isDeepEmpty(item, visited)) {
                        return false;
                    }
                }
                return true;
            }

            // Map类型递归检查
            if (obj instanceof Map) {
                Map<?, ?> map = (Map<?, ?>) obj;
                for (Map.Entry<?, ?> entry : map.entrySet()) {
                    if (!isDeepEmpty(entry.getKey(), visited) || !isDeepEmpty(entry.getValue(), visited)) {
                        return false;
                    }
                }
                return true;
            }

            // 数组类型递归检查
            if (obj.getClass().isArray()) {
                int length = Array.getLength(obj);
                for (int i = 0; i < length; i++) {
                    if (!isDeepEmpty(Array.get(obj, i), visited)) {
                        return false;
                    }
                }
                return true;
            }

            // Optional类型递归检查
            if (obj instanceof Optional) {
                Optional<?> optional = (Optional<?>) obj;
                return !optional.isPresent() || isDeepEmpty(optional.get(), visited);
            }

            // 其他类型认为不为空
            return false;

        } finally {
            visited.remove(obj);
        }
    }

    /**
     * 深度判断对象是否不为空（递归检查）
     *
     * @param obj 待判断的对象
     * @return true-对象不为空（包括递归检查），false-对象为空
     */
    public static boolean isDeepNotEmpty(Object obj) {
        return !isDeepEmpty(obj);
    }

    // ======================== 集合专用方法 ========================

    /**
     * 判断集合是否为空或null
     *
     * @param collection 待判断的集合
     * @return true-集合为null或空，false-集合不为空
     */
    public static boolean isEmptyCollection(Collection<?> collection) {
        return collection == null || collection.isEmpty();
    }

    /**
     * 判断集合是否不为空且不为null
     *
     * @param collection 待判断的集合
     * @return true-集合不为null且不为空，false-集合为null或空
     */
    public static boolean isNotEmptyCollection(Collection<?> collection) {
        return collection != null && !collection.isEmpty();
    }

    /**
     * 判断集合是否包含有效元素（非null且非空的元素）
     *
     * @param collection 待判断的集合
     * @return true-集合包含有效元素，false-集合为空或只包含null/空元素
     */
    public static boolean hasValidElements(Collection<?> collection) {
        if (isEmptyCollection(collection)) {
            return false;
        }
        for (Object item : collection) {
            if (isNotEmpty(item)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断集合是否所有元素都有效（非null且非空）
     *
     * @param collection 待判断的集合
     * @return true-集合所有元素都有效，false-集合为空或包含null/空元素
     */
    public static boolean allValidElements(Collection<?> collection) {
        if (isEmptyCollection(collection)) {
            return false;
        }
        for (Object item : collection) {
            if (isEmpty(item)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 过滤集合中的空元素，返回新集合
     *
     * @param collection 原集合
     * @param <T> 集合元素类型
     * @return 过滤后的新集合
     */
    public static <T> List<T> filterEmpty(Collection<T> collection) {
        if (isEmptyCollection(collection)) {
            return new ArrayList<>();
        }
        List<T> result = new ArrayList<>();
        for (T item : collection) {
            if (isNotEmpty(item)) {
                result.add(item);
            }
        }
        return result;
    }

    // ======================== Map专用方法 ========================

    /**
     * 判断Map是否为空或null
     *
     * @param map 待判断的Map
     * @return true-Map为null或空，false-Map不为空
     */
    public static boolean isEmptyMap(Map<?, ?> map) {
        return map == null || map.isEmpty();
    }

    /**
     * 判断Map是否不为空且不为null
     *
     * @param map 待判断的Map
     * @return true-Map不为null且不为空，false-Map为null或空
     */
    public static boolean isNotEmptyMap(Map<?, ?> map) {
        return map != null && !map.isEmpty();
    }

    // ======================== 数组专用方法 ========================

    /**
     * 判断数组是否为空或null
     *
     * @param array 待判断的数组
     * @return true-数组为null或空，false-数组不为空
     */
    public static boolean isEmptyArray(Object array) {
        return array == null || !array.getClass().isArray() || Array.getLength(array) == 0;
    }

    /**
     * 判断数组是否不为空且不为null
     *
     * @param array 待判断的数组
     * @return true-数组不为null且不为空，false-数组为null或空
     */
    public static boolean isNotEmptyArray(Object array) {
        return array != null && array.getClass().isArray() && Array.getLength(array) > 0;
    }

    // ======================== 字符串专用方法 ========================

    /**
     * 判断字符串是否为空或null（包括空白字符串）
     *
     * @param str 待判断的字符串
     * @return true-字符串为null、空或只包含空白字符，false-字符串有有效内容
     */
    public static boolean isEmptyString(String str) {
        return str == null || str.trim().isEmpty();
    }

    /**
     * 判断字符串是否不为空且不为null
     *
     * @param str 待判断的字符串
     * @return true-字符串不为null且有有效内容，false-字符串为null、空或只包含空白字符
     */
    public static boolean isNotEmptyString(String str) {
        return str != null && !str.trim().isEmpty();
    }

    // ======================== 条件判断方法 ========================

    /**
     * 如果对象为空则返回默认值
     *
     * @param obj 待判断的对象
     * @param defaultValue 默认值
     * @param <T> 对象类型
     * @return 如果obj为空则返回defaultValue，否则返回obj
     */
    @SuppressWarnings("unchecked")
    public static <T> T defaultIfEmpty(T obj, T defaultValue) {
        return isEmpty(obj) ? defaultValue : obj;
    }

    /**
     * 如果对象为null则返回默认值
     *
     * @param obj 待判断的对象
     * @param defaultValue 默认值
     * @param <T> 对象类型
     * @return 如果obj为null则返回defaultValue，否则返回obj
     */
    public static <T> T defaultIfNull(T obj, T defaultValue) {
        return isNull(obj) ? defaultValue : obj;
    }

    /**
     * 获取第一个非空的对象
     *
     * @param objects 对象数组
     * @param <T> 对象类型
     * @return 第一个非空的对象，如果都为空则返回null
     */
    @SafeVarargs
    public static <T> T firstNotEmpty(T... objects) {
        if (objects == null || objects.length == 0) {
            return null;
        }
        for (T obj : objects) {
            if (isNotEmpty(obj)) {
                return obj;
            }
        }
        return null;
    }

    /**
     * 获取第一个非null的对象
     *
     * @param objects 对象数组
     * @param <T> 对象类型
     * @return 第一个非null的对象，如果都为null则返回null
     */
    @SafeVarargs
    public static <T> T firstNotNull(T... objects) {
        if (objects == null || objects.length == 0) {
            return null;
        }
        for (T obj : objects) {
            if (isNotNull(obj)) {
                return obj;
            }
        }
        return null;
    }

    // ======================== 统计方法 ========================

    /**
     * 统计数组中非空元素的个数
     *
     * @param objects 对象数组
     * @return 非空元素个数
     */
    public static int countNotEmpty(Object... objects) {
        if (objects == null || objects.length == 0) {
            return 0;
        }
        int count = 0;
        for (Object obj : objects) {
            if (isNotEmpty(obj)) {
                count++;
            }
        }
        return count;
    }

    /**
     * 统计数组中非null元素的个数
     *
     * @param objects 对象数组
     * @return 非null元素个数
     */
    public static int countNotNull(Object... objects) {
        if (objects == null || objects.length == 0) {
            return 0;
        }
        int count = 0;
        for (Object obj : objects) {
            if (isNotNull(obj)) {
                count++;
            }
        }
        return count;
    }

    // ======================== 断言方法 ========================

    /**
     * 断言对象不为null，如果为null则抛出异常
     *
     * @param obj 待断言的对象
     * @param message 异常消息
     * @throws IllegalArgumentException 如果对象为null
     */
    public static void requireNotNull(Object obj, String message) {
        if (isNull(obj)) {
            throw new IllegalArgumentException(message != null ? message : "对象不能为null");
        }
    }

    /**
     * 断言对象不为空，如果为空则抛出异常
     *
     * @param obj 待断言的对象
     * @param message 异常消息
     * @throws IllegalArgumentException 如果对象为空
     */
    public static void requireNotEmpty(Object obj, String message) {
        if (isEmpty(obj)) {
            throw new IllegalArgumentException(message != null ? message : "对象不能为空");
        }
    }

    // ======================== 类型检查方法 ========================

    /**
     * 检查对象是否为指定类型且不为null
     *
     * @param obj 待检查的对象
     * @param clazz 目标类型
     * @param <T> 目标类型
     * @return true-对象不为null且为指定类型，false-否则
     */
    public static <T> boolean isInstanceAndNotNull(Object obj, Class<T> clazz) {
        return isNotNull(obj) && clazz.isInstance(obj);
    }

    /**
     * 安全的类型转换，如果对象为null或不是目标类型则返回null
     *
     * @param obj 待转换的对象
     * @param clazz 目标类型
     * @param <T> 目标类型
     * @return 转换后的对象，如果转换失败则返回null
     */
    @SuppressWarnings("unchecked")
    public static <T> T safeCast(Object obj, Class<T> clazz) {
        if (isInstanceAndNotNull(obj, clazz)) {
            return (T) obj;
        }
        return null;
    }
}
