package org.springblade.modules.nh.factory.common;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Slf4j
public abstract class PageAction<T, R> {

    public abstract PageInfo<T, R> pageData(int page, int pageSize, Map<String, Object> ctx) throws IOException;

    public abstract void handlePageInfo(PageInfo<T, R> pageInfo, Map<String, Object> ctx);

    protected boolean isOk(Boolean success) {
        return Objects.equals(success, true);
    }

    // for goodwe
    protected boolean isOk(Integer code) {
        return Objects.equals(code, 0);
    }

    protected boolean isAisOk(Integer code) {
        return Objects.equals(code, 200);
    }

    public int calcPage(long total, int pageSize) {
        return (int) (total / pageSize + (total % pageSize == 0 ? 0 : 1));
    }

    /**
     * @param label 任务名称
     * @param delay 单位秒
     */
    public void start(String label, int pageSize, Map<String, Object> ctx, Integer delay) {
        log.info("start fetch task ----- {} -----", label);
        long t = System.currentTimeMillis();
        long lastTime = t;
        log.info("start {}, page: {}", label, 1);
        PageInfo<T, R> pageInfo = pageDataWithRetry(label, 1, pageSize, ctx);

        if (pageInfo != null) {
            if (pageInfo.getPages() == null) {
                throw new RuntimeException("pages not set, label: " + label);
            }
            handlePageInfo(pageInfo, ctx);
            for (int i = 2; i <= pageInfo.getPages(); i++) {
                log.info("start {}, page: {}", label, i);
                if (delay != null && delay > 0) {
                    long sleep = System.currentTimeMillis() - lastTime - delay * 1000L;
                    if (sleep < 0) {
                        sleepSilently(Math.abs(sleep));
                    }
                }
                lastTime = System.currentTimeMillis();
                PageInfo<T, R> pageInfo1 = pageDataWithRetry(label, i, pageSize, ctx);
                if (pageInfo1 == null) {
                    break;
                }
                handlePageInfo(pageInfo1, ctx);
            }
        }
        log.info("end fetch task ----- {} -----, consumed: {}", label, System.currentTimeMillis() - t);
    }

    public void start(String label, int pageSize, int delay) {
        start(label, pageSize, new HashMap<>(), delay);
    }

    private void sleepSilently(long t) {
        try {
            Thread.sleep(t);
        } catch (InterruptedException e) {
            // ignore
        }
    }

    protected PageInfo<T, R> pageDataWithRetry(String label, int page, int pageSize, Map<String, Object> ctx) {
        PageInfo<T, R> pageInfo = null;
        try {
            pageInfo = pageData(page, pageSize, ctx);
        } catch (IOException ex) {
            try {
                pageInfo = pageData(page, pageSize, ctx);
            } catch (IOException e) {
                log.error("{}, page with retry error, page: {}", label, page, e);
            }
        }
        return pageInfo;
    }

}
