package com.sw.mes.eam.service.impl;

import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.UuidUtils;
import com.sw.mes.base.factory.init.entity.Equipment;
import com.sw.mes.base.factory.init.service.EquipmentService;
import com.sw.mes.base.system.entity.DictionaryItem;
import com.sw.mes.base.system.service.DictionaryItemService;
import com.sw.mes.base.system.service.SysLogService;
import com.sw.mes.core.annotation.Jinko;
import com.sw.mes.core.annotation.ServiceLogs;
import com.sw.mes.core.exception.BusinessException;
import com.sw.mes.core.utils.DateUtil;
import com.sw.mes.core.utils.NumberUtil;
import com.sw.mes.eam.dto.EamDeviceResponseDto;
import com.sw.mes.eam.entity.SyncEquipmentInDto;
import com.sw.mes.eam.service.MesToEamService;
import com.sw.mes.outside.dto.ToMESData;
import com.sw.mes.outside.entity.AlarmConfig;
import com.sw.mes.outside.entity.AlarmData;
import com.sw.mes.outside.service.AlarmConfigService;
import com.sw.mes.outside.util.EAPUtils;
import com.sw.mes.redis.server.RedisUtils;
import com.sw.mes.sap.dto.jip.JipISBCINFO;
import com.sw.mes.third.entity.RequestLog;
import com.sw.mes.third.service.RequestLogService;
import com.sw.mes.utils.StringUtils;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.persistence.Column;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: xushu
 * @Date: 2024/02/24/15:16
 * @Description:
 */
@Service
@Jinko(value="晶科MES拉取至eam操作业务逻辑Service",author = "xushu")
@Slf4j
public class MesToEamServiceImpl implements MesToEamService {

    private static final RestTemplate restTemplate = new RestTemplate();

    @Autowired
    private DictionaryItemService dictionaryItemService;

    @Autowired
    private RequestLogService requestLogService;

    @Autowired
    private SysLogService sysLogService;

    @Autowired
    private EquipmentService equipmentService;

    @Autowired
    private AlarmConfigService alarmConfigService;

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 设备运行状态
     */
    private static final String deviceStatusKey = "device_status_key_";

