package org.nl.point;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Test;
import org.nl.acs.device.device_driver.standard_inspect.ItemDto;
import org.nl.acs.device.domain.Device;
import org.nl.acs.device.domain.DeviceExtra;
import org.nl.acs.device.service.DeviceExtraService;
import org.nl.acs.device.service.dto.DeviceDto;
import org.nl.acs.device.service.dto.DeviceExtraDto;
import org.nl.acs.device.service.impl.DeviceServiceImpl;
import org.nl.acs.device.service.mapper.DeviceExtraMapper;
import org.nl.acs.device.service.mapper.DeviceRunpointMapper;
import org.nl.acs.device_driver.tianneng.guhuashi.GuhuashiSiteDefination;
import org.nl.acs.device_driver.tianneng.site.SiteDefination;
import org.nl.acs.opc.DeviceAppService;
import org.nl.acs.storage_cell.domain.StorageCell;
import org.nl.acs.storage_cell.service.dto.StorageCellDto;
import org.nl.acs.storage_cell.service.mapper.StorageCellMapper;
import org.nl.acs.utils.ConvertUtil;
import org.nl.common.utils.CodeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;


import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Author: lyd
 * @Description: 创建点位
 * @Date: 2023/6/15
 */
@Slf4j
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class PointCreate {


    @Autowired
    private DeviceExtraService deviceExtraService;
    @Autowired
    private StorageCellMapper storageCellMapper;
    @Autowired
    private DeviceExtraMapper deviceExtraMapper;
    @Autowired
    private DeviceRunpointMapper deviceRunpointMapper;
    @Autowired
    private DeviceServiceImpl device;
    @Autowired
    private DeviceAppService deviceAppService;




    @Test
    void testGH() {
        List<Device> pointList = new ArrayList<>();
        for (int i = 1; i <= 84; i++) {
            String pointCode = "GHS";
            if (i < 10) {
                pointCode = pointCode + "0" + i;
            } else {
                pointCode = pointCode + i;
            }
            Device point = new Device();
            point.setDevice_id(IdUtil.simpleUUID());
            point.setDevice_code(pointCode);
            point.setDevice_name(pointCode);
            point.setDevice_type("conveyor");
            point.setCreate_by("管理员");
            point.setUpdate_by("管理员");
            point.setCreate_time(DateUtil.now());
            point.setUpdate_time(DateUtil.now());
            pointList.add(point);
            for (int j = 1; j <= 7; j++) {
                String pointCode7 = pointCode + "0" + j;
                Device point7 = new Device();
                point7.setDevice_id(IdUtil.simpleUUID());
                point7.setDevice_code(pointCode7);
                point7.setDevice_name(pointCode7);
                point7.setDevice_type("conveyor");
                point7.setCreate_by("管理员");
                point7.setUpdate_by("管理员");
                point7.setCreate_time(DateUtil.now());
                point7.setUpdate_time(DateUtil.now());
                pointList.add(point7);
            }
            String pointCode2 = pointCode + "C";
            Device point2 = new Device();
            point2.setDevice_id(IdUtil.simpleUUID());
            point2.setDevice_code(pointCode2);
            point2.setDevice_name(pointCode2);
            point2.setDevice_type("conveyor");
            point2.setCreate_by("管理员");
            point2.setUpdate_by("管理员");
            point2.setCreate_time(DateUtil.now());
            point2.setUpdate_time(DateUtil.now());
            pointList.add(point2);
            String pointCode3 = pointCode + "R";
            Device point3 = new Device();
            point3.setDevice_id(IdUtil.simpleUUID());
            point3.setDevice_code(pointCode3);
            point3.setDevice_name(pointCode3);
            point3.setDevice_type("conveyor");
            point3.setCreate_by("管理员");
            point3.setUpdate_by("管理员");
            point3.setCreate_time(DateUtil.now());
            point3.setUpdate_time(DateUtil.now());
            pointList.add(point3);
        }
        device.saveOrUpdateBatch(pointList);
    }


    @Test
    public void ConfigGhsDevice() {
        try {
            List<Device> deviceList = device.list(new LambdaUpdateWrapper<Device>().like(Device::getDevice_code, "GHS"));
            deviceList = deviceList.stream().sorted(Comparator.comparing(Device::getDevice_code)).collect(Collectors.toList());
            GuhuashiSiteDefination siteDefination = new GuhuashiSiteDefination();
            for (Device device1 : deviceList) {
                String matchedDigits = "";
                Pattern pattern = Pattern.compile("\\d+");
                Matcher matcher = pattern.matcher(device1.getDevice_code());
                if (matcher.find()) {
                    matchedDigits = matcher.group(0);
                }
                //GHS01-GHS84
                if (Integer.parseInt(matchedDigits) < 85 && !device1.getDevice_code().contains("R") && !device1.getDevice_code().contains("C")) {
                    Result result = getResult(device1, true);
                    LambdaQueryWrapper<DeviceExtra> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(DeviceExtra::getDevice_id, result.device_id);
                    wrapper.eq(DeviceExtra::getFiled_type, "02");
                    //先删除
                    deviceExtraMapper.delete(wrapper);
                    //001db读
                    List<ItemDto> itemDto = siteDefination.getReadableItemDtos();
                    //新增deviceExtra表
                    insertDeviceExtra(result, itemDto, "02", "GHS");
                    LambdaQueryWrapper<DeviceExtra> wrapper3 = new LambdaQueryWrapper<>();
                    wrapper3.eq(DeviceExtra::getDevice_id, result.device_id);
                    wrapper3.eq(DeviceExtra::getFiled_type, "03");
                    deviceExtraMapper.delete(wrapper3);
                    //001db写
                    List<ItemDto> itemDtos = siteDefination.getWriteableItemDtos();
                    //新增deviceExtra表
                    insertDeviceExtra(result, itemDtos, "03", "GHS");
                    deviceAppService.removeDevice(result.device_code);
                    deviceAppService.addDevice(result.device_code);
                } else {
                    Result result = getResult(device1, false);
                    StorageCellDto celldto = new StorageCellDto();
                    celldto.setStorage_id(IdUtil.simpleUUID());
                    celldto.setStorage_code(result.device_code);
                    celldto.setParent_storage_code(result.device_code);
                    celldto.setX("0");
                    celldto.setY("0");
                    celldto.setZ("0");
                    celldto.setAddress(Integer.parseInt(CodeUtil.getNewCode("NDCADDRESS_NO")));
                    celldto.setCreate_by("admin");
                    celldto.setCreate_time(DateUtil.now());
                    celldto.setUpdate_by("admin");
                    celldto.setUpdate_time(DateUtil.now());
                    StorageCell entity = ConvertUtil.convert(celldto, StorageCell.class);
                    storageCellMapper.insert(entity);
                    deviceAppService.removeDevice(result.device_code);
                    deviceAppService.addDevice(result.device_code);
                }
            }
        } catch (Exception ex) {
            log.error("新增失败--------------------------------------------------------------------------------------------------");
            throw new RuntimeException("新增失败！");
        }
    }


    @Test
    void ConfigZcssxDevice() {
        try {
            List<Device> deviceList = device.list(new LambdaUpdateWrapper<Device>().like(Device::getDevice_code, "ZCSSX"));
            deviceList = deviceList.stream().sorted(Comparator.comparing(Device::getDevice_code)).collect(Collectors.toList());
            //其他设备 ZCSSX0102 - ZCSSX0106
            List<Device> otherDevice = new ArrayList<>();
            SiteDefination siteDefination = new SiteDefination();
            for (Device device1 : deviceList) {
                String matchedDigits = "";
                Pattern pattern = Pattern.compile("\\d+");
                Matcher matcher = pattern.matcher(device1.getDevice_code());
                if (matcher.find()) {
                    matchedDigits = matcher.group(0);
                }
                //0101 - 0607
                if (matchedDigits.length() > 2) {
                    Result result = getResult(device1, true);
                    LambdaQueryWrapper<DeviceExtra> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(DeviceExtra::getDevice_id, result.device_id);
                    wrapper.eq(DeviceExtra::getFiled_type, "02");
                    //先删除
                    deviceExtraMapper.delete(wrapper);
                    if (matchedDigits.endsWith("101") || matchedDigits.endsWith("301") || matchedDigits.endsWith("501")) {
                        //001db读
                        List<ItemDto> itemDto = siteDefination.getReadableItemDtos();
                        //新增deviceExtra表
                        insertDeviceExtra(result, itemDto, "02", "ZCSSX");
                        LambdaQueryWrapper<DeviceExtra> wrapper3 = new LambdaQueryWrapper<>();
                        wrapper3.eq(DeviceExtra::getDevice_id, result.device_id);
                        wrapper3.eq(DeviceExtra::getFiled_type, "03");
                        deviceExtraMapper.delete(wrapper3);
                        //001db写
                        List<ItemDto> itemDtos = siteDefination.getWriteableItemDtos();
                        //新增deviceExtra表
                        insertDeviceExtra(result, itemDto, "03", "ZCSSX");
                    } else if (matchedDigits.endsWith("107") || matchedDigits.endsWith("307") || matchedDigits.endsWith("507")) {
                        //007db读
                        List<ItemDto> itemDto = siteDefination.getReadableItemDtos1();
                        //新增deviceExtra表
                        insertDeviceExtra(result, itemDto, "02", "ZCSSX");
                        LambdaQueryWrapper<DeviceExtra> wrapper3 = new LambdaQueryWrapper<>();
                        wrapper3.eq(DeviceExtra::getDevice_id, result.device_id);
                        wrapper3.eq(DeviceExtra::getFiled_type, "03");
                        deviceExtraMapper.delete(wrapper3);
                        //007db写
                        List<ItemDto> itemDtos = siteDefination.getWriteableItemDtos1();
                        //新增deviceExtra表
                        insertDeviceExtra(result, itemDto, "03", "ZCSSX");
                    } else if (matchedDigits.endsWith("201") || matchedDigits.endsWith("401") || matchedDigits.endsWith("601")) {
                        //007db读
                        List<ItemDto> itemDto = siteDefination.getReadableItemDtos2();
                        //新增deviceExtra表
                        insertDeviceExtra(result, itemDto, "02", "ZCSSX");
                        LambdaQueryWrapper<DeviceExtra> wrapper3 = new LambdaQueryWrapper<>();
                        wrapper3.eq(DeviceExtra::getDevice_id, result.device_id);
                        wrapper3.eq(DeviceExtra::getFiled_type, "03");
                        deviceExtraMapper.delete(wrapper3);
                        //007db写
                        List<ItemDto> itemDtos = siteDefination.getWriteableItemDtos2();
                        //新增deviceExtra表
                        insertDeviceExtra(result, itemDto, "03", "ZCSSX");
                    } else if (matchedDigits.endsWith("207") || matchedDigits.endsWith("407") || matchedDigits.endsWith("607")) {
                        //007db读
                        List<ItemDto> itemDto = siteDefination.getReadableItemDtos3();
                        //新增deviceExtra表
                        insertDeviceExtra(result, itemDto, "02", "ZCSSX");
                        LambdaQueryWrapper<DeviceExtra> wrapper3 = new LambdaQueryWrapper<>();
                        wrapper3.eq(DeviceExtra::getDevice_id, result.device_id);
                        wrapper3.eq(DeviceExtra::getFiled_type, "03");
                        deviceExtraMapper.delete(wrapper3);
                        //007db写
                        List<ItemDto> itemDtos = siteDefination.getWriteableItemDtos3();
                        //新增deviceExtra表
                        insertDeviceExtra(result, itemDto, "03", "ZCSSX");
                    } else {
                        otherDevice.add(device1);
                    }
                    deviceAppService.removeDevice(result.device_code);
                    deviceAppService.addDevice(result.device_code);
                } else {
                    // 01-06 读
                    Result result = getResult(device1, true);
                    LambdaQueryWrapper<DeviceExtra> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(DeviceExtra::getDevice_id, result.device_id);
                    wrapper.eq(DeviceExtra::getFiled_type, "02");
                    //先删除
                    deviceExtraMapper.delete(wrapper);
                    //处理读的DB字段
                    List<ItemDto> itemDto = siteDefination.getReadableItemDtos4();
                    //新增deviceExtra表
                    insertDeviceExtra(result, itemDto, "02", "ZCSSX");
                    LambdaQueryWrapper<DeviceExtra> wrapper1 = new LambdaQueryWrapper<>();
                    wrapper1.eq(DeviceExtra::getDevice_id, result.device_id);
                    wrapper1.eq(DeviceExtra::getFiled_type, "03");
                    deviceExtraMapper.delete(wrapper1);
                    deviceAppService.removeDevice(result.device_code);
                    deviceAppService.addDevice(result.device_code);
                }
            }
            otherDevice = otherDevice.stream().sorted(Comparator.comparing(Device::getDevice_code)).collect(Collectors.toList());
            int j = 0;
            int v = 819;
            for (int d = 0; d < otherDevice.size(); d++) {
                if (j == 5) {
                    v = v + 2;
                }
                if (j == 10) {
                    v = 819;
                    j = 0;
                }
                // 002-006 db读
                JSONObject param = new JSONObject();
                String code = "ZCSSX" + "." + getOpcPlcCode(otherDevice.get(d).getDevice_code()) + "." + otherDevice.get(d).getDevice_code() + "." + "move";
                String name = "光电信号";
                String value = "DB6.B" + v;
                param.put("extra_id", IdUtil.simpleUUID());
                param.put("extra_code", code);
                param.put("extra_name", value);
                param.put("remark", name);
                param.put("order_seq", 1);
                param.put("filed_type", "02");
                param.put("device_id", otherDevice.get(d).getDevice_id());
                param.put("device_code", otherDevice.get(d).getDevice_code());
                param.put("create_by", "admin");
                param.put("create_time", DateUtil.now());
                DeviceExtra entity = ConvertUtil.convert(param, DeviceExtra.class);
                deviceExtraMapper.insert(entity);
                j++;
                v++;
            }
        } catch (Exception ex) {
            log.error("新增失败--------------------------------------------------------------------------------------------------");
            throw new RuntimeException("新增失败！");
        }
    }

    private void insertDeviceExtra(Result result, List<ItemDto> itemDto, String type, String deviceName) {
        for (int i = 0; i < itemDto.size(); i++) {
            JSONObject param = new JSONObject();
            param.put("extra_id", IdUtil.simpleUUID());
            String code = deviceName + "." + getOpcPlcCode(result.device_code) + "." + result.device_code + "." + itemDto.get(i).getCode();
            String name = itemDto.get(i).getName();
            String value = itemDto.get(i).getDb();
            param.put("extra_code", code);
            param.put("extra_name", value);
            param.put("remark", name);
            param.put("order_seq", i + 1);
            param.put("filed_type", type);
            param.put("device_id", result.device_id);
            param.put("device_code", result.device_code);
            param.put("create_by", "admin");
            param.put("create_time", DateUtil.now());
            param.put("update_by", "admin");
            param.put("update_time", DateUtil.now());
            DeviceExtra entity = ConvertUtil.convert(param, DeviceExtra.class);
            deviceExtraMapper.insert(entity);
        }
    }


    public String getOpcPlcCode(String device_code) {
        if (device_code.contains("GHS")) {
            return "GHS";
        }
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(device_code);
        String matchedDigits = "";
        if (matcher.find()) {
            matchedDigits = matcher.group(0);
        }
        String OpcPlcCode = "";
        if (matchedDigits.startsWith("01") || matchedDigits.startsWith("02")) {
            OpcPlcCode = "ZCSSX01";
        } else if (matchedDigits.startsWith("03") || matchedDigits.startsWith("04")) {
            OpcPlcCode = "ZCSSX02";
        } else {
            OpcPlcCode = "ZCSSX03";
        }
        return OpcPlcCode;
    }


    /**
     * updateDevice 是否配置plc
     */
    @NotNull
    private Result getResult(Device devices, Boolean updateDevice) {
        //设备标识
        String device_id = devices.getDevice_id();
        String device_code = devices.getDevice_code();
        String opc_plc_id = "";
        String opc_server_id = "";
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(device_code);
        String matchedDigits = "";
        DeviceDto dto = device.findById(device_id);
        if (device_code.contains("GHS")) {
            opc_plc_id = "564f2fc4f3b4411882f64c705f78be65";
            opc_server_id = "ce71ac3b6cae4d488b97e950fcf82107";
            dto.setDriver_code("guhuashi_site");
        } else if (device_code.contains("ZCSSX")) {
            if (matcher.find()) {
                matchedDigits = matcher.group(0);
            }
            if (matchedDigits.startsWith("01") || matchedDigits.startsWith("02")) {
                opc_plc_id = "2e105b9ec6ac4cff8b607b5debb3419c";
            } else if (matchedDigits.startsWith("03") || matchedDigits.startsWith("04")) {
                opc_plc_id = "8b1e7edfe7a44bfbb0e1e81fc571c130";
            } else {
                opc_plc_id = "1bfe8ab7629a4a6a952bca955f1e3acd";
            }
            opc_server_id = "ddd9cb5804ec4ec09fd47375a85c78ea";
            dto.setDriver_code("tianneng_site");
        }
        if (dto != null) {
            if (updateDevice) {
                dto.setOpc_plc_id(opc_plc_id);
                dto.setOpc_server_id(opc_server_id);
            } else {
                dto.setDriver_code("standard_ordinary_site");
            }
            dto.setIs_config("true");
            dto.setIs_route("true");
            dto.setAddress("0");
            device.update(dto);
        }
        //先删除设备扩展表【acs_device_extra】
        deviceExtraService.deleteAllByDeviceIds(new String[]{device_id});
        JSONObject addDeviceExtra = new JSONObject();
        addDeviceExtra.put("device_id", device_id);
        addDeviceExtra.put("device_code", device_code);
        //设备标识不算扩展属性
        addDeviceExtra.remove("device_id");
        for (Object key : addDeviceExtra.keySet()) {
            DeviceExtraDto dtos = new DeviceExtraDto();
            String now = DateUtil.now();
            dtos.setExtra_code((String) key);
            dtos.setDevice_code(addDeviceExtra.getString("device_code"));
            dtos.setDevice_id(device_id);
            dtos.setExtra_name((String) key);
            dtos.setExtra_value(String.valueOf(addDeviceExtra.get(key)));
            dtos.setFiled_type("01");
            dtos.setIs_active("1");
            dtos.setIs_delete("0");
            dtos.setCreate_by("admin");
            dtos.setOrder_seq(new BigDecimal(0));
            dtos.setExtra_id(IdUtil.simpleUUID());
            dtos.setUpdate_by("admin");
            dtos.setUpdate_time(now);
            dtos.setCreate_time(now);
            DeviceExtra entity = ConvertUtil.convert(dtos, DeviceExtra.class);
            //扩展表新增
            deviceExtraMapper.insert(entity);
        }
        Result result = new Result(device_id, device_code);
        return result;
    }

    private static class Result {
        public final String device_id;
        public final String device_code;

        public Result(String device_id, String device_code) {
            this.device_id = device_id;
            this.device_code = device_code;
        }
    }

    public String formatNum(int x) {
        if (x < 10) {
            return "0" + x;
        }
        return String.valueOf(x);
    }



}
