package com.ho.business.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.ho.business.constant.DeviceTypeConstant;
import com.ho.business.entity.*;
import com.ho.business.feignclient.UserFeignClient;
import com.ho.business.mapper.PlanningCurveIssueMapper;
import com.ho.business.mapper.PlanningCurveMapper;
import com.ho.business.service.DynamicConfigService;
import com.ho.business.service.PlanningCurveIssueService;
import com.ho.business.vo.DeviceTransfer;
import com.ho.business.vo.resp.planningCurve.PlanningIssueQueryVo;
import com.ho.business.vo.resp.planningCurve.PlanningIssueVo;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.constant.DefineConstant;
import com.ho.common.tools.exception.DataResult;
import com.ho.common.tools.service.RedisService;
import com.ho.datacollect.api.constant.DataCollectConstant;
import com.ho.user.api.entity.SysUser;
import com.ho.user.api.vo.req.QueryUserReqVO;
import jodd.util.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class PlanningCurveIssueServiceImpl implements PlanningCurveIssueService {

    @Autowired
    private PlanningCurveIssueMapper issueMapper;

    @Autowired
    private RedisService redisService;

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private PlanningCurveMapper planningMapper;

    @Autowired
    private DynamicConfigService dynamicConfigService;

    @Override
    public List<Map<String, Object>> getIssueDevices(PlanningIssueDevice issueDevice) {
        return issueMapper.getIssueDevices(issueDevice);
    }

    @Override
    public List<Map<String, Object>> getTemplate(PlanningIssueDevice issueDevice) {
        return issueMapper.getTemplate(issueDevice);
    }

    @Override
    public List<Map<String, Object>> getIssueDatas(PlanningIssueVo vo) {
        List<Map<String, Object>> result = null;
        try {
            Device device = issueMapper.getDeviceById(vo);
            if( null != vo && null != device ){
                vo.setDeviceType(device.getDeviceType());
            } else {
                return new ArrayList<>(0);
            }
            PlanningIssueDevice issueDevice = new PlanningIssueDevice();
            issueDevice.setPlanTemId(vo.getTemId());
            List<PlanningIssueComm> issueComms = issueMapper.getIssueComms(vo);
            //List<PlanningCurve> curveDetail = issueMapper.getCurveDetail(vo.getTemId());
            PlanningCurveTemplate planningCurveTemplate = this.queryCurrentIssue(issueDevice);
            List<PlanningCurve> curveDetail = new ArrayList<>(0);
            if( null != planningCurveTemplate ){
                curveDetail = planningCurveTemplate.getPlanningCurves();
            }
            result = this.processDatas(device, issueComms, curveDetail, vo);
            if ( result != null && result.size() > 0 ) {
                result.addAll(this.processTemData(device, issueComms, planningCurveTemplate, vo));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    private List<Map<String, Object>> processDatas(Device device, List<PlanningIssueComm> issueComms, List<PlanningCurve> curveDetail, PlanningIssueVo vo) {
        List<Map<String, Object>> result = new ArrayList<>(0);
        Map<String, Object> map = null;
        if (curveDetail.size() <= 0) {
            return null;
        }
        if (issueComms.size() <= 0) {
            return null;
        }
        String modelCol = null;
//        int i = 1;
        for (int i = 1; i <= 16; i++) {
            PlanningCurve planningCurve = new PlanningCurve();
            if ( (i-1) < curveDetail.size() && curveDetail.get(i-1) != null ) {
                planningCurve = curveDetail.get(i-1);
            }
//        for (PlanningCurve planningCurve : curveDetail) {
            for (int j = 0; j < 5; j++) {
                String redisKey = device.getDeviceType() + ":" + vo.getStationId() + ":" + device.getSrcId();
                map = new HashMap<>(0);
                switch (j) {
                    case 0:
                        modelCol = "planSoc" + i;
//                        if (null != planningCurve.getSoc()) {
                        map.put("modifyValue", planningCurve.getSoc() == null ? 0 : planningCurve.getSoc());
//                        } else {
//                            continue;
//                        }
                        break;
                    case 1:
                        modelCol = "planQ" + i;
//                        if (null != planningCurve.getQ()) {
                        map.put("modifyValue", planningCurve.getQ() == null ? 0 : planningCurve.getQ());
//                        } else {
//                            continue;
//                        }
                        break;
                    case 2:
                        modelCol = "planP" + i;
//                        if (null != planningCurve.getP()) {
                        map.put("modifyValue", planningCurve.getP() == null ? 0 : planningCurve.getP());
//                        } else {
//                            continue;
//                        }
                        break;
                    case 3:
                        modelCol = "planM" + i;
//                        if (null != planningCurve.getStartTime()) {
                            map.put("modifyValue", planningCurve.getStartTime() == null ? 0 : planningCurve.getStartTime().substring(3, 5));
//                        } else {
//                            continue;
//                        }
                        break;
                    case 4:
                        modelCol = "planH" + i;
//                        if (null != planningCurve.getStartTime()) {
                        map.put("modifyValue", planningCurve.getStartTime() == null ? 0 : planningCurve.getStartTime().substring(0, 2));
//                        } else {
//                            continue;
//                        }
                        break;
                    default:
                        break;
                }
                map.put("srcId", device.getSrcId());
                map.put("deviceName", device.getDeviceName());
                map.put("deviceType", device.getDeviceType());
                map.put("sn", device.getSerialNo());
                map.put("stationId", vo.getStationId());
                map.put("sensType", "2");
                Map<String, Object> matchModel = this.matchModel(issueComms, modelCol, redisKey);
                if ( null != matchModel && matchModel.size() > 0) {
                    map.putAll(matchModel);
                    result.add(map);
                }
            }
//            i++;
        }
        return result;
    }

    private List<Map<String,Object>> processTemData(Device device, List<PlanningIssueComm> issueComms, PlanningCurveTemplate template, PlanningIssueVo vo){
        List<Map<String,Object>> result = new ArrayList<Map<String,Object>>(0);
        Map<String,Object> map = null;
        String redisKey = device.getDeviceType() + ":" + vo.getStationId() + ":" + device.getSrcId();
        if (issueComms.size() <= 0) {
            return null;
        }
        Integer socUpper = template.getSocUpper();
        Integer socLower = template.getSocLower();
        String modelCol = null;
        if( socUpper != null ){
            map = new HashMap<>(0);
            modelCol = "planSocUpper";
            map.put("srcId", device.getSrcId());
            map.put("deviceName", device.getDeviceName());
            map.put("deviceType", device.getDeviceType());
            map.put("sn", device.getSerialNo());
            map.put("stationId", vo.getStationId());
            map.put("sensType", "2");
            map.put("modifyValue", socUpper);
            Map<String, Object> matchModel = this.matchModel(issueComms, modelCol, redisKey);
            if ( null != matchModel && matchModel.size() > 0) {
                map.putAll(matchModel);
                result.add(map);
            }
        }

        if( socLower != null ){
            map = new HashMap<>(0);
            modelCol = "planSocLower";
            map.put("srcId", device.getSrcId());
            map.put("deviceName", device.getDeviceName());
            map.put("deviceType", device.getDeviceType());
            map.put("sn", device.getSerialNo());
            map.put("stationId", vo.getStationId());
            map.put("sensType", "2");
            map.put("modifyValue", socLower);
            Map<String, Object> matchModel = this.matchModel(issueComms, modelCol, redisKey);
            if ( null != matchModel && matchModel.size() > 0) {
                map.putAll(matchModel);
                result.add(map);
            }
        }
        return result;
    }

    private Map<String, Object> matchModel(List<PlanningIssueComm> issueComms, String modelCol, String redisKey) {
        Map<String, Object> map = new HashMap<String, Object>(0);
        for (PlanningIssueComm issueComm : issueComms) {
            if (issueComm.getModelCol().equals(modelCol)) {
                map.put("colName", issueComm.getColName());
                map.put("col", issueComm.getTypeCol());
                map.put("maxValue", issueComm.getMaxValue());
                map.put("minValue", issueComm.getMinValue());
                Map<Object, Object> dataMap = new HashMap<>();
                Date date = new Date();
                if (redisService.hasKey(redisKey)) {
                    dataMap = redisService.hgetall(redisKey);
                    //去除ts createTime updateTime 3 个字段
                    date = (Date) dataMap.get(DataCollectConstant.UPDATE_TIME);
                    if (dataMap.containsKey(DataCollectConstant.TS)) {
                        dataMap.remove(DataCollectConstant.TS);
                    }
                    if (dataMap.containsKey(DataCollectConstant.CREATE_TIME)) {
                        dataMap.remove(DataCollectConstant.CREATE_TIME);
                    }
                    if (dataMap.containsKey(DataCollectConstant.UPDATE_TIME)) {
                        dataMap.remove(DataCollectConstant.UPDATE_TIME);
                    }
                }
                DeviceTransfer deviceTransfer = null;
                Object obj = dataMap.get(issueComm.getTypeCol());
                if (null != obj) {
                    deviceTransfer = (DeviceTransfer) obj;
                }
                BigDecimal round = null;
                String updateTime = DateUtil.format(date, CommonConstant.DATE);
                if (null == deviceTransfer) {
                    round = NumberUtil.round(new BigDecimal(CommonConstant.ZERO), 2);
                } else {
                    round = NumberUtil.round(deviceTransfer.getValue(), 2);
                }
                map.put("value", round);
                map.put("updateTime", updateTime);
                map.put("deviceTypeColId", issueComm.getTypeId());
                break;
            }
        }
        return map;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String, Object> insertIssueStatus(PlanningIssueDevice issueDevice) {
        Map<String, Object> result = new HashMap<String, Object>(0);
        if (null != issueDevice) {
            issueMapper.deleteIssueStatus(issueDevice);
            int i = issueMapper.insertIssueStatus(issueDevice);
            result.put("code", i > 0 ? "200" : "400");
            result.put("msg", i > 0 ? DefineConstant.PlanningCurveIssue.SEND_SUCCESS : DefineConstant.PlanningCurveIssue.SEND_FAIL);
        } else {
            result.put("code", "400");
            result.put("msg", DefineConstant.PlanningCurveIssue.SEND_FAIL);
        }
        return result;
    }

    @Override
    public PlanningIssueDevice queryIssueStatus(PlanningIssueDevice issueDevice) {
        PlanningIssueDevice planningIssueDevice = issueMapper.queryIssueStatus(issueDevice);
        if( planningIssueDevice != null && planningIssueDevice.getPlanTemId() != null ){
            Integer planTemId = planningIssueDevice.getPlanTemId();
            int i = issueMapper.chechTemplateExists(planTemId);
            if( i <= 0 ){
                planningIssueDevice.setPlanTemId(null);
            }
        }
        return planningIssueDevice;
    }


    @Override
    public PlanningCurveTemplate queryCurrentIssue(PlanningIssueDevice issueDevice) {
        return issueMapper.queryCurrentIssue(issueDevice);
    }

    @Override
    public List<Map<String, Object>> getPlanCurveIssueData(PlanningIssueQueryVo vo) {
        List<Map<String, Object>> result = new ArrayList<>();
        try {
            Device device = issueMapper.getDeviceById(vo);
            if( null != vo && null != device ){
                vo.setDeviceType(device.getDeviceType());
            } else {
                return new ArrayList<>(0);
            }
            PlanningIssueDevice issueDevice = new PlanningIssueDevice();
            issueDevice.setPlanTemId(vo.getTemId());
            List<PlanningIssueComm> issueComms = issueMapper.getIssueComms(vo);
            if(null != issueComms && issueComms.size()>0){
                for (PlanningIssueComm plan:issueComms) {
                    if(DeviceTypeConstant.PLAN_CURVE.PLAN_CONTROL_MODEL.equals(plan.getModelCol())){
                        getData(vo, result, device, plan,vo.getPlanControlModel(),plan.getTypeCol());
                    }else if(DeviceTypeConstant.PLAN_CURVE.PLAN_REFRESHH.equals(plan.getModelCol())){
                        getData(vo, result, device, plan,vo.getPlanRefreshH(),plan.getTypeCol());
                    }else if(DeviceTypeConstant.PLAN_CURVE.PLAN_REFRESHM.equals(plan.getModelCol())){
                        getData(vo, result, device, plan,vo.getPlanRefreshM(),plan.getTypeCol());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    @Transactional
    public void planCurveOperationRecord(PlanCurveOperationRecordReq planCurveOperationRecordReq) {
        //补充操作用户名称
        if(planCurveOperationRecordReq.getUserId()!=null){
            List<QueryUserReqVO> queryUserReqVO = new ArrayList<>();
            QueryUserReqVO uerId = new QueryUserReqVO();
            uerId.setUserId(planCurveOperationRecordReq.getUserId());
            queryUserReqVO.add(uerId);
            DataResult<List<SysUser>> userInfo = userFeignClient.queryUser(queryUserReqVO);
            if(userInfo.getData()!=null && !userInfo.getData().isEmpty()){
                planCurveOperationRecordReq.setUserName(userInfo.getData().get(0).getUsername());
            }
        }
        //补充操作内容
        //获取当前模板名称等信息
        PlanningCurveTemplate template = new PlanningCurveTemplate();
        template.setTemId(Integer.parseInt(planCurveOperationRecordReq.getLatestPlanningCurve()));
        List<PlanningCurveTemplate> planningCurveTemplates = planningMapper.getPlanningCurveTemplate(template);
        String templateName = planningCurveTemplates.get(0).getTemplateName();
        planCurveOperationRecordReq.setOperateContent(DefineConstant.PlanningCurveIssue.PLAN_CURVE+"-"+templateName);
        //将本次下发的计划曲线存入历史表
        String lastestOperateId = String.valueOf(UUID.randomUUID());

        List<PlanningCurveHistory> lastestPlanningCurve = planningCurveTemplates.get(0).getPlanningCurves().stream().map(s -> {
            PlanningCurveHistory planningCurveHistory = new PlanningCurveHistory();
            BeanUtils.copyProperties(s,planningCurveHistory);
            planningCurveHistory.setOperateNo(lastestOperateId);
            planningCurveHistory.setTempNo(s.getPlanningTemplateId());
            planningCurveHistory.setId(null);
            planningCurveHistory.setSocUpper(planningCurveTemplates.get(0).getSocUpper());
            planningCurveHistory.setSocLower(planningCurveTemplates.get(0).getSocLower());
            planningCurveHistory.setEffectiveTime(planCurveOperationRecordReq.getEffectiveTime());
            return planningCurveHistory;
        }).collect(Collectors.toList());
        issueMapper.addPlanningCurveHistory(lastestPlanningCurve);
        planCurveOperationRecordReq.setLatestPlanningCurve(lastestOperateId);
        //获取电站的上一次计划曲线模板id
        String previousOperateId = null;
        List<PlanCurveOperationRecordReq> result = issueMapper.getPlanCurveOperationList(String.valueOf(planCurveOperationRecordReq.getStationId()),null);
        //取成功下发的操作记录
        result = result.stream().filter(e ->1==e.getStatus()).collect(Collectors.toList());
        if(result.size()>0){
            previousOperateId = result.get(0).getLatestPlanningCurve();
        }
        planCurveOperationRecordReq.setPreviousPlanningCurve(previousOperateId);
        // 英文字段处理
        if(StringUtil.isNotBlank(planCurveOperationRecordReq.getOperateContent())){
            TranslateName opTrans = dynamicConfigService.getNameLanguage(planCurveOperationRecordReq.getOperateContent());
            planCurveOperationRecordReq.setOperateContentEn(opTrans.getNameEn());
            planCurveOperationRecordReq.setOperateContentFra(opTrans.getNameFra());
            planCurveOperationRecordReq.setOperateContentSpa(opTrans.getNameSpa());
            planCurveOperationRecordReq.setOperateContentDe(opTrans.getNameDe());
            planCurveOperationRecordReq.setOperateContentPl(opTrans.getNamePl());
            planCurveOperationRecordReq.setOperateContentAra(opTrans.getNameAra());
        }
        if(StringUtil.isNotBlank(planCurveOperationRecordReq.getOperateResult())){
            TranslateName reTrans = dynamicConfigService.getNameLanguage(planCurveOperationRecordReq.getOperateResult());
            planCurveOperationRecordReq.setOperateResultEn(reTrans.getNameEn());
            planCurveOperationRecordReq.setOperateResultFra(reTrans.getNameFra());
            planCurveOperationRecordReq.setOperateResultSpa(reTrans.getNameSpa());
            planCurveOperationRecordReq.setOperateResultDe(reTrans.getNameDe());
            planCurveOperationRecordReq.setOperateResultPl(reTrans.getNamePl());
            planCurveOperationRecordReq.setOperateResultAra(reTrans.getNameAra());
        }
        //插入操作记录
        issueMapper.planCurveOperationRecord(planCurveOperationRecordReq);
    }

    @Override
    public List<PlanCurveOperationRecordReq> getPlanCurveOperationList(String stationId,String lang) {
        List<PlanCurveOperationRecordReq> result = issueMapper.getPlanCurveOperationList(stationId,lang);
        return result;
    }

    @Override
    public Map<String, Object> getPlanningCurveHistory(List<String> planningCurveIds) {
        Map<String, Object> result = new HashMap<>();
        for(String planningCurveId : planningCurveIds){
            if(planningCurveId != null){
                List<PlanningCurveHistory> planningCurveHistory = new ArrayList<>();
                planningCurveHistory = issueMapper.getPlanningCurveHistory(planningCurveId);
                result.put(planningCurveId,planningCurveHistory);
            }
        }
        return result;
    }

    private void getData(PlanningIssueQueryVo vo, List<Map<String, Object>> result, Device device, PlanningIssueComm plan,Integer value,String col) {
        Map<String, Object> map = new HashMap<>();
        map.put("srcId", device.getSrcId());
        map.put("deviceName", device.getDeviceName());
        map.put("deviceType", device.getDeviceType());
        map.put("sn", device.getSerialNo());
        map.put("stationId", vo.getStationId());
        map.put("sensType", "2");
        map.put("maxValue", plan.getMaxValue());
        map.put("minValue", plan.getMinValue());
        map.put("value", value);
        map.put("modifyValue", value);
        map.put("col", col);
        result.add(map);
    }
}
