package com.jeequan.jeepay.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateRange;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.db.entity.StatsTaskRecord;
import com.jeequan.jeepay.service.mapper.StatsTaskRecordMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 数据统计任务记录表 服务实现类
 * </p>
 *
 * @author [mybatis plus generator]
 * @since 2023-02-07
 */
@Slf4j
@Service
public class StatsTaskRecordService extends ServiceImpl<StatsTaskRecordMapper, StatsTaskRecord> {

    @Autowired private StatsTradeService statsTradeService;
    @Autowired private StatsChannelService statsChannelService;
    @Autowired private StatsPayWayService statsPayWayService;
    @Autowired private StatsDeviceService statsDeviceService;

    /**
     * 统计任务记录 初始化
     * */
    public Long initTask(Byte taskType, Date beginRepairDate, Date endRepairDate) {
        StatsTaskRecord record = new StatsTaskRecord();
        record.setTaskType(taskType);
        record.setBeginTime(DateTime.now());
        record.setStatsBeginDate(DateUtil.formatDate(beginRepairDate));
        record.setStatsEndDate(DateUtil.formatDate(endRepairDate));
        record.setState(StatsTaskRecord.TASK_STATE_ING);
        boolean result = save(record);
        if (!result) {
            throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE);
        }
        return record.getId();
    }

    /**
     * 统计任务记录 任务成功
     * */
    public void updateSuccess(Long taskId, String errMsg) {
        this.update(new LambdaUpdateWrapper<StatsTaskRecord>()
                .set(StatsTaskRecord::getState, StatsTaskRecord.TASK_STATE_SUCCESS)
                .set(StringUtils.isNotBlank(errMsg), StatsTaskRecord::getErrMsg, errMsg)
                .set(StatsTaskRecord::getEndTime, DateTime.now())
                .eq(StatsTaskRecord::getId, taskId)
                .eq(StatsTaskRecord::getState, StatsTaskRecord.TASK_STATE_ING)
        );
    }

    /**
     * 统计任务记录 任务失败
     * */
    public void updateFail(Long taskId, String errMsg) {
        this.update(new LambdaUpdateWrapper<StatsTaskRecord>()
                .set(StatsTaskRecord::getState, StatsTaskRecord.TASK_STATE_FAIL)
                .set(StatsTaskRecord::getErrMsg, errMsg)
                .set(StatsTaskRecord::getEndTime, DateTime.now())
                .eq(StatsTaskRecord::getId, taskId)
        );
    }

    /**
     * 数据修复任务
     * */
    @Async
    public void repairStats(Long taskId, Date beginRepairDate, Date endRepairDate, String mchNo) {
        try {
            log.info("开始修复数据，开始日期：{}，结束日期：{}", DateUtil.formatDate(beginRepairDate), DateUtil.formatDate(endRepairDate));

            DateRange range = DateUtil.range(beginRepairDate, endRepairDate, DateField.DAY_OF_YEAR);
            List<DateTime> dateRangeList = new ArrayList<>();
            while (range.hasNext()) {
                dateRangeList.add(range.next());
            }

            for (DateTime dateTime : dateRangeList) {
                Date beginDate = DateUtil.beginOfDay(dateTime);
                Date endDate = DateUtil.endOfDay(dateTime);

                statsTradeService.handleStats(beginDate, endDate, mchNo);
                statsChannelService.handleStats(beginDate, endDate, mchNo);
                statsPayWayService.handleStats(beginDate, endDate, mchNo);
                statsDeviceService.handleStats(beginDate, endDate, mchNo);
            }

            updateSuccess(taskId, null);
        }catch (Exception e) {
            updateFail(taskId, e.getMessage());
            log.error("数据修复失败：", e);
        }
    }

}
