package com.slodon.b2b2c.job;

import cn.hutool.core.date.DateUtil;
import com.slodon.b2b2c.bo.*;
import com.slodon.b2b2c.enums.StatsConstant;
import com.slodon.b2b2c.enums.StatsTimeType;
import com.slodon.b2b2c.model.statistics.*;
import com.slodon.b2b2c.model.system.SettingModel;
import com.slodon.b2b2c.statistics.pojo.*;
import com.slodon.b2b2c.statistics.pojo.base.*;
import com.slodon.b2b2c.system.pojo.Setting;
import com.slodon.b2b2c.util.PlatformPresentDataUtil;
import com.slodon.b2b2c.util.SellerPresentDataUtil;
import com.slodon.b2b2c.util.StatsDataUtil;
import com.slodon.b2b2c.vo.statistics.AdminPresentDataVO;
import com.slodon.b2b2c.vo.statistics.SellerPresentDataVO;
import lombok.extern.slf4j.Slf4j;
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.CollectionUtils;

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

/**
 * 统计定时任务
 * 统计一段时间内的数据
 * 时间段的取值为[startTime,endTime],比如某小时内的数据，统计时间段为[14:00:00,14:59:59]
 */
@Slf4j
@Configuration      //1.主要用于标记配置类，兼备Component的效果。
@EnableScheduling   //2.开启定时任务
public class StatsJob {

    @Resource
    private StatsDataUtil statsDataUtil;
    @Resource
    private PlatformPresentDataUtil platformPresentDataUtil;
    @Resource
    private SellerPresentDataUtil sellerPresentDataUtil;
    @Resource
    private RedisTemplate<String, Object> objectRedisTemplate;

    //region model
    //小时model
    @Resource
    private BrandHourModel brandHourModel;
    @Resource
    private CategoryHourModel categoryHourModel;
    @Resource
    private GoodsHourModel goodsHourModel;
    @Resource
    private MemberHourModel memberHourModel;
    @Resource
    private MemberStoreHourModel memberStoreHourModel;
    @Resource
    private PlatformHourModel platformHourModel;
    @Resource
    private ProvinceHourModel provinceHourModel;
    @Resource
    private StoreHourModel storeHourModel;
    @Resource
    private TerminalHourModel terminalHourModel;

    //日model
    @Resource
    private BrandDayModel brandDayModel;
    @Resource
    private CategoryDayModel categoryDayModel;
    @Resource
    private GoodsDayModel goodsDayModel;
    @Resource
    private MemberDayModel memberDayModel;
    @Resource
    private MemberStoreDayModel memberStoreDayModel;
    @Resource
    private PlatformDayModel platformDayModel;
    @Resource
    private ProvinceDayModel provinceDayModel;
    @Resource
    private StoreDayModel storeDayModel;
    @Resource
    private TerminalDayModel terminalDayModel;

    //周model
    @Resource
    private BrandWeekModel brandWeekModel;
    @Resource
    private CategoryWeekModel categoryWeekModel;
    @Resource
    private GoodsWeekModel goodsWeekModel;
    @Resource
    private MemberWeekModel memberWeekModel;
    @Resource
    private MemberStoreWeekModel memberStoreWeekModel;
    @Resource
    private PlatformWeekModel platformWeekModel;
    @Resource
    private ProvinceWeekModel provinceWeekModel;
    @Resource
    private StoreWeekModel storeWeekModel;
    @Resource
    private TerminalWeekModel terminalWeekModel;

    //月model
    @Resource
    private BrandMonthModel brandMonthModel;
    @Resource
    private CategoryMonthModel categoryMonthModel;
    @Resource
    private GoodsMonthModel goodsMonthModel;
    @Resource
    private MemberMonthModel memberMonthModel;
    @Resource
    private MemberStoreMonthModel memberStoreMonthModel;
    @Resource
    private PlatformMonthModel platformMonthModel;
    @Resource
    private ProvinceMonthModel provinceMonthModel;
    @Resource
    private StoreMonthModel storeMonthModel;
    @Resource
    private TerminalMonthModel terminalMonthModel;

    //年model
    @Resource
    private BrandYearModel brandYearModel;
    @Resource
    private CategoryYearModel categoryYearModel;
    @Resource
    private GoodsYearModel goodsYearModel;
    @Resource
    private MemberYearModel memberYearModel;
    @Resource
    private MemberStoreYearModel memberStoreYearModel;
    @Resource
    private PlatformYearModel platformYearModel;
    @Resource
    private ProvinceYearModel provinceYearModel;
    @Resource
    private StoreYearModel storeYearModel;
    @Resource
    private TerminalYearModel terminalYearModel;
    @Resource
    private SettingModel settingModel;
    //endregion

