package com.docus.server.collect.web.job;

import com.docus.core.util.ExceptionUtils;
import com.docus.core.util.Func;
import com.docus.infrastructure.redis.service.IdService;
import com.docus.server.archivefile.service.ITaskConfigService;
import com.docus.server.collect.IJob;
import com.docus.server.collect.web.service.CollectService;
import com.docus.server.common.config.UserProperties;
import com.docus.server.entity.TaskConfig;
import com.docus.server.enums.StateEnum;
import com.docus.server.record.service.ITBasicService;
import com.docus.server.sys.service.IPowerDeptService;
import com.docus.server.sys.service.IPowerThirdLoginService;
import com.docus.server.sys.service.IPowerUserService;
import com.docus.server.util.PeriodTime;
import com.xxl.job.core.context.XxlJobHelper;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;
import java.util.List;

@Slf4j
public abstract class AbstractCollectJob<T> implements IJob<T> {
    @Resource
    protected IPowerThirdLoginService thirdLoginService;
    @Resource
    protected ITaskConfigService taskConfigService;
    @Resource
    protected IPowerUserService userService;
    @Resource
    protected IPowerDeptService deptService;
    @Resource
    protected ITBasicService basicService;
    @Resource
    protected CollectService collectService;
    @Resource
    protected UserProperties userProperties;
    @Resource
    protected IdService idService;

    @Override
    public void startCollectAll(String taskConfigId) {
        TaskConfig taskConfig = getTaskConfig(taskConfigId);
        try {
            List<PeriodTime> periodTimes = taskConfig.getAllPeriodTimes();

            for (PeriodTime periodTime : periodTimes) {

                page(periodTime, taskConfig);

                taskConfigService.updateAllPointerDate(taskConfigId, periodTime.getPeriodEndDate());
            }
            refreshTaskState(taskConfig);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            updateTaskState(ExceptionUtils.getExceptionMessage(ex), taskConfig);
            refreshTaskState(taskConfig);
            throw new RuntimeException(ex);
        }
    }

    @Override
    public void startCollectIncrement(String taskConfigId) {
        TaskConfig taskConfig = getTaskConfig(taskConfigId);

        try {
            List<PeriodTime> periodTimes = taskConfig.getIncPeriodTimes();

            for (PeriodTime periodTime : periodTimes) {

                page(periodTime, taskConfig);

                taskConfigService.updateIncPointerDate(taskConfigId, periodTime.getPeriodEndDate());
            }
            refreshTaskState(taskConfig);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            updateTaskState(ExceptionUtils.getExceptionMessage(ex), taskConfig);
            refreshTaskState(taskConfig);
            throw new RuntimeException(ex);
        }
    }


    @Override
    public void page(PeriodTime periodTime, TaskConfig taskConfig) {
        //考虑到性能，应该把起始时间和结束时间进行切割拆分到每天。按段查询。
        List<T> results;

        int pageNum = 1;

        for (; true; pageNum++) {
            taskConfig.setPageNum(pageNum);

            taskConfig.setOffset((pageNum - 1) * taskConfig.getPageSize());

            results = execute(periodTime, taskConfig);

            if (Func.isEmpty(results)) {
                log.info("本次采集：0笔" + taskConfig.getType());
                break;
            }

            log.info("本次采集：" + results.size() + "笔" + taskConfig.getType());

            doHandle(results, taskConfig.getParam());
        }
    }

    public abstract void doHandle(List<T> results, String param);

    public abstract List<T> execute(PeriodTime periodTime, TaskConfig taskConfig);


    private void refreshTaskState(TaskConfig taskConfig) {
        if (StateEnum.FAIL.equals(taskConfig.getState())) {
            updateTaskState(taskConfig);
        }
    }

    public void updateTaskState(TaskConfig taskConfig) {
        taskConfig.setState(StateEnum.OK);
        taskConfigService.updateTaskConfig(taskConfig);
    }

    public void updateTaskState(String message, TaskConfig taskConfig) {
        taskConfig.setState(StateEnum.FAIL);
        taskConfig.setLastErrorMsg(message);
        taskConfigService.updateTaskConfig(taskConfig);
    }

    private TaskConfig getTaskConfig(String taskConfigId) {
        return taskConfigService.getTaskConfigById(taskConfigId);
    }

    protected String getJobParam(String param) {
        return Func.isNotBlank(param) ? param : XxlJobHelper.getJobParam();
    }
}