    @Override
    @XxlJob("syncEquipment")
    public ReturnT<String> syncEquipment() {
        List<DictionaryItem> list = dictionaryItemService.findByThemeValueAndItemName("eam_url","syncEquipment",true);
        if (list == null || list.size() == 0) {
//            throw new BusinessException("eam请求地址数据字典未配置！");
            ReturnT.FAIL.setMsg("eam请求地址数据字典未配置！");
            return ReturnT.FAIL;
        }
        DictionaryItem dictionaryItem = list.get(0);
        // 地址
        String url = dictionaryItem.getValue();
        // 所属基地
        String extendValue = dictionaryItem.getExtendValue();
        // 页数
        String extendValue1 = dictionaryItem.getExtendValue1();
        if(StringUtils.isEmpty(extendValue)){
            ReturnT.FAIL.setMsg("eam所属基地数据字典未配置！");
            return ReturnT.FAIL;
        }
        // 设备类型
        String extendValue2 = dictionaryItem.getExtendValue2();
        List<String> deviceNameList = new ArrayList<>();
        if(StringUtils.isEmpty(extendValue2)){
            ReturnT.FAIL.setMsg("eam所属基地数据字典未配置！");
            return ReturnT.FAIL;
        }
        String[] split = extendValue2.split(",");
        deviceNameList = Arrays.asList(split);
        Integer i = 1;
        List<Equipment> equipmentList = equipmentService.getListByDeviceNameIn(deviceNameList);
//        Map<String, String> map = equipmentList.stream().collect(Collectors.toMap(Equipment::getName,Equipment::getEamId,(v1, v2)->v1));
        TreeMap<String, List<Equipment>> collect = equipmentList.stream().collect(Collectors.groupingBy(Equipment::getName, TreeMap::new, Collectors.toList()));

        Map<Long,String> map = new HashMap<>();

        while(true){
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            JipISBCINFO jipISBCINFO = new JipISBCINFO();
            jipISBCINFO.setSENDER("MES");
            Map<String, Object> dataObj = new HashMap<>();
            dataObj.put("IS_BC_INFO", jipISBCINFO);// header信息
            String result = null;
            JSONObject resultValue = null;
            Integer pageSize = 20;
            if(!StringUtils.isEmpty(extendValue1)){
                pageSize = NumberUtil.Object2Integer(extendValue1,20);
            }
            SyncEquipmentInDto syncEquipmentInDto = new SyncEquipmentInDto();
            syncEquipmentInDto.setPAGE(i);
            syncEquipmentInDto.setPAGESIZE(pageSize);
            syncEquipmentInDto.setBRANCH(NumberUtil.object2String(extendValue,""));
//            syncEquipmentInDto.setASSETNUM();
//            syncEquipmentInDto.setDESCRIPTION();
//            syncEquipmentInDto.setEND_DATE();
//            syncEquipmentInDto.setLEVEL();
//            syncEquipmentInDto.setSTART_DATE();

            dataObj.put("IT_DATA", syncEquipmentInDto);
            String json = JSONObject.toJSONString(dataObj);
            HttpEntity<JSONObject> request = new HttpEntity(dataObj, headers);
            ResponseEntity<String> responseEntity = restTemplate.postForEntity(url,request,String.class);
            if(responseEntity.getStatusCodeValue() != 200){
                throw new BusinessException("eam请求服务器异常！");
            }
            try {
                result = responseEntity.getBody();
                resultValue = JSONObject.parseObject(result);
                String et_date = resultValue.getString("ET_DATE");
//                JSONArray jsonArray = result.getJSONArray("ET_DATE");
                List<EamDeviceResponseDto> eamDeviceResponseDtoList = JSONObject.parseArray(et_date, EamDeviceResponseDto.class);
                for(EamDeviceResponseDto eamDeviceResponseDto : eamDeviceResponseDtoList){
                    if(collect.containsKey(eamDeviceResponseDto.getSCADACODE()) && !StringUtils.isEmpty(eamDeviceResponseDto.getASSETNUM())){
                        List<Equipment> equipmentList1 = collect.get(eamDeviceResponseDto.getSCADACODE());
                        Equipment equipment = equipmentList1.get(0);
                        equipment.setEamId(eamDeviceResponseDto.getASSETNUM());
                        map.put(equipment.getId(),eamDeviceResponseDto.getASSETNUM());
                    }
                }
//                handleEquipment(jsonArray);
            } catch (Exception e) {
                e.printStackTrace();
//                requestLogService.saveRequestLog("eam同步设备",url, new JSONObject(dataObj), result);
                sysLogService.save("eam同步设备",url,"error", json, result);
//                throw new BusinessException("数据异常！");
                ReturnT.FAIL.setMsg("数据异常！");
                return ReturnT.FAIL;
            }
            // 保存交互记录
//            requestLogService.saveRequestLog("eam同步设备",url, new JSONObject(dataObj), result);
            sysLogService.save("eam同步设备",url,"info", json, result);

            JSONObject ES_BC_INFO = resultValue.getJSONObject("ES_BC_INFO");
            if (!ES_BC_INFO.getString("TEXT2").equals("0000")) {
                i++;
            }else{
                break;
            }
//            Integer total = Integer.valueOf(ES_BC_INFO.getString("TEXT1"));
            Integer total = NumberUtil.Object2Integer(ES_BC_INFO.getString("TEXT1"),0);
            if(total == 0){
                break;
            }
            int page =(int) Math.ceil(total * 1.0 / pageSize);
//            //todo 临时测试
//            page = 2;
            if(i >= page + 1){
                break;
            }
        }
        Set<Map.Entry<Long, String>> entries = map.entrySet();
        for(Map.Entry<Long, String> entry : entries){
            Long key = entry.getKey();
            String value = entry.getValue();
            equipmentService.updateEquipmentEamId(key,value);
        }
        ReturnT.SUCCESS.setContent(JSONObject.toJSONString(map));
        return ReturnT.SUCCESS;
    }