    /**
     * 小时统计任务
     * 每小时执行一次，统计上一个小时内的数据，执行时间eg. 2020-12-12 15:00:30
     */
    @Scheduled(cron = "30 0 0/1 * * ? ")
    @SchedulerLock(name = "hourStats", lockAtMostFor = "3600000", lockAtLeastFor = "3000000")
    public void hourStats() {
        Date now = new Date();
        Date startTime = StatsTimeType.getStartTime(now, StatsTimeType.HOUR);
        Date endTime = StatsTimeType.getEndTime(now, StatsTimeType.HOUR);

        List<Setting> siteSetting = settingModel.getSiteSetting();
        if (!CollectionUtils.isEmpty(siteSetting)) {
            siteSetting.forEach(setting -> {
                StatsBasicDataBO basicDataBO;
                try {
                    //1.查询阶段内的统计基础数据
                    basicDataBO = statsDataUtil.searchStatsBasicData(startTime, endTime, setting.getValue());
                } catch (Exception e) {
                    log.error("查询阶段内的小时统计基础数据出错", e);
                    return;
                }

                try {
                    //2.保存品牌统计表
                    Collection<BrandOrderBO> brandOrderBos = statsDataUtil.buildBrandStatsInfo(basicDataBO);
                    brandOrderBos.forEach(brandOrderBO -> {
                        BrandBase brandBase = brandOrderBO.initStats(startTime, basicDataBO.getOrderMap());
                        BrandHour brandHour = new BrandHour();
                        brandHour.copy(brandBase);
                        brandHour.setWebSite(setting.getValue());
                        brandHourModel.saveBrandHour(brandHour);
                    });
                } catch (Exception e) {
                    log.error("保存品牌小时统计出错", e);
                }

                try {
                    //3.保存商品分类统计表
                    Collection<CategoryOrderBO> categoryOrderBos = statsDataUtil.buildCategoryStatsInfo(basicDataBO);
                    categoryOrderBos.forEach(categoryOrderBO -> {
                        CategoryBase categoryBase = categoryOrderBO.initStats(startTime, basicDataBO.getOrderMap());
                        CategoryHour categoryHour = new CategoryHour();
                        categoryHour.copy(categoryBase);
                        categoryHour.setWebSite(setting.getValue());
                        categoryHourModel.saveCategoryHour(categoryHour);
                    });
                } catch (Exception e) {
                    log.error("保存商品分类小时统计出错", e);
                }

                try {
                    //4.保存商品统计
                    Collection<GoodsStatsBO> goodsStatsBos = statsDataUtil.buildGoodsStatsInfo(basicDataBO);
                    goodsStatsBos.forEach(goodsStatsBO -> {
                        GoodsBase goodsBase = goodsStatsBO.initStats(startTime, basicDataBO.getOrderMap());
                        GoodsHour goodsHour = new GoodsHour();
                        goodsHour.copy(goodsBase);
                        goodsHour.setWebSite(setting.getValue());
                        goodsHourModel.saveGoodsHour(goodsHour);
                    });
                } catch (Exception e) {
                    log.error("保存商品小时统计出错", e);
                }

                try {
                    //5.保存会员统计
                    Collection<MemberStatsBO> memberStatsBos = statsDataUtil.buildMemberStatsInfo(basicDataBO);
                    memberStatsBos.forEach(memberStatsBO -> {
                        MemberBase memberBase = memberStatsBO.initStats(startTime);
                        MemberHour memberHour = new MemberHour();
                        memberHour.copy(memberBase);
                        memberHour.setWebSite(setting.getValue());
                        memberHourModel.saveMemberHour(memberHour);
                    });
                } catch (Exception e) {
                    log.error("保存会员小时统计出错", e);
                }

                try {
                    //6.保存店铺会员统计
                    Collection<MemberStoreStatsBO> memberStoreStatsBos = statsDataUtil.buildMemberStoreStatsInfo(basicDataBO);
                    memberStoreStatsBos.forEach(memberStoreStatsBO -> {
                        MemberStoreBase memberStoreBase = memberStoreStatsBO.initStats(startTime);
                        MemberStoreHour memberStoreHour = new MemberStoreHour();
                        memberStoreHour.copy(memberStoreBase);
                        memberStoreHour.setWebSite(setting.getValue());
                        memberStoreHourModel.saveMemberStoreHour(memberStoreHour);
                    });
                } catch (Exception e) {
                    log.error("保存店铺会员小时统计出错", e);
                }

                try {
                    //7.保存平台统计
                    PlatformStatsBO platformStatsBO = new PlatformStatsBO();
                    PlatformBase platformBase = platformStatsBO.initStats(startTime, basicDataBO);
                    PlatformHour platformHour = new PlatformHour();
                    platformHour.copy(platformBase);
                    platformHour.setWebSite(setting.getValue());
                    platformHourModel.savePlatformHour(platformHour);
                } catch (Exception e) {
                    log.error("保存平台小时统计出错", e);
                }

                try {
                    //8.保存省份统计
                    Collection<ProvinceStatsBO> provinceStatsBos = statsDataUtil.buildProvinceStatsInfo(basicDataBO);
                    provinceStatsBos.forEach(provinceStatsBO -> {
                        ProvinceBase provinceBase = provinceStatsBO.initStats(startTime);
                        ProvinceHour provinceHour = new ProvinceHour();
                        provinceHour.copy(provinceBase);
                        provinceHourModel.saveProvinceHour(provinceHour);
                    });
                } catch (Exception e) {
                    log.error("保存商品省份小时统计出错", e);
                }

                try {
                    //9.保存店铺统计
                    Collection<StoreStatsBO> storeStatsBos = statsDataUtil.buildStoreStatsInfo(basicDataBO);
                    storeStatsBos.forEach(storeStatsBO -> {
                        StoreBase storeBase = storeStatsBO.initStats(startTime);
                        StoreHour storeHour = new StoreHour();
                        storeHour.copy(storeBase);
                        storeHour.setWebSite(setting.getValue());
                        storeHourModel.saveStoreHour(storeHour);
                    });
                } catch (Exception e) {
                    log.error("保存店铺小时统计出错", e);
                }

                try {
                    //10.保存终端统计
                    Collection<TerminalStatsBO> terminalStatsBos = statsDataUtil.buildTerminalStatsInfo(basicDataBO);
                    terminalStatsBos.forEach(terminalStatsBO -> {
                        TerminalBase terminalBase = terminalStatsBO.initStats(startTime);
                        TerminalHour terminalHour = new TerminalHour();
                        terminalHour.copy(terminalBase);
                        terminalHourModel.saveTerminalHour(terminalHour);
                    });
                } catch (Exception e) {
                    log.error("保存终端小时统计出错", e);
                }
            });
        }

    }

