package com.platform.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.platform.entity.BrandEntity;
import com.platform.entity.TmSceneCensus;
import com.platform.entity.TmTaskLog;
import com.platform.service.custom.*;
import com.platform.service.impl.BrandServiceImpl;
import com.platform.service.impl.OrderServiceImpl;
import com.platform.utils.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author abnerhou
 * @date 2020/9/3 14:22
 * @desciption
 */
@Component
@EnableScheduling
@Async
@Slf4j
public class SceneStatisticTask {

    private static final long PAGE_SIZE = 100L;

    @Autowired
    TaskLogService taskLogService;

    @Autowired
    BrandServiceImpl brandService;

    @Autowired
    SceneCensusService sceneCensusService;

    @Autowired
    OrderServiceImpl orderService;

    @Autowired
    GoodsVisitHistoryService goodsVisitHistoryService;

    @Autowired
    private OrderDealLogService orderDealLogService;

    @Autowired
    private GoodsDetailLogService goodsDetailLogService;

    @Value("${4dkankan.api.vr.show.host}")
    private String openApiUrl;

   @Autowired
    private RestTemplate restTemplate;


    /**
     * 默认是fixedDelay 上一次执行完毕时间后执行下一轮
     */
    @Scheduled(cron = "0 */15 5-23 * * ?")
    public void run() throws InterruptedException {

        DateTimeFormatter localDateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate today = LocalDate.parse(LocalDate.now().toString(), localDateFormat);
        log.info("============开始日期[{}]的执行统计任务============", today);
        TmTaskLog tmTaskLog = taskLogService.getTaskByDate(today);
        if (null == tmTaskLog) {
            log.info("当天第一次执行统计任务");
            IPage<BrandEntity> resultPage = brandService.queryBrandList(1l, PAGE_SIZE, null);
            if (null != resultPage && resultPage.getTotal() > 0) {

                List<BrandEntity> companyVoList = resultPage.getRecords();
                if (CollectionUtils.isEmpty(companyVoList)) {
                    log.warn("获取到公司列表为空，但是总统计数不为空");
                    return;
                }
                long finishedNum = doCensus(companyVoList, today);
                log.info("当前任务完成的数量为：{}，总数为:{}", finishedNum , resultPage.getTotal());
                //新建
                TmTaskLog newTaskLog = new TmTaskLog();
                newTaskLog.setTaskDate(today);
                newTaskLog.setTotalNum(resultPage.getTotal());
                newTaskLog.setPageSize(PAGE_SIZE);
                newTaskLog.setHasFinishedNum(finishedNum);
                newTaskLog.setTotalPages(resultPage.getPages());
                newTaskLog.setCurrentPage(resultPage.getCurrent());
                //任务状态: 1->初始; 2->执行中;3->完成
                if (finishedNum == resultPage.getTotal()) {
                    newTaskLog.setTaskStatus(3);
                } else {
                    newTaskLog.setTaskStatus(2);
                }
                int taskInsert = taskLogService.insertTaskLog(newTaskLog);
                if (taskInsert != 1) {
                    log.error("任务日期：[{}]新增任务[{}]失败", today, JSON.toJSONString(newTaskLog));
                }
            } else {
                log.warn("获取公司列表失败，不创建当天[{}]任务", today);
            }

        } else {

            if (null != tmTaskLog.getHasFinishedNum() && null != tmTaskLog.getTotalNum()) {
                if (tmTaskLog.getTotalNum().compareTo(tmTaskLog.getHasFinishedNum()) == 0) {
                    log.info("任务[{}]在日期[{}]已经完成所有统计，不再执行统计逻辑", tmTaskLog.getTaskId(), tmTaskLog.getTaskDate());
                    if (null != tmTaskLog && tmTaskLog.getTaskStatus().compareTo(2) == 0) {
                        tmTaskLog.setTaskStatus(3);
                        taskLogService.updateTaskLog(tmTaskLog);
                    }
                    return;
                }
            }

            //已经存在，则
            long curPageNum = tmTaskLog.getCurrentPage() != null ? tmTaskLog.getCurrentPage() : 0;
            long nextPageNum = curPageNum + 1;
            log.info("之前获取到页码为:{}，将要获取页码为:{}", curPageNum, nextPageNum);
            IPage<BrandEntity> resultPage = brandService.queryBrandList(nextPageNum, PAGE_SIZE, "");
            if (null != resultPage && resultPage.getTotal() > 0) {
                List<BrandEntity> brandVoList = resultPage.getRecords();
                if (CollectionUtils.isEmpty(brandVoList)) {
                    log.warn("获取到公司列表为空，但是总统计数不为空");
                    return;
                }
                long finishedNum = doCensus(brandVoList, today);
                long preFinishedNum = tmTaskLog.getHasFinishedNum() != null ? tmTaskLog.getHasFinishedNum() : 0;
                long latestFinishedNum = finishedNum + preFinishedNum;
                if (tmTaskLog.getHasFinishedNum().compareTo(latestFinishedNum) != 0) {
                    tmTaskLog.setHasFinishedNum(latestFinishedNum);
                    tmTaskLog.setCurrentPage(nextPageNum);
                    tmTaskLog.setUpdateTime(LocalDateTime.now());
                    int update = taskLogService.updateTaskLog(tmTaskLog);
                    if (update != 1) {
                        log.error("日期[{}]更新任务[{}]的已完成数[{}]失败", today, tmTaskLog.getTaskId(), latestFinishedNum);
                    }
                }
            } else {
                log.warn("分支二获取公司列表失败，不创建当天[{}]任务", today);
            }
        }
        log.info("============统计任务已执行完============");
    }

