package com.sunwin.robot2ips.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.sunwin.robot2ips.beans.dto.CheckDataDTO;
import com.sunwin.robot2ips.beans.dto.IPSPointDTO;
import com.sunwin.robot2ips.beans.dto.RobotDTO;
import com.sunwin.robot2ips.beans.vo.IPSResp;
import com.sunwin.robot2ips.beans.vo.RecordData;
import com.sunwin.robot2ips.beans.vo.RecordTaskPoint;
import com.sunwin.robot2ips.common.RedisKey;
import com.sunwin.robot2ips.dao.UploadMapper;
import com.sunwin.robot2ips.service.CheckDataService;
import com.sunwin.robot2ips.util.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class CheckDataServiceImpl implements CheckDataService {
    private static final Logger logger = LoggerFactory.getLogger(CheckDataServiceImpl.class);

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    UploadMapper uploadMapper;

    @Value("${ips.connect.url}")
    private String url;

    @Value("${ips.point.fileName}")
    private String fileName;
    @Value("${ips.query.count}")
    private Integer count;

    /**
     * 查询巡检数据并上传至IPS系统
     *
     * @param
     * @return void
     * @author machao
     * @date 2022/6/6 17:06
     **/
    @Override
    public void uploadCheckData() {
        //获取机器人信息
        List<RobotDTO> robots = uploadMapper.selectRobots();
        if (CollectionUtils.isEmpty(robots)) {
            logger.info("threadName={} robot list is null skip this sync", Thread.currentThread().getName());
            return;
        }
        Map<Integer, List<RobotDTO>> robotMap = robots.stream().collect(Collectors.groupingBy(RobotDTO::getId));
        //从redis中获取最新一次上传id
        Long lastDataId = (Long) redisUtils.get(RedisKey.UPLOAD_IPS_LAST_ID);
        //若为首次上传则记录当前巡检数据的最大id 产生新的数据之后再进行上传
        if (lastDataId == null) {
            lastDataId = uploadMapper.selectMaxId();
            redisUtils.set(RedisKey.UPLOAD_IPS_LAST_ID, lastDataId);
            return;
        }
        //根据lastDataId查询基于上次上传后巡检数据
        List<RecordTaskPoint> checkDataList = uploadMapper.queryDataAfterId(lastDataId, count);
        if (!CollectionUtils.isEmpty(checkDataList)) {
            checkDataList = checkDataList.stream().filter(t -> t.getTaskId() != null).collect(Collectors.toList());
        }
        if (CollectionUtils.isEmpty(checkDataList)) {
            return;
        }
        //记录查询的最大id
        Long maxId = Long.valueOf(checkDataList.get(checkDataList.size() - 1).getResultId());
        //组装数据同步请求对象
        List<RecordData> uploadResult = getRecordData(robotMap, checkDataList);
        //若任务执行后 改变机器人信息 会导致无同步数据
        if (CollectionUtils.isEmpty(uploadResult)) {
            return;
        }
        //上传成功计数器
        int successCount = 0;
        //根据机器人拆分组装后遍历上传
        for (RecordData recordData : uploadResult) {
            //HttpPost
            String resp = HttpUtils.HttpPostWithJson(url, JSONObject.toJSONString(recordData));
            //上传成功
            if (!StringUtils.isEmpty(resp)) {
                IPSResp ipsResp = JSONObject.parseObject(resp, IPSResp.class);
                if (ipsResp.getIsSuccessed().equals("1")) {
                    successCount++;
                }
            }
        }
        //未全部成功则判定全部失败 下次重新上传
        if (uploadResult.size() != successCount) {
            logger.info("some data upload fail");
            redisUtils.set(RedisKey.UPLOAD_IPS_LAST_ID, lastDataId);
        } else {
            logger.info("data upload success");
            //全部成功则更新redis上传的最新id
            redisUtils.set(RedisKey.UPLOAD_IPS_LAST_ID, maxId);
        }
    }

    /**
     * 封装请求对象
     *
     * @param robotMap
     * @param checkDataList
     * @return java.util.List<com.sunwin.robot2ips.beans.vo.RecordData>
     * @author machao
     * @date 2022/6/16 15:25
     **/
    private List<RecordData> getRecordData(Map<Integer, List<RobotDTO>> robotMap, List<RecordTaskPoint> checkDataList) {
        //将巡检数据按照taskId分组
        Map<String, List<RecordTaskPoint>> robotCheckData = checkDataList.stream().collect(Collectors.groupingBy(RecordTaskPoint::getTaskId));
        //初始化上传集合
        List<RecordData> uploadResult = new ArrayList<>();
        //根据任务拆分巡检数据
        for (String taskId : robotCheckData.keySet()) {
            //获取taskId对应的巡检数据进行组装
            List<RecordTaskPoint> checkDataArray = robotCheckData.get(taskId);
            //获取任务执行机器人id
            Integer robotId = checkDataArray.get(0).getRobotId();
            List<RobotDTO> robot = robotMap.get(robotId);
            if (CollectionUtils.isEmpty(robot)) {
                continue;
            }
            RobotDTO robotDTO = robot.get(0);
            //初始化数据同步请求对象
            RecordData recordData = new RecordData();
            recordData.setRobotCode(robotDTO.getId().toString());
            recordData.setRobotName(robotDTO.getRobotName());
            recordData.setTaskId(taskId);
            //初始化实例集合
            List<RecordTaskPoint> recordTaskPoints = new ArrayList<>();
            //遍历设置时间
            for (RecordTaskPoint recordTaskPoint : checkDataArray) {
                //巡检照片转base64
                String base64 = FtpUtils.addrToBase64(recordTaskPoint.getImage());
                recordTaskPoint.setImage(base64);
                //取巡检数据的巡检时间的年月日作为任务日期
                String yyyyMMdd = DateUtil.parseToString(recordTaskPoint.getUpdateTime(), DateUtil.DateFormat_yyyy_MM_dd);
                Date start = DateUtil.strToDate(yyyyMMdd + " 00:00:00");
                Date end = DateUtil.strToDate(yyyyMMdd + " 23:59:59");
                //任务时间写死识别日期的00：00-23：59
                //recordTaskPoint.setRecordPlanStartDate(start);
                //recordTaskPoint.setRecordCompleteDate(end);
                recordTaskPoint.setRecordPlanCompleteDate(end);
                //recordTaskPoint.setRecordStartDate(start);
                recordTaskPoints.add(recordTaskPoint);
            }
            recordData.setRecordTaskPoints(recordTaskPoints);
            uploadResult.add(recordData);
        }
        return uploadResult;
    }


    /**
     * 绑定IPS与机器人巡检点关系
     *
     * @param
     * @return void
     * @author machao
     * @date 2022/6/8 9:13
     **/
    @Override
    public void bindIPSAndRobotPoint() {
        String absolutePath = new File("").getAbsolutePath() + "\\" + fileName;
        File file = new File(absolutePath);
        InputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(file);
            List<IPSPointDTO> importList = (List<IPSPointDTO>) ExcelUtil.read(fileInputStream, IPSPointDTO.class, file.getName());
            if (CollectionUtils.isEmpty(importList)) {
                return;
            }
            Iterator<IPSPointDTO> iterator = importList.iterator();
            while (iterator.hasNext()) {
                IPSPointDTO next = iterator.next();
                if (next.getPointId() == null) {
                    iterator.remove();
                }
            }
            //入库
            uploadMapper.insertBindLink(importList);
        } catch (Exception e) {
            logger.error("bind link error msg={}", e.getMessage());
        }
    }

}