    /**
     * 日统计任务
     * 每日执行一次，统计上一日内的数据，执行时间eg. 2020-12-12 00:00:30
     */
    @Scheduled(cron = "30 0 0 * * ? ")
    @SchedulerLock(name = "dayStats", lockAtMostFor = "86400000", lockAtLeastFor = "82800000")
    public void dayStats() {
        Date now = new Date();
        Date startTime = StatsTimeType.getStartTime(now, StatsTimeType.DAY);
        Date endTime = StatsTimeType.getEndTime(now, StatsTimeType.DAY);


        List<Setting> siteSetting = settingModel.getSiteSetting();
        if (!CollectionUtils.isEmpty(siteSetting)) {
            siteSetting.forEach(setting -> {
                StatsBasicDataBO basicDataBO;
                try {
                    //1.查询阶段内的统计基础数据
                    basicDataBO = statsDataUtil.searchStatsBasicData(startTime, endTime, setting.getValue());
                } catch (Exception e) {
                    log.error("查询阶段内的日统计基础数据出错", e);
                    return;
                }

                try {
                    //2.保存品牌统计表
                    Collection<BrandOrderBO> brandOrderBos = statsDataUtil.buildBrandStatsInfo(basicDataBO);
                    brandOrderBos.forEach(brandOrderBO -> {
                        BrandBase brandBase = brandOrderBO.initStats(startTime, basicDataBO.getOrderMap());
                        BrandDay brandDay = new BrandDay();
                        brandDay.copy(brandBase);
                        brandDay.setWebSite(setting.getValue());
                        brandDayModel.saveBrandDay(brandDay);
                    });
                } catch (Exception e) {
                    log.error("保存品牌日统计出错", e);
                }

                try {
                    //3.保存商品分类统计表
                    Collection<CategoryOrderBO> categoryOrderBos = statsDataUtil.buildCategoryStatsInfo(basicDataBO);
                    categoryOrderBos.forEach(categoryOrderBO -> {
                        CategoryBase categoryBase = categoryOrderBO.initStats(startTime, basicDataBO.getOrderMap());
                        CategoryDay categoryDay = new CategoryDay();
                        categoryDay.copy(categoryBase);
                        categoryDay.setWebSite(setting.getValue());
                        categoryDayModel.saveCategoryDay(categoryDay);
                    });
                } catch (Exception e) {
                    log.error("保存商品分类日统计出错", e);
                }

                try {
                    //4.保存商品统计
                    Collection<GoodsStatsBO> goodsStatsBos = statsDataUtil.buildGoodsStatsInfo(basicDataBO);
                    goodsStatsBos.forEach(goodsStatsBO -> {
                        GoodsBase goodsBase = goodsStatsBO.initStats(startTime, basicDataBO.getOrderMap());
                        GoodsDay goodsDay = new GoodsDay();
                        goodsDay.copy(goodsBase);
                        goodsDay.setWebSite(setting.getValue());
                        goodsDayModel.saveGoodsDay(goodsDay);
                    });
                } catch (Exception e) {
                    log.error("保存商品日统计出错", e);
                }

                try {
                    //5.保存会员统计
                    Collection<MemberStatsBO> memberStatsBos = statsDataUtil.buildMemberStatsInfo(basicDataBO);
                    memberStatsBos.forEach(memberStatsBO -> {
                        MemberBase memberBase = memberStatsBO.initStats(startTime);
                        MemberDay memberDay = new MemberDay();
                        memberDay.copy(memberBase);
                        memberDay.setWebSite(setting.getValue());
                        memberDayModel.saveMemberDay(memberDay);
                    });
                } catch (Exception e) {
                    log.error("保存会员日统计出错", e);
                }

                try {
                    //6.保存店铺会员统计
                    Collection<MemberStoreStatsBO> memberStoreStatsBos = statsDataUtil.buildMemberStoreStatsInfo(basicDataBO);
                    memberStoreStatsBos.forEach(memberStoreStatsBO -> {
                        MemberStoreBase memberStoreBase = memberStoreStatsBO.initStats(startTime);
                        MemberStoreDay memberStoreDay = new MemberStoreDay();
                        memberStoreDay.copy(memberStoreBase);
                        memberStoreDay.setWebSite(setting.getValue());
                        memberStoreDayModel.saveMemberStoreDay(memberStoreDay);
                    });
                } catch (Exception e) {
                    log.error("保存店铺会员日统计出错", e);
                }

                try {
                    //7.保存平台统计
                    PlatformStatsBO platformStatsBO = new PlatformStatsBO();
                    PlatformBase platformBase = platformStatsBO.initStats(startTime, basicDataBO);
                    PlatformDay platformDay = new PlatformDay();
                    platformDay.copy(platformBase);
                    platformDay.setWebSite(setting.getValue());
                    platformDayModel.savePlatformDay(platformDay);
                } catch (Exception e) {
                    log.error("保存平台日统计出错", e);
                }

                try {
                    //8.保存省份统计
                    Collection<ProvinceStatsBO> provinceStatsBos = statsDataUtil.buildProvinceStatsInfo(basicDataBO);
                    provinceStatsBos.forEach(provinceStatsBO -> {
                        ProvinceBase provinceBase = provinceStatsBO.initStats(startTime);
                        ProvinceDay provinceDay = new ProvinceDay();
                        provinceDay.copy(provinceBase);
                        provinceDayModel.saveProvinceDay(provinceDay);
                    });
                } catch (Exception e) {
                    log.error("保存省份日统计出错", e);
                }

                try {
                    //9.保存店铺统计
                    Collection<StoreStatsBO> storeStatsBos = statsDataUtil.buildStoreStatsInfo(basicDataBO);
                    storeStatsBos.forEach(storeStatsBO -> {
                        StoreBase storeBase = storeStatsBO.initStats(startTime);
                        StoreDay storeDay = new StoreDay();
                        storeDay.copy(storeBase);
                        storeDay.setWebSite(setting.getValue());
                        storeDayModel.saveStoreDay(storeDay);
                    });
                } catch (Exception e) {
                    log.error("保存店铺日统计出错", e);
                }

                try {
                    //10.保存终端统计
                    Collection<TerminalStatsBO> terminalStatsBos = statsDataUtil.buildTerminalStatsInfo(basicDataBO);
                    terminalStatsBos.forEach(terminalStatsBO -> {
                        TerminalBase terminalBase = terminalStatsBO.initStats(startTime);
                        TerminalDay terminalDay = new TerminalDay();
                        terminalDay.copy(terminalBase);
                        terminalDayModel.saveTerminalDay(terminalDay);
                    });
                } catch (Exception e) {
                    log.error("保存终端日统计出错", e);
                }
            });
        }


    }