    private long doCensus(List<BrandEntity> brandEntityList, LocalDate today) {
        long finishedNum = 0l;
        for (BrandEntity brandEntity : brandEntityList) {
            if (StringUtils.isBlank(brandEntity.getSceneNum())) {
                log.info("店铺[{}]的场景为空，不做统计，跳过" , brandEntity.getId());
                continue;
            }
            log.info("将执行场景[{}]的统计" , brandEntity.getSceneNum());
            TmSceneCensus dbSceneCensus = sceneCensusService.getCensusBySceneNum(brandEntity.getSceneNum(),  today.plusDays(-1));
            if (null == dbSceneCensus) {
                log.info("场景码:{}的统计日期:{}统计记录不存在，将新增", brandEntity.getSceneNum(), today);
                LocalDate yesterday = today.plusDays(-1);
                LocalDate start = yesterday.plusDays(-6);
                LocalDate end = yesterday;
                LocalDate theDayBeforYesterday = yesterday.plusDays(-1);
                //不存在，才创建
                Map<String, Object> pvUvMap = sceneCensusService.getPvUvHistoryFromKankan(start, end, brandEntity.getSceneNum());
                List<Map<String, Object>> scenePvList = (List<Map<String, Object>>) pvUvMap.get("pv");
                List<Map<String, Object>> sceneUvList = (List<Map<String, Object>>) pvUvMap.get("uv");
                List<Map<String, Object>> hotVisitList = sceneCensusService.getHotHistoryFromKankan(start, end, brandEntity.getSceneNum());
                long totalVisitTalk = goodsVisitHistoryService.countTotalBySceneNum(brandEntity.getSceneNum());
                List<Map<String, Object>> talkHistory = goodsVisitHistoryService.getHistoryByRangeTwo(start, 7, brandEntity.getSceneNum());
                String talkHistoryStr = JSON.toJSONString(talkHistory);
                TmSceneCensus preSceneCensus = sceneCensusService.getCensusBySceneNum(brandEntity.getSceneNum(), theDayBeforYesterday);
                TmSceneCensus tmSceneCensus = new TmSceneCensus();
                tmSceneCensus.setCompanyId(brandEntity.getId().toString());
                tmSceneCensus.setCompanyName(brandEntity.getName());
                tmSceneCensus.setSceneNum(brandEntity.getSceneNum());
                tmSceneCensus.setCensusDate(end);
                tmSceneCensus.setPvHistory(JSON.toJSONString(scenePvList));
                tmSceneCensus.setUvHistory(JSON.toJSONString(sceneUvList));
                tmSceneCensus.setHotVisitHistory(JSON.toJSONString(hotVisitList));
                tmSceneCensus.setLastModifyDatetime(LocalDateTime.now());
                tmSceneCensus.setCreateTime(LocalDateTime.now());
                tmSceneCensus.setCompanyId(brandEntity.getId().toString());
                tmSceneCensus.setTotalTalkNum(totalVisitTalk);
                tmSceneCensus.setTalkHistory(talkHistoryStr);
                tmSceneCensus.setCensusSize(7);
                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                //当天成交量
                long curDealOrderNum = orderDealLogService.getDealNumByBrandId(end , brandEntity.getId().intValue());
                tmSceneCensus.setDealNum(curDealOrderNum);
                //近七天成交量
                long dealTotalNum = 0;
                dealTotalNum += curDealOrderNum;
                //近七天成交量历史
                List<Map<String , Object>> dealOrderNumList = new ArrayList<>();

                //近七天商品详情pv
                long goodsDetailLogTotalNum = 0;

                //当天商品详情PV
                long goodsDetailLogNum = goodsDetailLogService.countByVisitDate(end , brandEntity.getSceneNum());
                tmSceneCensus.setGoodsDetailVisitNum(goodsDetailLogNum);
                goodsDetailLogTotalNum += goodsDetailLogNum;


                //近七天商品详情PV列表
                List<Map<String , Object>> goodsDetailLogNumList = new ArrayList<>();

                Map<String , Object> curDealMap = new HashMap<>();
                Map<String , Object> curGoodDetailLogMap = new HashMap<>();
                //先登记当天的成交量
                curDealMap.put(dateTimeFormatter.format(end) , curDealOrderNum);

                //先登记当天的商品详情pv
                curGoodDetailLogMap.put(dateTimeFormatter.format(end) , goodsDetailLogNum);

                for(int i = 6; i> 0 ; i--){
                    LocalDate theDate = end.plusDays(-i);
                    //累加当天的成交量
                    long tempDealNum = orderDealLogService.getDealNumByBrandId(theDate , brandEntity.getId().intValue());
                    dealTotalNum += tempDealNum;

                    Map<String , Object> tmpMap = new HashMap<>();
                    tmpMap.put(dateTimeFormatter.format(theDate) , tempDealNum);
                    dealOrderNumList.add(tmpMap);

                    long tmpGoodDetailLogNum = goodsDetailLogService.countByVisitDate(theDate , brandEntity.getSceneNum());
                    goodsDetailLogTotalNum += tmpGoodDetailLogNum;
                    Map<String , Object> tmpGoodDetailMap = new HashMap<>();
                    tmpGoodDetailMap.put(dateTimeFormatter.format(theDate) , tmpGoodDetailLogNum);
                    goodsDetailLogNumList.add(tmpGoodDetailMap);

                }
                //最后才写当天，因为，前端需要一个返回一个时间按照创建时间升序的列表
                dealOrderNumList.add(curDealMap);
                goodsDetailLogNumList.add(curGoodDetailLogMap);
                //复制历史（近七天的数值）
                tmSceneCensus.setDealHistory(JSON.toJSONString(dealOrderNumList));
                tmSceneCensus.setGoodsDetailVisitHistory(JSON.toJSONString(goodsDetailLogNumList));
                if(null != preSceneCensus && null != preSceneCensus.getDealTotalNum()){
                    dealTotalNum += preSceneCensus.getDealTotalNum();
                }
                tmSceneCensus.setDealTotalNum(dealTotalNum);
                long prePvTotalNum = 0;
                long preUvTotalNum = 0;
                if (null != preSceneCensus) {
                    log.info("前一天存在统计数据，将总数累加计算");
                    //存在昨天的统计，则累加pv,uv,询盘总数
                    prePvTotalNum = preSceneCensus.getPvTotalNum() != null ? preSceneCensus.getPvTotalNum() : 0;
                    preUvTotalNum = preSceneCensus.getUvTotalNum() != null ? preSceneCensus.getUvTotalNum() : 0;
                }
                long latestPvTotalNum = prePvTotalNum;
                long latestUvTotalNum = preUvTotalNum;
                if (!CollectionUtils.isEmpty(scenePvList)) {
                    if(null != preSceneCensus){
                        //这里最后一个就是最新的统计日期
                        Map<String, Object> curPvResult = scenePvList.get(scenePvList.size() -1);
                        if(!CollectionUtils.isEmpty(curPvResult)){
                            log.info("获取到的最新的统计数据为:{}" , JSON.toJSONString(curPvResult));
                            Integer curDatePvNum = (Integer) curPvResult.get(end +" 00:00:00");
                            long tmp = null != curDatePvNum ? curDatePvNum.longValue() : 0;
                            latestPvTotalNum += tmp;
                        }

                    }else{
                        //首次添加，则遍历所有当前的历史数据累加
                        for(int i = 0 ; i < scenePvList.size() ; i++){
                            Map<String, Object> curPvResult = scenePvList.get(i);
                            for (Map.Entry entry : curPvResult.entrySet()) {
                                log.info("当前统计日期为:{}，获取到当天的pv统计日期为:{},数量为:{},截止前一天的总数为:{}",
                                        yesterday, entry.getKey(), entry.getValue(), latestPvTotalNum);
                                long tmp = ((Integer) entry.getValue()).longValue();
                                latestPvTotalNum += tmp;
                            }
                        }
                    }

                }

                if (!CollectionUtils.isEmpty(sceneUvList)) {
                    if(null != preSceneCensus){
                        //非首次统计当前场景，则
                        Map<String, Object> curUvResult = sceneUvList.get(sceneUvList.size() - 1);
                        if(!CollectionUtils.isEmpty(curUvResult)){
                            log.info("获取到的最新的统计数据为:{}" , JSON.toJSONString(curUvResult));
                            Integer curDateUvNum = (Integer) curUvResult.get(end +" 00:00:00");
                            log.info("当前统计日期为:{}，获取到当天的Uv统计日期为:{},数量为:{},截止前一天的总数为:{}",
                                    yesterday, end, curDateUvNum, latestUvTotalNum);
                            long tmp = null != curDateUvNum ? curDateUvNum.longValue() : 0;
                            latestUvTotalNum += tmp;
                        }

                    }else{
                        //首次添加，则遍历所有当前的历史数据累加
                        for(int i = 0 ; i < sceneUvList.size() ; i++){
                            Map<String, Object> curUvResult = sceneUvList.get(i);
                            for (Map.Entry entry : curUvResult.entrySet()) {
                                log.info("当前统计日期为:{}，获取到当天的Uv统计日期为:{},数量为:{},截止前一天的总数为:{}",
                                        yesterday, entry.getKey(), entry.getValue(), latestUvTotalNum);
                                long tmp = null != entry ? ((Integer) entry.getValue()).longValue() : 0;
                                latestUvTotalNum += tmp;
                            }
                        }
                    }


                }

                tmSceneCensus.setPvTotalNum(latestPvTotalNum);
                tmSceneCensus.setUvTotalNum(latestUvTotalNum);

                //从商圈API获取店铺下面所有商品的数量
                String shopApiUrl = openApiUrl + "4dage/shop/getGoodsNum?sceneNum=" + brandEntity.getSceneNum();

                String resultString = HttpClientUtil.doGet(shopApiUrl);
                log.info("商圈api返回详情:{}", JSON.toJSONString(resultString));
                JSONObject resObj = JSON.parseObject(resultString, JSONObject.class);
                if (null != resObj) {
                    int code = resObj.getInteger("code");
                    if (code == 0) {
                        Integer goodsNum = resObj.getInteger("data");
                        if (null != goodsNum) {
                            log.info("场景的[{}]的商品数为:{}" , brandEntity.getSceneNum() , goodsNum);
                            tmSceneCensus.setGoodsNum(goodsNum);
                        } else {
                            log.info("从商圈api获取到的商品数为空");
                        }

                    }
                }else{
                    log.info("场景[{}]获取商品数失败" , brandEntity.getSceneNum() );
                }
                int insert = sceneCensusService.addSceneCensus(tmSceneCensus);
                if (insert != 1) {
                    log.warn("新增场景[{}]-日期[{}]统计失败", brandEntity.getSceneNum(), end);
                } else {
                    finishedNum += 1;
                }
            }else{
                log.info("场景[{}]的统计记录已经存在，不在新增" , brandEntity.getSceneNum());
            }
        }
        return finishedNum;
    }

}
