package com.platform.service.custom;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.platform.entity.TmSceneCensus;
import com.platform.enums.IdStarterEnum;
import com.platform.enums.ResultCodeEnum;
import com.platform.exception.CommonBaseException;
import com.platform.service.impl.TmSceneCensusServiceImpl;
import com.platform.utils.UUidGenerator;
import com.platform.vo.FdKanKanStasticVo;
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.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
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/7/15 15:42
 * @desciption
 */
@Service
@Slf4j
public class SceneCensusService extends TmSceneCensusServiceImpl {

    private static final String KANKAN_QUERY_PATH = "scene/statistics/findByTime";

    @Value("${4dkankan.host}")
    private String kankanHost;

    @Autowired
    private RestTemplate restTemplate;

    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
    public int addSceneCensus(TmSceneCensus tmSceneCensus){
        if(null == tmSceneCensus){
            return -1;
        }
        if(StringUtils.isBlank(tmSceneCensus.getSceneNum())){
            log.error("场景码为空，无法新增场景统计记录");
            return -1;
        }
        tmSceneCensus.setCensusId(UUidGenerator.generatorUuid(IdStarterEnum.DEFAULT_ID.getStarter()));
        tmSceneCensus.setCreateTime(LocalDateTime.now());
        tmSceneCensus.setLastModifyDatetime(LocalDateTime.now());
        tmSceneCensus.setEnable(1);
        return  getBaseMapper().insert(tmSceneCensus);
    }

    public TmSceneCensus getCensusBySceneNum(String sceneNum , LocalDate localDate){
        if(StringUtils.isBlank(sceneNum)){
            return null;
        }
        QueryWrapper<TmSceneCensus> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("scene_num" , sceneNum);
        queryWrapper.eq("census_date" , localDate);
        queryWrapper.eq("enable" , 1);
        queryWrapper.last("limit 1");
        return getBaseMapper().selectOne(queryWrapper);
    }
    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
    public int selectForUpdateThenUpdate(String sceneNum , LocalDate localDate , String companyId ,
                                         int sceneDotNum ,int goodsNum , int videoNum){
        if(null == localDate || StringUtils.isBlank(sceneNum)){
            return -1;
        }
        TmSceneCensus dbSceneCensus = getCensusBySceneNumForUpdate(sceneNum , LocalDate.now());
        if(null == dbSceneCensus){
            log.error("锁定场景[{}]-日期[{}]失败" , sceneNum , localDate.toString());
            throw new CommonBaseException(ResultCodeEnum.D101, "锁定场景统计记录失败");
        }
        boolean needUpdate = false;
        if (StringUtils.isBlank(dbSceneCensus.getCompanyId())) {
            dbSceneCensus.setCompanyId(companyId);
            needUpdate = true;
        }
        if (null == dbSceneCensus.getSceneHots() || dbSceneCensus.getSceneHots() != sceneDotNum) {
            needUpdate = true;
            dbSceneCensus.setSceneHots(sceneDotNum);
        }
        if (null == dbSceneCensus.getGoodsNum() || dbSceneCensus.getGoodsNum() != goodsNum) {
            needUpdate = true;
            dbSceneCensus.setGoodsNum(goodsNum);
        }

        if (null == dbSceneCensus.getVideoNums() || dbSceneCensus.getVideoNums() != videoNum) {
            needUpdate = true;
            dbSceneCensus.setVideoNums(videoNum);
        }
        int update = 1;
        if(needUpdate){
            log.info("需要更新场景统计值");
            update = updateCensus(dbSceneCensus);
            if(update != 1){
                throw new CommonBaseException(ResultCodeEnum.D101, "更新场景统计数据失败");
            }
        }
        return  update;
    }

    public TmSceneCensus getCensusBySceneNumForUpdate(String sceneNum , LocalDate localDate){
        if(StringUtils.isBlank(sceneNum)){
            return null;
        }
        QueryWrapper<TmSceneCensus> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("scene_num" , sceneNum);
        queryWrapper.eq("enable" , 1);
        queryWrapper.eq("census_date" , localDate);
        queryWrapper.last("limit 1  for update");
        return getBaseMapper().selectOne(queryWrapper);
    }
    @Transactional(rollbackFor = Exception.class)
    public int updateCensus(TmSceneCensus tmSceneCensus){
        if(null == tmSceneCensus){
            return -1;
        }
        if(StringUtils.isBlank(tmSceneCensus.getSceneNum()) && StringUtils.isBlank(tmSceneCensus.getCensusId())){
            log.error("场景码和统计ID全为空，无法更新场景统计记录");
            return -1;
        }
        UpdateWrapper<TmSceneCensus> updateWrapper = new UpdateWrapper<>();
        updateWrapper.last("limit 1");
        if(StringUtils.isNotBlank(tmSceneCensus.getSceneNum())){
            updateWrapper.eq("scene_num" , tmSceneCensus.getSceneNum());
        }
        if(StringUtils.isNotBlank(tmSceneCensus.getCensusId())){
            updateWrapper.eq("census_id" , tmSceneCensus.getCensusId());
        }
        return getBaseMapper().update(tmSceneCensus ,updateWrapper);
    }

    public List<TmSceneCensus> getRecentCensusList(int rangeLength , String sceneNum){
        QueryWrapper<TmSceneCensus> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("enable" , 1);
        queryWrapper.eq("scene_num" , sceneNum);
        queryWrapper.orderByDesc("census_date");
        if(rangeLength == 0){
            rangeLength = 30;
        }
        queryWrapper.between("census_date" , LocalDate.now().plusDays(0l - (long)rangeLength) , LocalDate.now());

        queryWrapper.last("limit " + rangeLength);
        return getBaseMapper().selectList(queryWrapper);
    }