    /**
     * 周统计任务
     * 每周一执行一次，统计上一周内的数据，执行时间eg. 2020-12-14 00:00:30
     */
    @Scheduled(cron = "30 0 0 ? * 1 ")
    @SchedulerLock(name = "weekStats", lockAtMostFor = "604800000", lockAtLeastFor = "601200000")
    public void weekStats() {
        Date now = new Date();
        Date startTime = StatsTimeType.getStartTime(now, StatsTimeType.WEEK);
        Date endTime = StatsTimeType.getEndTime(now, StatsTimeType.WEEK);

        List<Setting> siteSetting = settingModel.getSiteSetting();
        if (!CollectionUtils.isEmpty(siteSetting)) {
            siteSetting.forEach(setting -> {
                StatsBasicDataBO basicDataBO;
                try {
                    //1.查询阶段内的统计基础数据
                    basicDataBO = statsDataUtil.searchStatsBasicData(startTime, endTime, setting.getValue());
                } catch (Exception e) {
                    log.error("查询阶段内的周统计基础数据出错", e);
                    return;
                }

                try {
                    //2.保存品牌统计表
                    Collection<BrandOrderBO> brandOrderBos = statsDataUtil.buildBrandStatsInfo(basicDataBO);
                    brandOrderBos.forEach(brandOrderBO -> {
                        BrandBase brandBase = brandOrderBO.initStats(startTime, basicDataBO.getOrderMap());
                        BrandWeek brandWeek = new BrandWeek();
                        brandWeek.copy(brandBase);
                        brandWeek.setWebSite(setting.getValue());
                        brandWeekModel.saveBrandWeek(brandWeek);
                    });
                } catch (Exception e) {
                    log.error("保存品牌周统计出错", e);
                }

                try {
                    //3.保存商品分类统计表
                    Collection<CategoryOrderBO> categoryOrderBos = statsDataUtil.buildCategoryStatsInfo(basicDataBO);
                    categoryOrderBos.forEach(categoryOrderBO -> {
                        CategoryBase categoryBase = categoryOrderBO.initStats(startTime, basicDataBO.getOrderMap());
                        CategoryWeek categoryWeek = new CategoryWeek();
                        categoryWeek.copy(categoryBase);
                        categoryWeek.setWebSite(setting.getValue());
                        categoryWeekModel.saveCategoryWeek(categoryWeek);
                    });
                } catch (Exception e) {
                    log.error("保存商品分类周统计出错", e);
                }

                try {
                    //4.保存商品统计
                    Collection<GoodsStatsBO> goodsStatsBos = statsDataUtil.buildGoodsStatsInfo(basicDataBO);
                    goodsStatsBos.forEach(goodsStatsBO -> {
                        GoodsBase goodsBase = goodsStatsBO.initStats(startTime, basicDataBO.getOrderMap());
                        GoodsWeek goodsWeek = new GoodsWeek();
                        goodsWeek.copy(goodsBase);
                        goodsWeek.setWebSite(setting.getValue());
                        goodsWeekModel.saveGoodsWeek(goodsWeek);
                    });
                } catch (Exception e) {
                    log.error("保存商品周统计出错", e);
                }

                try {
                    //5.保存会员统计
                    Collection<MemberStatsBO> memberStatsBos = statsDataUtil.buildMemberStatsInfo(basicDataBO);
                    memberStatsBos.forEach(memberStatsBO -> {
                        MemberBase memberBase = memberStatsBO.initStats(startTime);
                        MemberWeek memberWeek = new MemberWeek();
                        memberWeek.copy(memberBase);
                        memberWeek.setWebSite(setting.getValue());
                        memberWeekModel.saveMemberWeek(memberWeek);
                    });
                } catch (Exception e) {
                    log.error("保存会员周统计出错", e);
                }

                try {
                    //6.保存店铺会员统计
                    Collection<MemberStoreStatsBO> memberStoreStatsBos = statsDataUtil.buildMemberStoreStatsInfo(basicDataBO);
                    memberStoreStatsBos.forEach(memberStoreStatsBO -> {
                        MemberStoreBase memberStoreBase = memberStoreStatsBO.initStats(startTime);
                        MemberStoreWeek memberStoreWeek = new MemberStoreWeek();
                        memberStoreWeek.copy(memberStoreBase);
                        memberStoreWeek.setWebSite(setting.getValue());
                        memberStoreWeekModel.saveMemberStoreWeek(memberStoreWeek);
                    });
                } catch (Exception e) {
                    log.error("保存店铺会员周统计出错", e);
                }

                try {
                    //7.保存平台统计
                    PlatformStatsBO platformStatsBO = new PlatformStatsBO();
                    PlatformBase platformBase = platformStatsBO.initStats(startTime, basicDataBO);
                    PlatformWeek platformWeek = new PlatformWeek();
                    platformWeek.copy(platformBase);
                    platformWeek.setWebSite(setting.getValue());
                    platformWeekModel.savePlatformWeek(platformWeek);
                } catch (Exception e) {
                    log.error("保存平台周统计出错", e);
                }

                try {
                    //8.保存省份统计
                    Collection<ProvinceStatsBO> provinceStatsBos = statsDataUtil.buildProvinceStatsInfo(basicDataBO);
                    provinceStatsBos.forEach(provinceStatsBO -> {
                        ProvinceBase provinceBase = provinceStatsBO.initStats(startTime);
                        ProvinceWeek provinceWeek = new ProvinceWeek();
                        provinceWeek.copy(provinceBase);
                        provinceWeekModel.saveProvinceWeek(provinceWeek);
                    });
                } catch (Exception e) {
                    log.error("保存省份周统计出错", e);
                }

                try {
                    //9.保存店铺统计
                    Collection<StoreStatsBO> storeStatsBos = statsDataUtil.buildStoreStatsInfo(basicDataBO);
                    storeStatsBos.forEach(storeStatsBO -> {
                        StoreBase storeBase = storeStatsBO.initStats(startTime);
                        StoreWeek storeWeek = new StoreWeek();
                        storeWeek.copy(storeBase);
                        storeWeek.setWebSite(setting.getValue());
                        storeWeekModel.saveStoreWeek(storeWeek);
                    });
                } catch (Exception e) {
                    log.error("保存店铺周统计出错", e);
                }

                try {
                    //10.保存终端统计
                    Collection<TerminalStatsBO> terminalStatsBos = statsDataUtil.buildTerminalStatsInfo(basicDataBO);
                    terminalStatsBos.forEach(terminalStatsBO -> {
                        TerminalBase terminalBase = terminalStatsBO.initStats(startTime);
                        TerminalWeek terminalWeek = new TerminalWeek();
                        terminalWeek.copy(terminalBase);
                        terminalWeekModel.saveTerminalWeek(terminalWeek);
                    });
                } catch (Exception e) {
                    log.error("保存终端周统计出错", e);
                }
            });
        }
    }

