package com.zehong.web.controller.equipment;

import com.zehong.common.utils.TCP.TCPClient;
import com.zehong.system.domain.TEquipmentAlarmData;
import com.zehong.system.domain.TEquipmentInfo;
import com.zehong.system.domain.TStoreyInfo;
import com.zehong.system.service.ITEquipmentAlarmDataService;
import com.zehong.system.service.ITEquipmentInfoService;
import com.zehong.system.service.ITStoreyInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 生产设备数据采集
 *
 * @author zehong
 * @date 2025-05-28
 */
@RestController
@RequestMapping("/equipmentData")
public class EquipmentDataCollection {
    private static final Logger log = LoggerFactory.getLogger(EquipmentDataCollection.class);
    @Autowired
    private ITEquipmentInfoService tEquipmentInfoService;
    @Autowired
    private ITStoreyInfoService tStoreyInfoService;
    @Autowired
    private ITEquipmentAlarmDataService tEquipmentAlarmDataService;

    /**
     * 1.老化柜、标定柜巡查
     * 2.老化层断电
     */
    @GetMapping("/equipmentPatrol")
    public void equipmentPatrol(){
        List<String> type = new ArrayList<>();
        type.add("1");
        type.add("2");
        List<TEquipmentInfo> equipmentInfos = tEquipmentInfoService.selectTEquipmentList(type);
        try{
            if(equipmentInfos.size() == 0){
                log.error("设备列表查询结果为空");
                throw new Exception("无设备信息！");
            }
            String sendMsg = "00010000000601040000000A";
            String receiveMsg;

            TEquipmentAlarmData alarmData = new TEquipmentAlarmData();
            for(TEquipmentInfo info : equipmentInfos){
                /* 1.老化柜、标定柜通讯 */
                receiveMsg = agingCabinetCommunication(info, sendMsg);
                if(receiveMsg == null){
                    // 记录异常数据
                    alarmData.setfAlarmType("01"); // 01.老化柜 02.标定柜 03.机械臂 04.老化层 05.点位
                    alarmData.setfEquipmentCode(info.getfEquipmentCode());
                    alarmData.setfAlarmData("老化柜通讯失败，无响应");
                    tEquipmentAlarmDataService.insertTEquipmentAlarmData(alarmData);
                    // 更新老化柜状态（“0”空闲，“1”运行，“2”故障）
                    info.setfStatus("2");
                    tEquipmentInfoService.updateTEquipmentInfo(info);
                } else if (receiveMsg.length() != 58) {
                    // 记录异常数据
                    alarmData.setfAlarmType("01"); // 01.老化柜 02.标定柜 03.机械臂 04.老化层 05.点位
                    alarmData.setfEquipmentCode(info.getfEquipmentCode());
                    alarmData.setfAlarmData("老化柜IP或端口号为空");
                    tEquipmentAlarmDataService.insertTEquipmentAlarmData(alarmData);
                } else {
                    // 解析服务器返回信息
                    // 示例：00 01 00 00 00 17 01 04 14 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    String flag = receiveMsg.substring(18, 58);
                    if("0000000000000000000000000000000000000000".equals(flag) && !"0".equals(info.getfStatus())){
                        // 更新老化柜状态（“0”空闲，“1”运行，“2”故障）
                        info.setfStatus("0");
                        info.setfUpdateTime(new Date());
                        tEquipmentInfoService.updateTEquipmentInfo(info);
                    } else if (!"0000000000000000000000000000000000000000".equals(flag) && "0".equals(info.getfStatus())){
                        info.setfStatus("1");
                        info.setfUpdateTime(new Date());
                        tEquipmentInfoService.updateTEquipmentInfo(info);

                        // 解析层状态，根据层编号修改状态
                        int startIndex;
                        int endIndex;
                        int code; //组成老化层编号
                        String status;
                        TStoreyInfo storeyInfo = new TStoreyInfo();
                        for(startIndex = 18,endIndex = 22,code = 1; endIndex <= receiveMsg.length(); startIndex += 4,endIndex += 4,code++){
                            status = receiveMsg.substring(startIndex, endIndex);
                            storeyInfo.setfStoreyCode(info.getfEquipmentCode() + "-" + code);
                            if("0000".equals(status)){
                                /* 2.老化层断电 */


                                storeyInfo.setfStatus("4"); //断电
                                tStoreyInfoService.updateTStoreyInfoByCode(storeyInfo);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 上料：
     * 1.由页面向机械臂发送上料指令，通讯机械臂
     * 2.通讯老化柜，根据响应信息获取层状态
     * 3.通讯老化层，分别获取72个点位状态，开始计时
     * 4.向点位写入时间，分别写入年、月、日、时、分
     */
    @GetMapping("/agingCabinet")
//    public void agingCabinetData(TStoreyInfo storeyInfo) throws Exception {
    public void agingCabinetData() throws Exception {
        // 获取老化层信息，将用页面传参代替此步骤
        Long id = Long.valueOf(1);
        TStoreyInfo storeyInfo = tStoreyInfoService.selectTStoreyInfoById(id);

        if (storeyInfo == null) {
            throw new Exception("无老化层信息！");
        }
        //获取老化柜信息
        TEquipmentInfo equipmentInfo = tEquipmentInfoService.selectTEquipmentInfoById(storeyInfo.getfEquipmentId());
        if (equipmentInfo == null) {
            throw new Exception("无老化柜信息！");
        }

        /* 1.机械臂通讯 */


        /* 2.老化柜通讯 */
        String sendMsg1 = "00010000000601040000000A";
        String receiveMsg1 = agingCabinetCommunication(equipmentInfo, sendMsg1);

        TEquipmentAlarmData alarmData = new TEquipmentAlarmData();
        if (receiveMsg1 == null) {
            // 记录异常数据
            alarmData.setfAlarmType("01"); //01.老化柜 02.标定柜 03.机械臂 04.老化层
            alarmData.setfEquipmentCode(equipmentInfo.getfEquipmentCode());
            alarmData.setfAlarmData("老化柜通讯失败，无响应");
            tEquipmentAlarmDataService.insertTEquipmentAlarmData(alarmData);
            throw new Exception(storeyInfo.getfStoreyCode() + "号老化柜通讯故障！");
        } else if(receiveMsg1.length() != 58){
            throw new Exception(receiveMsg1);
        }
        if (receiveMsg1.length() == 58) {
            // 解析服务器返回信息
            // 示例：00 01 00 00 00 17 01 04 14 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
            String storeyCode = storeyInfo.getfStoreyCode();
            int code = Integer.parseInt(storeyCode.substring(storeyCode.indexOf("-")+1));
            int startIndex;
            int endIndex;
            String status;
            int flag = 1;
            for(startIndex = 18,endIndex = 22,code = 1; endIndex <= receiveMsg1.length(); startIndex += 4,endIndex += 4,flag++){
                status = receiveMsg1.substring(startIndex, endIndex);
                if(flag == code && "0001".equals(status)){

                    /* 3.老化层通讯，72个点位 */
                    String sendMsg2 = "010000000601030000000A"; //第二个“01”位置代表点位地址
                    String receiveMsg2 = null;
                    int num2 = 1;
                    //若无返回信息将再次通讯，最多通讯3次
                    while(receiveMsg2 == null && num2 >= 3){
                        receiveMsg2 = storeyCommunication(storeyInfo, sendMsg2);
                        num2++;
                    }
                    if(receiveMsg2 == null){
                        // 记录异常数据
                        alarmData.setfAlarmType("04"); //01.老化柜 02.标定柜 03.机械臂 04.老化层 05.点位
                        alarmData.setfEquipmentCode(storeyInfo.getfStoreyCode());
                        alarmData.setfAlarmData("老化层通讯失败，无响应");
                        tEquipmentAlarmDataService.insertTEquipmentAlarmData(alarmData);
                    }
                    // 解析服务器返回信息
                    // 示例：000100000017010314 浓度0000 状态0001 AD值01F7 标定AD值01F7 年07E9 月0005 日0004 时000E 分000F 秒0015
                    String value = receiveMsg2.substring(22, 26); //板子状态
                    if("0001".equals(value)){

                        /* 4.写入时间，年、月、日、时、分 */
                        // 示例：0100000006 设备地址01写时间06 寄存器地址04（年04月05日06时07分08） 年/月/日/时/分数值07E9（2025）
                        Calendar cal=Calendar.getInstance();
                        // 当前年
                        int y = cal.get(Calendar.YEAR);
                        // 当前月
                        int m = cal.get(Calendar.MONTH) + 1;
                        // 当前日
                        int d = cal.get(Calendar.DATE);
                        // 当前小时
                        int h = cal.get(Calendar.HOUR_OF_DAY);
                        // 当前分钟
                        int mm = cal.get(Calendar.MINUTE);
                        String minutes = Integer.toHexString(mm).length()<2?"0"+Integer.toHexString(mm):Integer.toHexString(mm);;
                        String hours = Integer.toHexString(h).length()<2?"0"+Integer.toHexString(h):Integer.toHexString(h);;
                        String date = Integer.toHexString(d).length()<2?"0"+Integer.toHexString(d):Integer.toHexString(d);;
                        String month = Integer.toHexString(m).length()<2?"0"+Integer.toHexString(m):Integer.toHexString(m);;
                        String year = Integer.toHexString(Integer.valueOf(String.valueOf(y).substring(2, 4)));

                        String sendMsgYear = "01000000060" + code + "0604" + year;
                        String receiveMsgYear = null;
                        int num3 = 1;
                        //写入时间失败将再次通讯，最多通讯3次
                        while(!sendMsgYear.equals(receiveMsgYear) || receiveMsgYear == null){
                            receiveMsgYear = storeyCommunication(storeyInfo, sendMsgYear);
                            num3++;
                        }
                        if(!sendMsgYear.equals(receiveMsgYear) || receiveMsgYear == null){
                            // 记录异常数据
                            alarmData.setfAlarmType("05"); //01.老化柜 02.标定柜 03.机械臂 04.老化层 05.点位
                            alarmData.setfEquipmentCode(storeyInfo.getfStoreyCode());
                            alarmData.setfAlarmData("写入时间失败");
                            tEquipmentAlarmDataService.insertTEquipmentAlarmData(alarmData);
                        }
                    }
                }
            }
        }

    }

    // 老化柜通讯
    private String agingCabinetCommunication(TEquipmentInfo equipment, String sendMsg) {
        String receiveMsg = null;
        String ip = null;
        Integer port = null;
        try{
            ip = equipment.getfIp();
            port = equipment.getfPort();
            if(ip == null || port == null){
                receiveMsg = equipment.getfEquipmentCode();
                return receiveMsg;
            } else {
                // 发送并接收数据
                receiveMsg = TCPClient.PLCConnect(ip, port, sendMsg);
            }
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
        return receiveMsg;
    }

    //老化层通讯
    private String storeyCommunication(TStoreyInfo storey, String sendMsg){
        String ip = null;
        Integer port = null;
        String receiveMsg = null;
        try{
            ip = storey.getfIp();
            port = storey.getfPort();
            if(ip == null || port == null){
                throw new Exception("请确认老化层的IP和端口号是否正确！");
            }
            // 发送并接收数据
            receiveMsg = TCPClient.PLCConnect(ip, port, sendMsg);
        }catch(Exception e){
            throw new RuntimeException(e);
        }
        return receiveMsg;
    }
}