    public Map<String , Object> getPvUvHistoryFromKankan(LocalDate start , LocalDate end , String sceneNum){
        Map<String , Object> result = new HashMap<>();
        if(null == start || null == end || StringUtils.isBlank(sceneNum)){
            log.info("入参缺失，无法去指房宝获取场景的pv统计数据");
            return result;
        }
        List<Map<String, Object>> scenePvList = new ArrayList<>();
        List<Map<String, Object>> sceneUvList = new ArrayList<>();
        DateTimeFormatter kankanDateFormat = DateTimeFormatter.ofPattern("yyyyMMdd");
        //先获取场景uv,pv
        Map<String, Object> sceneParams = new HashMap<>();
        sceneParams.put("startDate", kankanDateFormat.format(start));
        sceneParams.put("endDate", kankanDateFormat.format(end));
        sceneParams.put("sceneNum", sceneNum);
        //1:场景，2:热点，3:视频
        sceneParams.put("type", 1);
        String url = kankanHost + KANKAN_QUERY_PATH;
        JSONArray sceneDataArray = getDataFromKanKan(url, sceneParams);
        if (!CollectionUtils.isEmpty(sceneDataArray)) {
            List<FdKanKanStasticVo> sceneDataList = JSONArray.parseArray(sceneDataArray.toJSONString(),
                    FdKanKanStasticVo.class);
            if (!CollectionUtils.isEmpty(sceneDataList)) {
                for (FdKanKanStasticVo fdKanKanStasticVo : sceneDataList) {
                    Map<String, Object> tmpPvMap = new HashMap<>();
                    tmpPvMap.put(fdKanKanStasticVo.getDateStr(), fdKanKanStasticVo.getPvCount());
                    scenePvList.add(tmpPvMap);

                    Map<String, Object> tmpUvMap = new HashMap<>();
                    tmpUvMap.put(fdKanKanStasticVo.getDateStr(), fdKanKanStasticVo.getVisitorCount());
                    sceneUvList.add(tmpUvMap);

                }
            }
        }
        result.put("pv" , scenePvList);
        result.put("uv" , sceneUvList);
        return result;
    }

    public  List<Map<String, Object>> getHotHistoryFromKankan(LocalDate start , LocalDate end , String sceneNum) {
        List<Map<String, Object>> hotVisitList = new ArrayList<>();
        if (null == start || null == end || StringUtils.isBlank(sceneNum)) {
            log.info("入参缺失，无法去指房宝获取场景的pv统计数据");
            return hotVisitList;
        }
        String url = kankanHost + KANKAN_QUERY_PATH;
        DateTimeFormatter kankanDateFormat = DateTimeFormatter.ofPattern("yyyyMMdd");
         //再获取热点统计
        Map<String, Object> hotParams = new HashMap<>();
        hotParams.put("startDate", kankanDateFormat.format(start));
        hotParams.put("endDate", kankanDateFormat.format(end));
        hotParams.put("sceneNum", sceneNum);
        //1:场景，2:热点，3:视频
        hotParams.put("type", 2);
        JSONArray hotDataArray = getDataFromKanKan(url, hotParams);
        if (!CollectionUtils.isEmpty(hotDataArray)) {
            List<FdKanKanStasticVo> hotDataList = JSONArray.parseArray(hotDataArray.toJSONString(),
                    FdKanKanStasticVo.class);
            if (!CollectionUtils.isEmpty(hotDataList)) {
                for (FdKanKanStasticVo fdKanKanStasticVo : hotDataList) {
                    Map<String, Object> tmpHotMap = new HashMap<>();
                    tmpHotMap.put(fdKanKanStasticVo.getDateStr(), fdKanKanStasticVo.getPvCount());
                    hotVisitList.add(tmpHotMap);
                }
            }
        }
        return hotVisitList;
    }

    public JSONArray getDataFromKanKan(String url, Map<String, Object> params) {
        if (StringUtils.isBlank(url)) {
            throw new CommonBaseException(ResultCodeEnum.D101, "入参不全，无法获取四维场景列表");
        }
        ResponseEntity<String> kankanResult = restTemplate.postForEntity(url, params,String.class);
        //把信息封装为json
        JSONObject res = JSONObject.parseObject(kankanResult.getBody());
        JSONArray mySceneList = parseKanKanRsp(res);
        return mySceneList;
    }

    public JSONArray parseKanKanRsp(JSONObject result) {
        if (null == result) {
            throw new CommonBaseException(ResultCodeEnum.D101, "指房宝返回数据异常");
        }
        log.info("看看获取场景列表返回:{}", result.toJSONString());
        int code = -10;
        if (result.containsKey("code")) {
            code = (int) result.get("code");
            if (code != 200) {
                throw new CommonBaseException(ResultCodeEnum.D101, "调用指房宝失败");
            }
            JSONArray data = result.getJSONArray("message");
            if (null == data) {
                throw new CommonBaseException(ResultCodeEnum.D101, "指房宝返回数据异常-缺data");
            }
            log.debug("查询到指房宝的统计数据:{}", data.toJSONString());
            return data;
        } else {
            throw new CommonBaseException(ResultCodeEnum.D101, "调用指房宝失败");
        }
    }

}