    /**
     * 月统计任务
     * 每月1号执行一次，统计上一个月内的数据，执行时间eg. 2020-12-01 00:00:30
     */
    @Scheduled(cron = "30 0 0 1 * ? ")
    @SchedulerLock(name = "monthStats", lockAtMostFor = "2419200000", lockAtLeastFor = "2332800000")
    public void monthStats() {
        Date now = new Date();
        Date startTime = StatsTimeType.getStartTime(now, StatsTimeType.MONTH);
        Date endTime = StatsTimeType.getEndTime(now, StatsTimeType.MONTH);

        List<Setting> siteSetting = settingModel.getSiteSetting();
        if (!CollectionUtils.isEmpty(siteSetting)) {
            siteSetting.forEach(setting -> {
                StatsBasicDataBO basicDataBO;
                try {
                    //1.查询阶段内的统计基础数据
                    basicDataBO = statsDataUtil.searchStatsBasicData(startTime, endTime, setting.getValue());
                } catch (Exception e) {
                    log.error("查询阶段内的月统计基础数据出错", e);
                    return;
                }

                try {
                    //2.保存品牌统计表
                    Collection<BrandOrderBO> brandOrderBos = statsDataUtil.buildBrandStatsInfo(basicDataBO);
                    brandOrderBos.forEach(brandOrderBO -> {
                        BrandBase brandBase = brandOrderBO.initStats(startTime, basicDataBO.getOrderMap());
                        BrandMonth brandMonth = new BrandMonth();
                        brandMonth.copy(brandBase);
                        brandMonth.setWebSite(setting.getValue());
                        brandMonthModel.saveBrandMonth(brandMonth);
                    });
                } catch (Exception e) {
                    log.error("保存品牌月统计出错", e);
                }

                try {
                    //3.保存商品分类统计表
                    Collection<CategoryOrderBO> categoryOrderBos = statsDataUtil.buildCategoryStatsInfo(basicDataBO);
                    categoryOrderBos.forEach(categoryOrderBO -> {
                        CategoryBase categoryBase = categoryOrderBO.initStats(startTime, basicDataBO.getOrderMap());
                        CategoryMonth categoryMonth = new CategoryMonth();
                        categoryMonth.copy(categoryBase);
                        categoryMonth.setWebSite(setting.getValue());
                        categoryMonthModel.saveCategoryMonth(categoryMonth);
                    });
                } catch (Exception e) {
                    log.error("保存商品分类月统计出错", e);
                }

                try {
                    //4.保存商品统计
                    Collection<GoodsStatsBO> goodsStatsBos = statsDataUtil.buildGoodsStatsInfo(basicDataBO);
                    goodsStatsBos.forEach(goodsStatsBO -> {
                        GoodsBase goodsBase = goodsStatsBO.initStats(startTime, basicDataBO.getOrderMap());
                        GoodsMonth goodsMonth = new GoodsMonth();
                        goodsMonth.copy(goodsBase);
                        goodsMonth.setWebSite(setting.getValue());
                        goodsMonthModel.saveGoodsMonth(goodsMonth);
                    });
                } catch (Exception e) {
                    log.error("保存商品月统计出错", e);
                }

                try {
                    //5.保存会员统计
                    Collection<MemberStatsBO> memberStatsBos = statsDataUtil.buildMemberStatsInfo(basicDataBO);
                    memberStatsBos.forEach(memberStatsBO -> {
                        MemberBase memberBase = memberStatsBO.initStats(startTime);
                        MemberMonth memberMonth = new MemberMonth();
                        memberMonth.copy(memberBase);
                        memberMonth.setWebSite(setting.getValue());
                        memberMonthModel.saveMemberMonth(memberMonth);
                    });
                } catch (Exception e) {
                    log.error("保存会员月统计出错", e);
                }

                try {
                    //6.保存店铺会员统计
                    Collection<MemberStoreStatsBO> memberStoreStatsBos = statsDataUtil.buildMemberStoreStatsInfo(basicDataBO);
                    memberStoreStatsBos.forEach(memberStoreStatsBO -> {
                        MemberStoreBase memberStoreBase = memberStoreStatsBO.initStats(startTime);
                        MemberStoreMonth memberStoreMonth = new MemberStoreMonth();
                        memberStoreMonth.copy(memberStoreBase);
                        memberStoreMonth.setWebSite(setting.getValue());
                        memberStoreMonthModel.saveMemberStoreMonth(memberStoreMonth);
                    });
                } catch (Exception e) {
                    log.error("保存店铺会员月统计出错", e);
                }

                try {
                    //7.保存平台统计
                    PlatformStatsBO platformStatsBO = new PlatformStatsBO();
                    PlatformBase platformBase = platformStatsBO.initStats(startTime, basicDataBO);
                    PlatformMonth platformMonth = new PlatformMonth();
                    platformMonth.copy(platformBase);
                    platformMonth.setWebSite(setting.getValue());
                    platformMonthModel.savePlatformMonth(platformMonth);
                } catch (Exception e) {
                    log.error("保存品平台月统计出错", e);
                }

                try {
                    //8.保存省份统计
                    Collection<ProvinceStatsBO> provinceStatsBos = statsDataUtil.buildProvinceStatsInfo(basicDataBO);
                    provinceStatsBos.forEach(provinceStatsBO -> {
                        ProvinceBase provinceBase = provinceStatsBO.initStats(startTime);
                        ProvinceMonth provinceMonth = new ProvinceMonth();
                        provinceMonth.copy(provinceBase);
                        provinceMonthModel.saveProvinceMonth(provinceMonth);
                    });
                } catch (Exception e) {
                    log.error("保存省份月统计出错", e);
                }

                try {
                    //9.保存店铺统计
                    Collection<StoreStatsBO> storeStatsBos = statsDataUtil.buildStoreStatsInfo(basicDataBO);
                    storeStatsBos.forEach(storeStatsBO -> {
                        StoreBase storeBase = storeStatsBO.initStats(startTime);
                        StoreMonth storeMonth = new StoreMonth();
                        storeMonth.copy(storeBase);
                        storeMonth.setWebSite(setting.getValue());
                        storeMonthModel.saveStoreMonth(storeMonth);
                    });
                } catch (Exception e) {
                    log.error("保存店铺月统计出错", e);
                }

                try {
                    //10.保存终端统计
                    Collection<TerminalStatsBO> terminalStatsBos = statsDataUtil.buildTerminalStatsInfo(basicDataBO);
                    terminalStatsBos.forEach(terminalStatsBO -> {
                        TerminalBase terminalBase = terminalStatsBO.initStats(startTime);
                        TerminalMonth terminalMonth = new TerminalMonth();
                        terminalMonth.copy(terminalBase);
                        terminalMonthModel.saveTerminalMonth(terminalMonth);
                    });
                } catch (Exception e) {
                    log.error("保存终端月统计出错", e);
                }
            });
        }
    }

