package com.ai.da.common.config.mybatis.plus;

import cn.hutool.core.util.StrUtil;
import com.ai.da.common.annotation.Condition;
import com.ai.da.common.annotation.Order;
import com.ai.da.common.enums.ConditionType;
import com.ai.da.common.utils.ConvertUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * @author: dangweijian
 * @description:
 * @create: 2020-09-14 15:47
 **/
@Data
@Slf4j
public abstract class QueryCriteria<T, E> {

    private long page = 1;
    private long limit = 10;
    private Function<T, E> mapper;
    private Consumer<QueryWrapper<T>> appendWrapper;
    private Consumer<T> peekBefore;
    private Consumer<E> peekAfter;
    private Consumer<List<E>> peekAllAfter;

    public QueryCriteria(Function<T, E> mapper) {
        this.mapper = mapper;
    }

    public QueryWrapper<T> buildWrapper() {
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        Field[] fields = this.getClass().getDeclaredFields();
        for (Field field : fields) {
            Condition condition = field.getAnnotation(Condition.class);
            if (condition != null) {
                field.setAccessible(true);
                Object value = null;
                try {
                    value = field.get(this);
                } catch (IllegalAccessException e) {
                    log.warn("reflection anomaly!");
                }
                if (!StrUtil.isEmptyIfStr(value)) {
                    switch (condition.type()) {
                        case EQ:
                            wrapper.eq(ConvertUtil.humpToLine2(field.getName()), value);
                            break;
                        case LIKE:
                            wrapper.like(ConvertUtil.humpToLine2(field.getName()), value);
                        case BETWEEN:
                            if (value instanceof Collection && ((List) value).size() >= 2) {
                                wrapper.between(ConvertUtil.humpToLine2(field.getName()), ((List) value).get(0), ((List) value).get(1));
                            }
                        default:
                    }
                } else if (condition.isNull()) {
                    wrapper.isNull(ConvertUtil.humpToLine2(field.getName()));
                }
            }
            Order order = field.getAnnotation(Order.class);
            if (order != null) {
                if (!StrUtil.isEmptyIfStr(order.order())) {
                    switch (order.order()) {
                        case DESC:
                            wrapper.orderByDesc(ConvertUtil.humpToLine2(field.getName()));
                            break;
                        case ASC:
                            wrapper.orderByAsc(ConvertUtil.humpToLine2(field.getName()));
                    }
                }
            }
        }
        wrapper.func(this.getAppendWrapper() != null, this.getAppendWrapper());
        return wrapper;
    }
}
