package com.github.wxiaoqi.security.common.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.github.wxiaoqi.security.common.exception.BaseException;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.util.process.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.mockito.internal.util.collections.Sets;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.github.wxiaoqi.security.common.constant.CommonConstants.SYS_FALSE;
import static com.github.wxiaoqi.security.common.constant.CommonConstants.SYS_JSON_TRUE;

@Slf4j
public class AssertUtils {
    public static<T> T isBlank(T object, BaseException baseException, String name) throws BaseException {
        log.info(" AssertUtils.isBlank : {}", object);
        if(object instanceof Collection) {
            if (CollUtil.isEmpty((List)object)) {
                throwException(baseException, name);
            }
        }else if (object == null) {
            throwException(baseException, name);
        }
        return object;
    }

    public static<T> T isNotBlank(T object, BaseException baseException, String name) throws BaseException {
        log.info(" AssertUtils.isNotBlank : {}", object);
        if (object != null ) {
            //如果是集合 并且 为空 着不抛异常
            if (object instanceof Collection && CollUtil.isEmpty((List)object)) {
                return object;
            }else {
                throwException(baseException, name);
            }
        }
        return object;
    }

    public static<T> T isBlank(T object, BaseException baseException) throws BaseException {
        return isBlank(object, baseException, null);
    }

    public static<T> T isNotBlank(T object, BaseException baseException) throws BaseException {
        return isNotBlank(object, baseException, null);
    }

    public static void isBlankMulti(Object... objects) throws BaseException {
        log.info(" AssertUtils.isBlank : {}", objects);
        isBlank(objects);
        for (Object object : objects) {
            isBlank(object);
        }
    }

//    public static void isEqual(Object a, Object b, BaseException bex) throws BaseException {
//        log.info(" AssertUtils.isEqual : {} {}", a, b);
//        if(a.equals(b)) {
//            if(null != bex) {
//                throw new BaseException(ResultCode.DB_OPERATION_FAIL_CODE);
//            }else {
//                throw bex;
//            }
//        }
//    }

    public static<T> T isBlank(T object) throws BaseException {
        return isBlank(object, null, null);
    }

    public static<T> T isBlankBean(T object) throws BaseException {
        Map<String, Object> beanMap = BeanUtil.beanToMap(object);
        isBlank(object);
        for(String key : beanMap.keySet()) {
            isBlank(beanMap.get(key), null, null);
        }
        return object;
    }

    public static<T> T isBlank(T object, String attrName) throws BaseException {
        return isBlank(object, null, attrName);
    }

    public static Integer isDBSucc(Integer flag, BaseException baseException) throws BaseException {
        log.info(" AssertUtils.isDBSucc : {}", flag);
        if(SYS_FALSE.equals(flag)) {
            throwDBException(baseException);
        }
        return flag;
    }

    public static Integer isDBSucc(Integer flag) throws BaseException {
        return isDBSucc(flag, null);
    }

    public static<T> ObjectRestResponse<T> isFeignSucc(ObjectRestResponse<T> orr) throws BaseException {
        log.info(" AssertUtils.isFeignSucc : {}", orr);
        if(!SYS_JSON_TRUE.equals(orr.getStatus())) {
            throw new BaseException(orr.getMessage(), orr.getStatus());
        }
        return orr;
    }

    public static<T,E> ObjectRestResponse<T> isFeignSuccGetObj(E dto, Function<Map, ObjectRestResponse<T>> function) throws BaseException {
        log.info(" AssertUtils.isFeignSucc : {}", dto);
        ObjectRestResponse<T> orr = function.apply(DepthBeanToMap.objectToMap(dto));
        //ObjectRestResponse<T> orr = function.apply( BeanUtil.beanToMap(dto, false, false));
        if(!SYS_JSON_TRUE.equals(orr.getStatus())) {
            throw new BaseException(orr.getMessage(), orr.getStatus());
        }
        return orr;
    }

    public static<T,E> List<T> isFeignSuccGetDataList(E dto, Function<Map, ObjectRestResponse<List<T>>> function, Class<T> tClass) throws BaseException {
        log.info(" AssertUtils.isFeignSucc : {}", dto);
        ObjectRestResponse<List<T>> orr = function.apply(DepthBeanToMap.objectToMap(dto));
        //ObjectRestResponse<List<T>> orr = function.apply(BeanUtil.beanToMap(dto, false, false));
        if(!SYS_JSON_TRUE.equals(orr.getStatus())) {
            throw new BaseException(orr.getMessage(), orr.getStatus());
        }

        orr.setData(orr.getData().parallelStream().map(t -> BeanUtil.toBean(t, tClass)).collect(Collectors.toList()));
        return orr.getData();
    }

    public static<T,E> T isFeignSuccGetData(E dto, Function<Map, ObjectRestResponse<T>> function) throws BaseException {

        return isFeignSuccGetObj(dto, function).getData();
    }

    private static void throwException(BaseException baseException, String name) {
        if(null != baseException) {
            throw  baseException;
        }else {
            throw new BaseException(ResultCode.NOTEXIST_CODE, Sets.newSet(name));
        }
    }
    private static void throwDBException(BaseException baseException) {
        if(null != baseException) {
            throw  baseException;
        }else {
            throw new BaseException(ResultCode.DB_OPERATION_FAIL_CODE);
        }
    }

}
