package com.face.util;

import com.face.global.enums.CommonCode;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

@Slf4j
public class BatchExecuteUtils {
    public static <T, ID> void pageAllById(int pageSize, ID startMaxId,
                                           PageMaxIdFunction<T, ID> pageFunction,
                                           Consumer<List<T>> pageConsumer,
                                           Function<T, ID> idFunction, Class<T> dataCls,
                                           Class<ID> idCls) {
        List<T> datas;
        ID startId = startMaxId;
        do {
            try {
                PageMaxParam pageMaxParam = PageMaxParam.builder().maxId(startId)
                        .pageIndex(1).pageSize(pageSize).build();
                datas = pageFunction.pageByMax(pageMaxParam);
                pageConsumer.accept(datas);
                if (!CollectionUtils.isEmpty(datas)) {
                    startId = idFunction.apply(datas.get(datas.size() - 1));
                }
            } catch (Exception e) {
                log.error("pageAllByIdFail {}", startMaxId, e);
                throw SystemExceptionUtils.buildBusinessException(CommonCode.ERROR.getCode(), e);
            }
        } while (!CollectionUtils.isEmpty(datas) && datas.size() >= pageSize);
    }



    public interface PageMaxIdFunction<T, ID> {
        List<T> pageByMax(PageMaxParam<ID> pageMaxParam);
    }

    @Builder
    @Getter
    public static class PageMaxParam<ID> {
        private int pageIndex;
        private int pageSize;
        private ID maxId;
    }

    public static <T> void pageAll(int pageSize,
                                   PageFunction<T, PageParam> pageFunction,
                                   Consumer<List<T>> pageConsumer,
                                   Class<T> dataCls) {
        List<T> datas;
        int pageIndex = 1;
        do {
            try {
                PageParam pageParam = PageParam.builder()
                        .pageIndex(pageIndex).pageSize(pageSize).build();
                datas = pageFunction.page(pageParam);
                pageConsumer.accept(datas);
                if (CollectionUtils.isEmpty(datas) || datas.size() >= pageSize) {
                    break;
                }
                pageIndex ++;
            } catch (Throwable e) {
                log.error("pageAllFail", e);
                throw SystemExceptionUtils.buildBusinessException(CommonCode.ERROR.getCode(), e);
            }
        } while (!CollectionUtils.isEmpty(datas) && datas.size() >= pageSize);
    }


    public interface PageFunction<T, PageParam> {
         List<T> page(PageParam pageMaxParam) throws Throwable;
    }

    @Builder
    @Getter
    public static class PageParam {
        private int pageIndex;
        private int pageSize;
    }
}
