package cn.chnmuseum.party.service.impl;

import cn.chnmuseum.party.common.util.CurrencyMathUtil;
import cn.chnmuseum.party.common.util.DateUtil;
import cn.chnmuseum.party.common.util.RedisUtil;
import cn.chnmuseum.party.core.annotations.RedisLock;
import cn.chnmuseum.party.model.*;
import cn.chnmuseum.party.mapper.TBoardStatisticMapper;
import cn.chnmuseum.party.service.TAreaService;
import cn.chnmuseum.party.service.TBoardStatisticService;
import cn.chnmuseum.party.service.TUserService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <pre>
 * 展板统计信息表 服务实现类
 * </pre>
 *
 * @author Danny Lee
 * @since 2021-03-25
 */
@Slf4j
@Service
public class TBoardStatisticServiceImpl extends ServiceImpl<TBoardStatisticMapper, TBoardStatistic> implements TBoardStatisticService {

    @Resource
    private TBoardStatisticMapper boardStatisticMapper;

    @Autowired
    private TUserService userService;

    @Autowired
    private TAreaService areaService;

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private RedisTemplate<String, ? extends Object> redisTemplate;
    private static String STATISTIC_BOARD_INFO_KEY = "STATISTIC_BOARD_INFO_KEY"; // 展板统计信息key

    @Override
    @RedisLock(value = "boardLock", timeLock = 20, required = true, timeOut = 1100000)
    public Object boardStatisticInfo(TBoardStatistic tBoardStatistic, boolean autoUpdate) {
        if (tBoardStatistic != null) {
            // 根据用户id获取用户信息
            TUser user = userService.selectById(tBoardStatistic.getUserId());
            tBoardStatistic.setOrganId(user.getOrgId());    // 用户所属机构
            tBoardStatistic.setAreaId(Integer.parseInt(user.getAreaId()));// 用户所属地区
            if (StringUtils.isEmpty(tBoardStatistic.getPlayDate())) {
                // 获取当前日期
                tBoardStatistic.setPlayDate(DateUtil.getCurrentDate("yyyyMMdd"));
            }
            if (null == tBoardStatistic.getPlayNumber()) {
                // 获取当前日期
                tBoardStatistic.setPlayNumber(1);
            }

        }

        List<TBoardStatistic> statisticList = new ArrayList<>();
        String redisKey = STATISTIC_BOARD_INFO_KEY;
        // 获取统计信息缓存数据
        String businessJsonArray = (String) redisUtil.get(redisKey);
        // 缓存数据不为空,转换数据
        if (StringUtils.isNotEmpty(businessJsonArray)) {
            statisticList = JSONObject.parseArray(businessJsonArray, TBoardStatistic.class);
        }
        if (tBoardStatistic != null) {
            statisticList.add(tBoardStatistic);
        }
        redisUtil.set(redisKey, JSON.toJSON(statisticList).toString());
        // 统计记录数等于100 时,或者需要自动更新时 汇总统计数据
        if (statisticList.size() >= 100 || (autoUpdate && statisticList.size() > 0)) {
            // 更新展板统计信息
            updateBoardStatisticInfo(statisticList, redisKey);
        }
        return true;
    }


    @Override
    public Page<TBoardPlayRank> getBoardRankPageList(Page<TBoardPlayRank> page, TBoardPlayRank rank) {
        page.setRecords(boardStatisticMapper.getBoardRankPageList(page, rank));
        return page;
    }

    @Override
    public Page<TBoardPlayTrend> getBoardTrendPageList(Page<TBoardPlayTrend> page, TBoardPlayTrend trend) {

        page.setRecords(boardStatisticMapper.getBoardTrendPageList(page, trend));
        return page;
    }

//    @Override
//    public List<TBoardPlayTrend> getBoardTrendPageList(Page<TBoardPlayTrend> page, TBoardPlayTrend trend) {
//
//        List<TBoardPlayTrend> boardTrendPageList = boardStatisticMapper.getBoardTrendPageList(trend);
//        return boardTrendPageList;
//    }

    @Override
    public Page<TDistrictBoardStatistic> getBoardDistrictPageList(Page<TDistrictBoardStatistic> page, TDistrictBoardStatistic district) {
        List<TDistrictBoardStatistic> list = boardStatisticMapper.getBoardDistrictPageList(page, district);
        page.setRecords(list);
        return page;
    }

    @Override
    public TBoardSurvey getBoardSurvey(TBoardSurvey survey) {
        // 获取展板播放量
        survey.setPlayCnt(boardStatisticMapper.getBoardPlayTotal(survey));
        // 获取展板总数
        survey.setBoardCnt(boardStatisticMapper.getBoardTotal(survey));
        // 获取播放展板的机构总数
        survey.setOrgCnt(boardStatisticMapper.getOrganTotal(survey));
        // 获取互动总数
        survey.setInteractionCnt(boardStatisticMapper.getInteractionTotal(survey));
        return survey;
    }

    @Override
    public Page getInteractionFrequency(Page page, String frequencyDate, String orgCode) {
        page.setRecords(boardStatisticMapper.getInteractionFrequency(page, frequencyDate, orgCode));
        return page;
    }


    @Override
    public Page getInteractionFrequency(Page page, String frequencyDate, String orgCode, List<String> areaIds) {
        page.setRecords(boardStatisticMapper.getInteractionFrequency1(page, frequencyDate, orgCode,areaIds));
        return page;
    }

