package com.xxfc.platform.vehicle.biz;

import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.google.common.collect.Maps;
import com.xxfc.platform.vehicle.constant.RedisKey;
import com.xxfc.platform.vehicle.entity.VehicleBookInfo;
import com.xxfc.platform.vehicle.mapper.VehicleBookInfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VehicleBookInfoBiz extends BaseBiz<VehicleBookInfoMapper, VehicleBookInfo> {

    public static final String TB_NAME_PREFIX = "vehicle_book_info_his_";
    public static final DateTimeFormatter YEAR_DATE_TIME_FORMATTER = DateTimeFormat.forPattern("yyyy");
    public static final DateTimeFormatter YEARMONTH_DATE_TIME_FORMATTER = DateTimeFormat.forPattern("yyyy-MM");
    public static final Integer DEL_BATCH_SIZE = 1000;
    public static final Integer COPY_BATCH_SIZE = 100;
    public static final int MONTH_INTERVAL = 2;

    @Autowired
    private RedisTemplate customRedisTemplate;

    /**
     * 迁移数据到历史表
     * 每年一张表
     */
    @Scheduled(cron = "0 0 0 1 * ?")//每月1号0点触发
    @Transactional
    public void transfer2HistoryTb() {
        //获取表格名称
        String tbName = getTbNameNow();
        DateTime now = DateTime.now();//当前获取的时间为标准
        log.info("开始预定信息迁移至历史表的定时任务。");
        //每月初将上月数据复制到历史表
        Boolean needRun = copyDataLastMoth(now, tbName);
        if (needRun) {
            //每月初将上上月数据从当前信息表中删除
            delDataTheMonthBeforeLast(now, tbName);
        }
    }

    /**
     * 获取上月数据，并复制到历史表
     */
    @Transactional
    public Boolean copyDataLastMoth(DateTime now, String tbName) {
        String lastMonthStr = now.plusMonths(-1).toString(YEARMONTH_DATE_TIME_FORMATTER);
        String redisKey = RedisKey.DEL_BOOK_INFO_LOCK_PREFIX + lastMonthStr;

        Boolean hasSuc = customRedisTemplate.opsForValue().setIfAbsent(redisKey, String.valueOf(DateTime.now().getMillis()));
        if (hasSuc) {//设置1天后过期
            customRedisTemplate.expire(redisKey, 1, TimeUnit.DAYS);
        } else {
            log.info("[预定信息迁移]乐观锁获取失败，该线程不执行任务。");
            return Boolean.FALSE;
        }
        createTbIfNotExists(tbName);
        //逐页查出数据
        Integer curPageNo = 1;
        List<VehicleBookInfo> vehicleBookInfoList = null;
        do {
            Map<String, Object> params = Maps.newHashMap();
            params.put("yearMonth", lastMonthStr);
            params.put("pageStart", (curPageNo - 1) * COPY_BATCH_SIZE);
            params.put("pageSize", COPY_BATCH_SIZE);
            vehicleBookInfoList = mapper.getByPage4YearMonth(params);
            if (CollectionUtils.isNotEmpty(vehicleBookInfoList)) {
                //插入数据到历史表
                for (VehicleBookInfo vehicleBookInfo : vehicleBookInfoList) {
                    Map<String, Object> insertHisParams = Maps.newHashMap();
                    insertHisParams.put("tbName", tbName);
                    insertHisParams.put("id", vehicleBookInfo.getId());
                    insertHisParams.put("vehicle", vehicleBookInfo.getVehicle());
                    insertHisParams.put("yearMonth", vehicleBookInfo.getYearMonth());
                    insertHisParams.put("bookedDate", vehicleBookInfo.getBookedDate());
                    mapper.insertHis(insertHisParams);
                }
            }
            curPageNo++;
            log.info("【复制上月预定信息至历史表中】，当前复制页【" + curPageNo + "】，页大小【" + COPY_BATCH_SIZE + "】");
        } while (CollectionUtils.isNotEmpty(vehicleBookInfoList));
        log.info("复制上月预定信息至历史表中完成，总页数【" + (curPageNo - 1) + "】");
        ;
        return Boolean.TRUE;
    }

    /**
     * 删除上上月数据
     */
    @Transactional
    public void delDataTheMonthBeforeLast(DateTime now, String tbName) {
        String theMonthBeforeLastStr = now.plusMonths(-2).toString(YEARMONTH_DATE_TIME_FORMATTER);
        Integer effected = 0;
        Integer total = 0;
        Map<String, Object> params = Maps.newHashMap();
        params.put("yearMonth", theMonthBeforeLastStr);
        params.put("batchSize", DEL_BATCH_SIZE);
        do {
            effected = mapper.del4YearMoth(params);
            total += effected;
            log.info("开始删除预定信息数据，删除总数【" + total + "】");
        } while (effected != 0);
        log.info("删除预定信息数据完成");
    }


    private String getTbNameNow() {
        return TB_NAME_PREFIX + DateTime.now().toString(YEAR_DATE_TIME_FORMATTER);
    }

    /**
     * 创建当年相关表格
     */
    private void createTbIfNotExists(String tbName) {
        mapper.createTbIfNotExists(tbName);
    }

    public void InsertBatch(List<VehicleBookInfo> bookInfos) {
        mapper.insertBatch(bookInfos);
    }

    public int update(VehicleBookInfo vehicleBookInfo) {
        return mapper.updateById(vehicleBookInfo);
    }
}