    /**
     * 年统计任务
     * 每年1月1号执行一次，统计上一年内的数据，执行时间eg. 2021-01-01 00:00:30
     */
    @Scheduled(cron = "30 0 0 1 1 ? ")
    @SchedulerLock(name = "yearStats", lockAtMostFor = "31536000000", lockAtLeastFor = "31104000000")
    public void yearStats() {
        Date now = new Date();
        Date startTime = StatsTimeType.getStartTime(now, StatsTimeType.YEAR);
        Date endTime = StatsTimeType.getEndTime(now, StatsTimeType.YEAR);

        List<Setting> siteSetting = settingModel.getSiteSetting();
        if (!CollectionUtils.isEmpty(siteSetting)) {
            siteSetting.forEach(setting -> {

                StatsBasicDataBO basicDataBO;
                try {
                    //1.查询阶段内的统计基础数据
                    basicDataBO = statsDataUtil.searchStatsBasicData(startTime, endTime, setting.getValue());
                } catch (Exception e) {
                    log.error("查询阶段内的年统计基础数据出错", e);
                    return;
                }

                try {
                    //2.保存品牌统计表
                    Collection<BrandOrderBO> brandOrderBos = statsDataUtil.buildBrandStatsInfo(basicDataBO);
                    brandOrderBos.forEach(brandOrderBO -> {
                        BrandBase brandBase = brandOrderBO.initStats(startTime, basicDataBO.getOrderMap());
                        BrandYear brandYear = new BrandYear();
                        brandYear.copy(brandBase);
                        brandYear.setWebSite(setting.getValue());
                        brandYearModel.saveBrandYear(brandYear);
                    });
                } catch (Exception e) {
                    log.error("保存品牌年统计出错", e);
                }

                try {
                    //3.保存商品分类统计表
                    Collection<CategoryOrderBO> categoryOrderBos = statsDataUtil.buildCategoryStatsInfo(basicDataBO);
                    categoryOrderBos.forEach(categoryOrderBO -> {
                        CategoryBase categoryBase = categoryOrderBO.initStats(startTime, basicDataBO.getOrderMap());
                        CategoryYear categoryYear = new CategoryYear();
                        categoryYear.copy(categoryBase);
                        categoryYear.setWebSite(setting.getValue());
                        categoryYearModel.saveCategoryYear(categoryYear);
                    });
                } catch (Exception e) {
                    log.error("保存品商品分类年统计出错", e);
                }

                try {
                    //4.保存商品统计
                    Collection<GoodsStatsBO> goodsStatsBos = statsDataUtil.buildGoodsStatsInfo(basicDataBO);
                    goodsStatsBos.forEach(goodsStatsBO -> {
                        GoodsBase goodsBase = goodsStatsBO.initStats(startTime, basicDataBO.getOrderMap());
                        GoodsYear goodsYear = new GoodsYear();
                        goodsYear.copy(goodsBase);
                        goodsYear.setWebSite(setting.getValue());
                        goodsYearModel.saveGoodsYear(goodsYear);
                    });
                } catch (Exception e) {
                    log.error("保存商品年统计出错", e);
                }

                try {
                    //5.保存会员统计
                    Collection<MemberStatsBO> memberStatsBos = statsDataUtil.buildMemberStatsInfo(basicDataBO);
                    memberStatsBos.forEach(memberStatsBO -> {
                        MemberBase memberBase = memberStatsBO.initStats(startTime);
                        MemberYear memberYear = new MemberYear();
                        memberYear.copy(memberBase);
                        memberYear.setWebSite(setting.getValue());
                        memberYearModel.saveMemberYear(memberYear);
                    });
                } catch (Exception e) {
                    log.error("保存会员年统计出错", e);
                }

                try {
                    //6.保存店铺会员统计
                    Collection<MemberStoreStatsBO> memberStoreStatsBos = statsDataUtil.buildMemberStoreStatsInfo(basicDataBO);
                    memberStoreStatsBos.forEach(memberStoreStatsBO -> {
                        MemberStoreBase memberStoreBase = memberStoreStatsBO.initStats(startTime);
                        MemberStoreYear memberStoreYear = new MemberStoreYear();
                        memberStoreYear.copy(memberStoreBase);
                        memberStoreYear.setWebSite(setting.getValue());
                        memberStoreYearModel.saveMemberStoreYear(memberStoreYear);
                    });
                } catch (Exception e) {
                    log.error("保存店铺会员年统计出错", e);
                }

                try {
                    //7.保存平台统计
                    PlatformStatsBO platformStatsBO = new PlatformStatsBO();
                    PlatformBase platformBase = platformStatsBO.initStats(startTime, basicDataBO);
                    PlatformYear platformYear = new PlatformYear();
                    platformYear.copy(platformBase);
                    platformYear.setWebSite(setting.getValue());
                    platformYearModel.savePlatformYear(platformYear);
                } catch (Exception e) {
                    log.error("保存平台年统计出错", e);
                }

                try {
                    //8.保存省份统计
                    Collection<ProvinceStatsBO> provinceStatsBos = statsDataUtil.buildProvinceStatsInfo(basicDataBO);
                    provinceStatsBos.forEach(provinceStatsBO -> {
                        ProvinceBase provinceBase = provinceStatsBO.initStats(startTime);
                        ProvinceYear provinceYear = new ProvinceYear();
                        provinceYear.copy(provinceBase);
                        provinceYearModel.saveProvinceYear(provinceYear);
                    });
                } catch (Exception e) {
                    log.error("保存省份年统计出错", e);
                }

                try {
                    //9.保存店铺统计
                    Collection<StoreStatsBO> storeStatsBos = statsDataUtil.buildStoreStatsInfo(basicDataBO);
                    storeStatsBos.forEach(storeStatsBO -> {
                        StoreBase storeBase = storeStatsBO.initStats(startTime);
                        StoreYear storeYear = new StoreYear();
                        storeYear.copy(storeBase);
                        storeYear.setWebSite(setting.getValue());
                        storeYearModel.saveStoreYear(storeYear);
                    });
                } catch (Exception e) {
                    log.error("保存店铺年统计出错", e);
                }

                try {
                    //10.保存终端统计
                    Collection<TerminalStatsBO> terminalStatsBos = statsDataUtil.buildTerminalStatsInfo(basicDataBO);
                    terminalStatsBos.forEach(terminalStatsBO -> {
                        TerminalBase terminalBase = terminalStatsBO.initStats(startTime);
                        TerminalYear terminalYear = new TerminalYear();
                        terminalYear.copy(terminalBase);
                        terminalYearModel.saveTerminalYear(terminalYear);
                    });
                } catch (Exception e) {
                    log.error("保存终端年统计出错", e);
                }
            });
        }

    }