    @Override
    public List getBoardProvincePlayTotalList(String organId, String orgCode) {
        // 获取省份信息
        QueryWrapper qw = new QueryWrapper();
        qw.eq("type", "P");
        List<TArea> provlist = areaService.list(qw);
        provlist.stream().forEach(l -> l.setName(l.getName().replace("省", "").replace("市", "").
                replace("自治区", "").replace("特别行政区", "").replace("壮族", "").replace("回族", "").replace("维吾尔", "")));
        // 遍历省份,统计各省播放量
        TBoardSurvey survey = new TBoardSurvey();
        String dateStr = DateUtil.getCurrentDate("yyyyMM");
        survey.setStatisticDate(dateStr);
        survey.setOrganId(organId);
        survey.setOrganCode(orgCode);
        List list = new ArrayList();
        // 根据省份查询播放量
        for (TArea prov : provlist) {
            Map map = new HashMap();
            survey.setAreaId(prov.getId().toString().substring(0, 2));
            Integer cnt = boardStatisticMapper.getBoardPlayTotal(survey);
            map.put("name", prov.getName());
            map.put("value", cnt == null ? 0 : cnt);
            list.add(map);
        }
        return list;
    }

    @Override
    public List getBoardCityPlayTotalList(String areaCode, String orgCode) {
        if (areaCode.equals("110000")||areaCode.equals("120000")||areaCode.equals("310000")||areaCode.equals("500000")){
            areaCode=areaCode.substring(0,2)+"0100";
        }
        QueryWrapper qw = new QueryWrapper();
        if (areaCode.endsWith("00")) {
            qw.eq("parent_id", areaCode);
        }else {
            qw.eq("code", areaCode);
        }

        List<TArea> provlist = areaService.list(qw);
        TBoardSurvey survey = new TBoardSurvey();
        String dateStr = DateUtil.getCurrentDate("yyyyMM");
        survey.setStatisticDate(dateStr);
        survey.setOrganCode(orgCode);
        List list = new ArrayList();
        // 根据省份查询播放量
        for (TArea prov : provlist) {
            Map map = new HashMap();
            if (areaCode.endsWith("0000")) {
                survey.setAreaId(prov.getId().toString().substring(0, 4));
            }else {
                survey.setAreaId(prov.getId().toString());
            }
            Integer cnt = boardStatisticMapper.getBoardPlayTotal(survey);
            map.put("name", prov.getName());
            map.put("value", cnt == null ? 0 : cnt);
            list.add(map);
        }
        return list;
    }


    @Override
    public Page<TBoardPlayTrend> getBoardPageList(Page<TBoardPlayTrend> page, TBoardPlayTrend trend) {
        HashMap<String, Integer> map = new HashMap<>();
        List<TBoardPlayTrend> board = boardStatisticMapper.getBoardPageList(page, trend);
        for (TBoardPlayTrend tBoardPlayTrend : board) {
            map.put(tBoardPlayTrend.getPlayDate(),tBoardPlayTrend.getPlayNumber());
        }
        SimpleDateFormat sim = new SimpleDateFormat("yyyyMM");
        Date begin = null;
        Date end = null;
        try {
            begin = sim.parse(trend.getBeginDate());
            end = sim.parse(trend.getEndDate());
        } catch (ParseException e) {
            e.printStackTrace();
        }

        long l = (end.getTime() - begin.getTime()) / 1000 / 3600 / 24 / 30;

        ArrayList<TBoardPlayTrend> list = new ArrayList<>();
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(begin);
        for (int i = 0; i <= l; i++) {
            TBoardPlayTrend tBoardPlayTrend = new TBoardPlayTrend();
            String date = sim.format(rightNow.getTime());
            tBoardPlayTrend.setPlayDate(date);
            if (map.get(date)!=null){
                tBoardPlayTrend.setPlayNumber(map.get(date));
            }else {
                tBoardPlayTrend.setPlayNumber(0);
            }
            list.add(tBoardPlayTrend);
            rightNow.add(Calendar.MONTH, 1);
        }
        page.setRecords(list);
        return page;
    }

    /**
     * 更新展板统计信息
     */
    @Override
    public void updateBoardStatisticInfo(List<TBoardStatistic> statisticList, String redisKey) {
        Map<String, TBoardStatistic> map = new HashMap<>();
        statisticList.stream().forEach(s -> {
            String key = s.getBoardId() + "_" + s.getOrganId() + "_" + s.getPlayDate();
            // 如果有对应的展板记录,累计播放量
            if (map.containsKey(key)) {
                TBoardStatistic boardStatistic = map.get(key);
                boardStatistic.setPlayNumber(Integer.parseInt(CurrencyMathUtil.add(boardStatistic.getPlayNumber(), s.getPlayNumber())));
                map.put(key, boardStatistic);
            } else {
                // 如果无对应的展板记录,插入到map中
                map.put(key, s);
            }
        });
        // 更新数据库展板统计信息
        for (String key : map.keySet()) {
            TBoardStatistic bs = map.get(key);
            // 查询数据库是否有对应的记录
            QueryWrapper<TBoardStatistic> qw = new QueryWrapper<>();
            qw.eq("board_id", bs.getBoardId());
            qw.eq("organ_id", bs.getOrganId());
            qw.eq("play_date", bs.getPlayDate());
            TBoardStatistic tbDB = this.getOne(qw,false);
            // 如果数据库存在统计记录,则累计统计数量
            if (tbDB != null) {
                tbDB.setPlayNumber(Integer.parseInt(CurrencyMathUtil.add(bs.getPlayNumber(), tbDB.getPlayNumber())));
                this.updateById(tbDB);
                map.put(key, tbDB);
            } else {
                // 如果数据库不存在统计记录,则增加统计数据
                this.save(bs);
            }
        }

        // 清空redis
        redisUtil.del(redisKey);
    }

}