package com.codvision.webcore.util;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.codvision.commoncore.utils.BeanUtil;
import com.codvision.webcore.annotation.QueryCondition;
import com.codvision.webcore.bean.QueryPage;
import org.apache.commons.lang3.ObjectUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * 分页工具
 *
 * @author lingee
 * @since 2023/7/20
 */
public class PageUtil {


    /**
     * Mybatis-Plus分页封装
     *
     * @param page 分页VO
     * @param <T>  范型
     * @return 分页响应
     */
    public static <T> Page<T> initPage(QueryPage page) {

        Page<T> p;
        int pageNumber = page.getPageNumber();
        int pageSize = page.getPageSize();
        String sort = page.getSort();
        String order = page.getOrder();

        if (pageNumber < 1) {
            pageNumber = 1;
        }
        if (pageSize < 1) {
            pageSize = 10;
        }
        if (pageSize > 100000) {
            pageSize = 100000;
        }
        if (StrUtil.isNotBlank(sort)) {
            Boolean isAsc = false;
            if (StrUtil.isBlank(order)) {
                isAsc = false;
            } else {
                if ("desc".equals(order.toLowerCase())) {
                    isAsc = false;
                } else if ("asc".equals(order.toLowerCase())) {
                    isAsc = true;
                }
            }
            p = new Page<>(pageNumber, pageSize);
            if (isAsc) {
                p.addOrder(OrderItem.asc(sort));
            } else {
                p.addOrder(OrderItem.desc(sort));
            }

        } else {
            p = new Page<>(pageNumber, pageSize);
        }
        return p;
    }

    /**
     * 生成条件搜索 全对象对比
     *
     * @param object 对象
     * @return 查询wrapper
     */
    public static <T> QueryWrapper<T> initWrapper(Object object) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        if (ObjectUtils.isNotEmpty(object)) {
            Field[] fields = BeanUtil.getFields(object);
            if (ArrayUtil.isEmpty(fields)) {
                return queryWrapper;
            }
            for (int j = 0; j < fields.length; j++) {
                Field field = fields[j];
                if (ObjectUtils.isEmpty(field)) {
                    continue;
                }
                field.setAccessible(true);

                String key = field.getName();
                Object value = BeanUtil.getFieldValueByName(key, object);
                if (StrUtil.isEmptyIfStr(value)) {
                    continue;
                }
                String columnName = StringUtils.camelToUnderline(key);
                if (field.isAnnotationPresent(QueryCondition.class)) {
                    QueryCondition queryCondition = field.getAnnotation(QueryCondition.class);
                    if (StrUtil.isNotBlank(queryCondition.column())) {
                        columnName = queryCondition.column();
                    }
                    if (StrUtil.isNotBlank(queryCondition.property())) {
                        columnName = StringUtils.camelToUnderline(queryCondition.property());
                    }
                    switch (queryCondition.condition()) {
                        case LIKE:
                            queryWrapper.like(columnName, value);
                            break;
                        case IN:
                            queryWrapper.in(columnName, value);
                            break;
                        case LE:
                            queryWrapper.le(columnName, value);
                            break;
                        case GE:
                            queryWrapper.ge(columnName, value);
                            break;
                        case LT:
                            queryWrapper.lt(columnName, value);
                            break;
                        case GT:
                            queryWrapper.gt(columnName, value);
                            break;
                        case NE:
                            queryWrapper.ne(columnName, value);
                            break;
                        case IS_NULL:
                            queryWrapper.isNull(columnName);
                            break;
                        case IS_NOT_NULL:
                            queryWrapper.isNotNull(columnName);
                            break;
                        default:
                            queryWrapper.eq(columnName, value);
                    }
                    continue;
                }
                queryWrapper.eq(columnName, value);
            }
        }
        return queryWrapper;
    }

    /**
     * List 手动分页
     *
     * @param page 分页对象
     * @param list 分页集合
     * @return 范型结果
     */
    public static <T> List<T> listToPage(QueryPage page, List<T> list) {

        int pageNumber = page.getPageNumber() - 1;
        int pageSize = page.getPageSize();

        if (pageNumber < 0) {
            pageNumber = 0;
        }
        if (pageSize < 1) {
            pageSize = 10;
        }
        if (pageSize > 100) {
            pageSize = 100;
        }

        int fromIndex = pageNumber * pageSize;
        int toIndex = pageNumber * pageSize + pageSize;

        if (fromIndex > list.size()) {
            return new ArrayList<>();
        } else if (toIndex >= list.size()) {
            return list.subList(fromIndex, list.size());
        } else {
            return list.subList(fromIndex, toIndex);
        }
    }

    /**
     * 转换分页类型
     *
     * @param originPage 原分页
     * @param records    新分页数据
     * @param <T>        新类型
     * @return 新类型分页
     */
    public static <T> IPage<T> convertPage(IPage originPage, List<T> records) {
        IPage<T> resultPage = new Page<>();
        if (originPage != null) {
            resultPage.setCurrent(originPage.getCurrent());
            resultPage.setPages(originPage.getPages());
            resultPage.setTotal(originPage.getTotal());
            resultPage.setSize(originPage.getSize());
            resultPage.setRecords(records);
        }
        return resultPage;
    }

}
