package com.ym.mec.common.page;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ym.mec.common.exception.BizException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author hgw
 * Created by 2021-12-20
 */
public class WrapperUtil<T> {

    public static final Predicate<? super Object> ObjPredicate = (Predicate<Object>) Objects::nonNull;

    public static final Predicate<? super String> StrPredicate = (Predicate<String>) StringUtils::isNotBlank;

    public static final Predicate<? super Collection<?>> ListPredicate = (Predicate<Collection<?>>) CollectionUtils::isNotEmpty;

    private final QueryWrapper<T> queryWrapper;

    public WrapperUtil() {
        this.queryWrapper = new QueryWrapper<>();
    }

    /**
     * 返回QueryWrapper
     *
     * @return QueryWrapper
     */
    public QueryWrapper<T> queryWrapper() {
        return queryWrapper;
    }

    /**
     * 值如果不为空则添加到查询条件中
     * 仅支持简单的类型
     *
     * @param column 列名称
     * @param val    值
     */
    public WrapperUtil<T> hasEq(String column, String val) {
        queryWrapper.eq(StrPredicate.test(val), column, val);
        return this;
    }

    public WrapperUtil<T> hasEq(String column, Object val) {
        queryWrapper.eq(ObjPredicate.test(val), column, val);
        return this;
    }

    /**
     * in 查询,值如果不为空则添加到查询条件中
     *
     * @param column 列名称
     * @param val    集合
     */
    public WrapperUtil<T> hasIn(String column, Collection<?> val) {
        queryWrapper.in(ListPredicate.test(val), column, val);
        return this;
    }

    /**
     * in 查询
     *
     * @param column 列名称
     * @param val    逗号分开的值
     */
    public WrapperUtil<T> hasSplitIn(String column, String val) {
        return this.hasIn(column, WrapperUtil.toList(val));
    }

    /**
     * 大于等于 >=
     *
     * @param column 列名称
     * @param val    条件
     */
    public WrapperUtil<T> hasGe(String column, Object val) {
        queryWrapper.ge(ObjPredicate.test(val), column, val);
        return this;
    }

    /**
     * 小于等于 <=
     *
     * @param column 列名称
     * @param val    条件
     */
    public WrapperUtil<T> hasLe(String column, Object val) {
        queryWrapper.le(ObjPredicate.test(val), column, val);
        return this;
    }

    public static <S, O> Integer toInt(Map<S, O> map, S str, String exMsg) {
        Optional<O> o = Optional.ofNullable(map)
                .map(m -> m.get(str));
        return intOptional(o)
                .orElseThrow(() -> new BizException(exMsg));
    }

    public static <S, O> Integer toInt(Map<S, O> map, S str) {
        Optional<O> o = Optional.ofNullable(map)
                .map(m -> m.get(str));
        return intOptional(o)
                .orElse(null);
    }

    public static Integer toInt(String str) {
        return Optional.ofNullable(str)
                .map(Integer::valueOf)
                .orElse(null);
    }

    public static <O> Optional<Integer> intOptional(Optional<O> optional) {
        return optional
                .map(String::valueOf)
                .map(Integer::valueOf);
    }

    public static <S, O> String toStr(Map<S, O> map, S str) {
        Optional<O> o = Optional.ofNullable(map)
                .map(m -> m.get(str));
        return strOptional(o)
                .orElse(null);
    }

    public static <S, O> String toStr(Map<S, O> map, S str, String exMsg) {
        Optional<O> o = Optional.ofNullable(map)
                .map(m -> m.get(str));
        return strOptional(o)
                .orElseThrow(() -> new BizException(exMsg));
    }

    private static <O> Optional<String> strOptional(Optional<O> optional) {
        return optional
                .filter(s -> s instanceof String)
                .map(String::valueOf)
                .filter(StrPredicate);
    }

    public static <S, O> boolean strParamIsNull(Map<S, O> map, S str) {
        return StrPredicate.test(WrapperUtil.toStr(map, str));
    }

    public static List<String> toList(String key) {
        return toList(key, ",");
    }

    public static List<String> toList(String key, String symbol) {
        return toListOptional(key, symbol)
                .orElse(null);
    }

    /**
     * 将用逗号分割的字符串转换为List
     *
     * @param key 用逗号分割的字符
     * @return Optional
     */
    public static Optional<List<String>> toListOptional(String key) {
        return toListOptional(key, ",");
    }

    public static Optional<List<String>> toListOptional(String key, String symbol) {
        return Optional.ofNullable(key)
                .filter(StrPredicate)
                .map(b -> b.split(symbol))
                .map(WrapperUtil::collectToList)
                .filter(ListPredicate);
    }

    public static List<String> collectToList(String[] b) {
        return Arrays.stream(b)
                .filter(StrPredicate)
                .distinct()
                .collect(Collectors.toList());
    }

    public static List<Integer> splitToIntList(String str) {
        List<String> strList = WrapperUtil.toList(str);
        if (CollectionUtils.isEmpty(strList)) {
            return null;
        }
        return strToIntList(strList);
    }

    public static List<Integer> strToIntList(List<String> strList) {
        if (CollectionUtils.isEmpty(strList)) {
            return null;
        }
        return strList.stream()
                .distinct()
                .map(WrapperUtil::toInt)
                .collect(Collectors.toList());
    }

    /**
     * 全部有值则为true
     *
     * @param obj 多个对象
     */
    public static boolean checkObj(Object... obj) {
        return Arrays.stream(obj).noneMatch(Objects::isNull);
    }

    /**
     * 检查str中是否包含 o
     * 包含返回true
     */
    public static boolean checkStr(String o, String... str) {
        if (StrPredicate.test(o) && ObjPredicate.test(str)) {
            return Arrays.asList(str).contains(o);
        } else {
            return false;
        }
    }

    public static boolean checkInObj(Object o, Object... str) {
        if (ObjPredicate.test(str)) {
            return Arrays.asList(str).contains(o);
        } else {
            return false;
        }
    }

    /**
     * 根据分组groupVal进行聚合分组
     *
     * @param list     待聚合的集合
     * @param groupVal 分组value
     */
    public static <S, L> Map<S, List<L>> groupList(List<L> list, Function<? super L, ? extends S> groupVal) {
        return list.stream()
                .filter(ObjPredicate)
                .collect(Collectors.groupingBy(groupVal));
    }

    /**
     * 根据groupVal进行聚合累加
     *
     * @param list   待聚合的集合
     * @param sumVal 需要聚合操作的字段
     */
    public static <L> BigDecimal sumList(List<L> list, Function<? super L, BigDecimal> sumVal) {
        return list.stream()
                .map(sumVal)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 对比a,b集和
     * <p> 示例
     * <p>  传入a -> [1,3,4,6]
     * <p>  传入b -> [1,2,4]
     * <p> 执行该方法后a,b会被修改为
     * <p> a -> [3,6]
     * <p> b -> [2]
     */
    @SuppressWarnings("unchecked")
    public static <O> void listDifference(List<O> a, List<O> b) {
        //将ab并集
        Collection<O> abUn = CollectionUtils.retainAll(a, b);
        //删除a中abUn的值
        a.removeAll(abUn);
        //删除b中abUn的值
        b.removeAll(abUn);
    }

    @SuppressWarnings("unchecked")
    public static Map<String, Object> toMap(Object obj) {
        if (obj instanceof Map) {
            return (Map<String, Object>) obj;
        }
        return Optional.ofNullable(obj)
                .map(JSONObject::toJSON)
                .map(o -> JSONObject.toJavaObject((JSONObject) o, Map.class))
                .orElse(new HashMap<String, Object>());
    }

}