    @Override
    @XxlJob("syncEquipmentWarningInfo")
    public void syncEquipmentWarningInfo(ToMESData data) {
        List<DictionaryItem> list = dictionaryItemService.findByThemeValueAndItemName("eam_url","syncEquipmentWarningInfo",true);
        if (list == null || list.size() == 0) {
            throw new BusinessException("eam同步设备预警请求地址数据字典未配置！");
        }
        String url = list.get(0).getValue();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        String deviceCode = data.getDeviceCode();
        if (com.sw.mes.core.utils.StringUtils.isBlank(deviceCode)) {
            throw new RuntimeException("未传输炉台号");
        }

        Equipment equipment = equipmentService.findByCode(deviceCode);
        if (null == equipment) {
            throw new RuntimeException("MES未配置此炉台信息");
        }

        if(StringUtils.isEmpty(equipment.getEamId())){
            throw new RuntimeException("此炉台设备台账信息无EAM设备id");
        }

        String taskCode = data.getTaskCode();
        String[] taskCodeNames = taskCode.split("-");
        if (taskCodeNames.length != 2) throw new RuntimeException("工序名称格式不正确:" + taskCode);

        // taskName  EAM报警-报警
        // 报警
        String name = taskCodeNames[1];
        // EAM报警
        String nameType = taskCodeNames[0];
        List<AlarmConfig> all = alarmConfigService.findByDeviceType(data.getDeviceType());
        Map<String, String> map = all.stream().collect(Collectors.toMap(AlarmConfig::getCode,AlarmConfig::getName,(v1,v2)->v1));
        Map<String, String> collectionData = data.getStartCollectionData();
        Map<String, Object> startValidateMap = data.getStartValidateMap();
        String errorDesc = "";
        // 可能有多个报警一起上报
        Map<String,String> map2 = new HashMap<>();
        if(!collectionData.isEmpty()){
            Set<Map.Entry<String, String>> entries = collectionData.entrySet();
            for(Map.Entry<String, String> entry : entries){
                String key = entry.getKey();
                String value = entry.getValue();
                if(startValidateMap.containsKey(key)){
                    Object o = startValidateMap.get(key);
                    String s = NumberUtil.object2String(o, "");
                    if(!StringUtils.isEmpty(s) && !s.equals(value)){
                        if(map.containsKey(key)){
                            errorDesc = map.get(key);
                            map2.put(key,errorDesc);
                        } else {
                            errorDesc = "未知报警";
                            map2.put(key,errorDesc);
                        }
                    }
                }

            }
        }
//        if(map1.containsKey("工步")){
//            Object stepName = map1.get("工步");
//            if(null != stepName){
//                BigDecimal bigDecimal = NumberUtil.Object2BigDecimal(stepName, null);
//                if(null != bigDecimal){
//                    int i = bigDecimal.intValue();
//                    if(EAPUtils.stepMapping.containsKey(i)){
//                        map1.put("工步",EAPUtils.stepMapping.get(i));
//                    }
//                }
//            }
//        }

        Set<Map.Entry<String, String>> entries = map2.entrySet();
        for(Map.Entry<String, String> entry : entries){
            String key = entry.getKey();
            String value = entry.getValue();
            Map<String, Object> dataObj = new HashMap<>();
            dataObj.put("assetCode",equipment.getEamId());
            dataObj.put("deviceNo",equipment.getName());
//            String uuid = UuidUtils.generateUuid();
            dataObj.put("messageId",data.getMessageId());
            dataObj.put("errorFlag","1");
            dataObj.put("errorDesc",value);
            dataObj.put("errorTime", DateUtil.toDate(data.getStartTime(),DateUtil.longFormat));
            dataObj.put("pointCode",key);
            dataObj.put("manufacturers","MES");
            String json = JSONObject.toJSONString(dataObj);
            HttpEntity<JSONObject> request = new HttpEntity(dataObj, headers);
            String result = "";
            try {
                ResponseEntity<String> responseEntity = restTemplate.postForEntity(url,request,String.class);
                if(responseEntity.getStatusCodeValue() != 200){
                    throw new BusinessException("eam同步设备预警请求服务器异常！");
                }
                result = responseEntity.getBody();
            } catch (Exception e) {
                e.printStackTrace();
                sysLogService.save("eam同步设备预警",url,"error", json, result);
            }
            sysLogService.save("eam同步设备预警",url,"info", json, result);
        }
    }