    /**
     * 实时统计数据更新
     * 每个1小时更新一次
     */
    @Scheduled(cron = "0 0 0/1 * * ? ")
    @SchedulerLock(name = "presentDataReset", lockAtMostFor = "3600000", lockAtLeastFor = "3000000")
    public void presentDataReset() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        //结束时间，当前小时
        Date endTime = calendar.getTime();
        //今日0时开始
        Date startTime = DateUtil.beginOfDay(endTime);

        List<Setting> settings=settingModel.getSiteSetting();
        settings.forEach(setting -> {
            //计算平台实时统计数据
            AdminPresentDataVO vo = platformPresentDataUtil.calculatePresentData(startTime, endTime,setting.getValue());
            //缓存数据
            objectRedisTemplate.opsForHash().put(StatsConstant.ADMIN_PRESENT_REDIS_KEY + "_" + setting.getValue(), StatsConstant.ADMIN_PRESENT_REDIS_KEY + "_" + setting.getValue(), vo);
        });



        List<Setting> settingList = settingModel.getSiteSetting();
        if (!CollectionUtils.isEmpty(settingList)) {
            settingList.forEach(setting -> {
                //查询所有有统计缓存店铺，redis set中的hashkey即为店铺id
                Set<Object> keys = objectRedisTemplate.opsForHash().keys(StatsConstant.SELLER_PRESENT_REDIS_KEY + "_" + setting.getValue());
                if (!CollectionUtils.isEmpty(keys)) {
                    keys.forEach(o -> {
                        //计算实时统计数据
                        SellerPresentDataVO sellerPresentDataVO = sellerPresentDataUtil.calculatePresentData(startTime, endTime, setting.getValue(), Long.parseLong((String) o));
                        //缓存数据
                        objectRedisTemplate.opsForHash().put(StatsConstant.SELLER_PRESENT_REDIS_KEY + "_" + setting.getValue(), o, sellerPresentDataVO);
                    });
                }
            });

        }


    }
}