    @Override
//    @XxlJob("syncEquipmentStatus")
    @ServiceLogs(description = "设备状态上报EAM")
    public void syncEquipmentStatus(Equipment equipment) {
        if (null == equipment) {
            throw new RuntimeException("MES未配置此炉台信息");
        }

        if(StringUtils.isEmpty(equipment.getEamId())){
            throw new RuntimeException("此炉台设备台账信息无EAM设备id");
        }
        List<DictionaryItem> list = dictionaryItemService.findByThemeValueAndItemName("eam_url","syncEquipmentStatus",true);
        if (list == null || list.size() == 0) {
            throw new BusinessException("eam同步状态请求地址数据字典未配置！");
        }
        String url = list.get(0).getValue();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        Object o = redisUtils.hmGet(deviceStatusKey, equipment.getName());

        Integer lastStatus = NumberUtil.Object2Integer(o, -1);
        Integer status1 = equipment.getStatus();
        if("停炉".equals(equipment.getCurrentStep())){
            status1 = 9;
        }

        List<DictionaryItem> dictionaryItems = dictionaryItemService.findByThemeValueAndItemName("eam_device_status",equipment.getDevice().getName(),true);

        if(dictionaryItems.isEmpty()){
            throw new BusinessException("设备状态数据字典未配置！");
        }
        TreeMap<String, List<DictionaryItem>> collect = dictionaryItems.stream().collect(Collectors.groupingBy(DictionaryItem::getValue, TreeMap::new, Collectors.toList()));



        if(!lastStatus.equals(status1)) {

            String status = status1.toString();
            List<DictionaryItem> dictionaryItems1 = collect.get(status);
            if(null == dictionaryItems1){
                throw new BusinessException("设备状态数据字典未配置！" + status);
            }
            DictionaryItem dictionaryItem = dictionaryItems1.get(0);
            String pointDesc = dictionaryItem.getExtendValue();
            Map<String, Object> dataObj = new HashMap<>();
            dataObj.put("assetCode", equipment.getEamId());
            dataObj.put("deviceNo",equipment.getName());
            String uuid = UuidUtils.generateUuid();
            dataObj.put("messageId", uuid);
            dataObj.put("assetStatus", status);
            Date date = new Date();
            dataObj.put("pointDesc", pointDesc);
            dataObj.put("changeTime", date);
//            dataObj.put("pointName", "SC-02QF-PM24.SC-02QF-PM24.Out_Warn");
            dataObj.put("manufacturers", "5");
            dataObj.put("type", 1);
            HttpEntity<JSONObject> request = new HttpEntity(dataObj, headers);
            String json = JSONObject.toJSONString(dataObj);
            String result = "";
            try {
                ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, request, String.class);
                if (responseEntity.getStatusCodeValue() != 200) {
                    throw new BusinessException("eam同步设备状态请求服务器异常！");
                }
                result = responseEntity.getBody();
            } catch (Exception e) {
                e.printStackTrace();
                log.error("eam同步设备状态请求服务器异常: ", e);
                sysLogService.save("eam同步设备状态", url, "error", json, result);
                return;
            }
            // 保存交互记录
            sysLogService.save("eam同步设备状态", url, "info", json, result);
            redisUtils.hmSet(deviceStatusKey, equipment.getName(), status1);

        }
    }


    private void handleEquipment(JSONArray array) {
        int length = array.size();
        // 使用for循环遍历每个物料组信息数据
        for (int i = 0; i < length; i++) {
            JSONObject element = array.getJSONObject(i);
            String BRANCH = element.getString("BRANCH");
            String BRANCHDESC = element.getString("BRANCHDESC");
            String CHP = element.getString("CHP");
            String CHPD = element.getString("CHPD");
            String CLASSIFICATIONDESC = element.getString("CLASSIFICATIONDESC");
            String DESC= element.getString("DESC");
            String DEVICECLASS = element.getString("DEVICECLASS");
            String FJTYPE = element.getString("FJTYPE");
            String HIERARCHYPATH = element.getString("HIERARCHYPATH");
            String ITEMNUM = element.getString("ITEMNUM");
            String JTWZ= element.getString("JTWZ");
            String LEVEL = element.getString("LEVEL");
            String LOCATION = element.getString("LOCATION");
            String LOCATIONDESC = element.getString("LOCATIONDESC");
            String PARENT = element.getString("PARENT");
            String PARENTDESC = element.getString("PARENTDESC");
            String PLP = element.getString("PLP");
            String PLPD = element.getString("PLPD");
            String UDSTATUS = element.getString("UDSTATUS");
        }
    }
}
