package com.yfd.platform.modules.auxcontrol.service.impl;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.component.WebSocketServer;
import com.yfd.platform.component.iec104.client.MasterSysDataHandler;
import com.yfd.platform.component.iec104.config.Iec104Config;
import com.yfd.platform.component.iec104.server.Iec104Master;
import com.yfd.platform.component.iec104.server.Iec104MasterFactory;
import com.yfd.platform.component.iec104.server.master.BootNettyClientChannel;
import com.yfd.platform.component.iec104.server.master.BootNettyClientChannelCache;
import com.yfd.platform.component.iec104.server.master.EventLoopGroupManager;
import com.yfd.platform.component.utils.OptimizedThreadPool;
import com.yfd.platform.modules.auxcontrol.domain.DeviceSignal;
import com.yfd.platform.modules.auxcontrol.domain.GatewayDevice;
import com.yfd.platform.modules.auxcontrol.mapper.DeviceSignalMapper;
import com.yfd.platform.modules.auxcontrol.mapper.GatewayDeviceMapper;
import com.yfd.platform.modules.auxcontrol.service.IGatewayDeviceService;
import com.yfd.platform.utils.StringUtils;
import io.netty.channel.EventLoopGroup;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 变电站-通讯网关设备 服务实现类
 * </p>
 *
 * @author zhengsl
 * @since 2025-04-23
 */
@Service
public class GatewayDeviceServiceImpl extends ServiceImpl<GatewayDeviceMapper, GatewayDevice> implements IGatewayDeviceService {

    @Resource
    private GatewayDeviceMapper gatewayDeviceMapper;

    @Resource
    private DeviceSignalMapper deviceSignalMapper;

    /**********************************
     * 用途说明: 根据IP,更新心跳保持时间
     * 参数说明
     * ip 终端对应IP
     * 返回值说明: 无
     ***********************************/
    @Override
    public void updateKeepLiveTime(String ip) {
        LambdaUpdateWrapper<GatewayDevice> queryWrapper = new LambdaUpdateWrapper<>();
        queryWrapper.eq(GatewayDevice::getIpAddr, ip).set(GatewayDevice::getStatus, "01").set(GatewayDevice::getKeepliveTime, new Timestamp(System.currentTimeMillis()));
        this.update(queryWrapper);
    }

    /**********************************
     * 用途说明: 分页查询变电站网关设备
     * 参数说明 deviceName 设备名称
     * 参数说明 deviceModel 设备型号
     * 参数说明 deviceType 设备类型
     * 参数说明 status 状态
     * 参数说明 page
     * 返回值说明: com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.yfd.platform.modules.auxcontrol.domain.GatewayDevice>
     ***********************************/
    @Override
    public Page<GatewayDevice> getGatewayDevicePage(String stationId, String deviceName, String deviceModel,
                                                    String deviceType,
                                                    String status, Page<GatewayDevice> page) {
        //根据条件查询 变电站系统设备 分页查询变电站系统设备
        LambdaQueryWrapper<GatewayDevice> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(stationId)) {
            queryWrapper.like(GatewayDevice::getStationId, stationId);
        }
        //如果设备名称 deviceName不为空
        if (StringUtils.isNotEmpty(deviceName)) {
            queryWrapper.like(GatewayDevice::getDeviceName, deviceName);
        }
        //如果设备型号 deviceModel不为空
        if (StringUtils.isNotEmpty(deviceModel)) {
            queryWrapper.like(GatewayDevice::getDeviceModel, deviceModel);
        }
        //如果设备类型 deviceType不为空
        if (StringUtils.isNotEmpty(deviceType)) {
            queryWrapper.eq(GatewayDevice::getDeviceType, deviceType);
        }
        //如果设备状态 status不为空
        if (StringUtils.isNotEmpty(status)) {
            queryWrapper.eq(GatewayDevice::getStatus, status);
        }
        //根据设备编号排序
        queryWrapper.orderByAsc(GatewayDevice::getDeviceCode);
        return gatewayDeviceMapper.selectPage(page, queryWrapper);
    }

    /**********************************
     * 用途说明: 新增变电站网关设备
     * 参数说明 gatewayDevice 网关设备对象
     * 返回值说明: boolean
     ***********************************/
    @Override
    public boolean addGatewayDevice(GatewayDevice gatewayDevice) {
        if (StrUtil.isNotBlank(gatewayDevice.getIpAddr())) {
            LambdaQueryWrapper<GatewayDevice> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(GatewayDevice::getIpAddr, gatewayDevice.getIpAddr());
            int count = this.count(queryWrapper);
            if (count > 0) {
                throw new RuntimeException("当前ip已经有网关机绑定");
            }
        }
        if (StrUtil.isNotBlank(gatewayDevice.getIpAddr()) && !Validator.isIpv4(gatewayDevice.getIpAddr())) {
            throw new RuntimeException("当前ip地址不规范");
        }
        return this.saveOrUpdate(gatewayDevice);
    }

    /**********************************
     * 用途说明: 修改变电站网关设备
     * 参数说明 gatewayDevice 网关设备对象
     * 返回值说明: boolean
     ***********************************/
    @Override
    public boolean updateGatewayDevice(GatewayDevice gatewayDevice) {
        if (StrUtil.isNotBlank(gatewayDevice.getIpAddr())) {
            LambdaQueryWrapper<GatewayDevice> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.ne(GatewayDevice::getId, gatewayDevice.getId()).eq(GatewayDevice::getIpAddr,
                    gatewayDevice.getIpAddr());
            int count = this.count(queryWrapper);
            if (count > 0) {
                throw new RuntimeException("当前ip已经有网关机绑定");
            }
        }
        if (StrUtil.isNotBlank(gatewayDevice.getIpAddr()) && !Validator.isIpv4(gatewayDevice.getIpAddr())) {
            throw new RuntimeException("当前ip地址不规范");
        }

        return this.saveOrUpdate(gatewayDevice);
    }

    @Override
    public boolean connectToSlave(String ip) {
        LambdaQueryWrapper<GatewayDevice> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GatewayDevice::getIpAddr, ip);
        GatewayDevice systemDevice = gatewayDeviceMapper.selectOne(queryWrapper);
        if (ObjUtil.isNotEmpty(systemDevice)) {
            Iec104Config iec104Config = new Iec104Config();
            iec104Config.setFrameAmountMax((short) 10);
            short terminnalAddress = systemDevice.getIecAddr().shortValue();
            //通讯网关机地址
            iec104Config.setTerminnalAddress(terminnalAddress);
            iec104Config.setSlaveCode(systemDevice.getDeviceCode());
            iec104Config.setSlaveIP(systemDevice.getIpAddr());
            EventLoopGroup group = EventLoopGroupManager.getEventLoopGroup(ip);
            if (ObjUtil.isNotEmpty(group)) {
                try {
                    disconnectToSlave(ip);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    log.error("Exception caught", e);
                }
            }
//            Runnable runnable = () -> {
//                Iec104Master iec104server = Iec104MasterFactory.createTcpClientMaster(iec104Config.getSlaveIP(), 2404);
//                try {
//                    iec104server.setDataHandler(new MasterSysDataHandler()).setConfig(iec104Config).run();
//                } catch (Exception e) {
//                    EventLoopGroupManager.shutdownEventLoopGroup(ip);
//                    log.error(String.format("%s-对应的终端连接失败！", iec104Config.getSlaveIP()));
//                }
//            };
//            OptimizedThreadPool threadPool = OptimizedThreadPool.getInstance();
//            threadPool.execute(runnable);

        }
        return true;
    }

    @Override
    //断开与网关机的通讯连接
    public boolean disconnectToSlave(String ip) {
        LambdaQueryWrapper<GatewayDevice> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GatewayDevice::getIpAddr, ip);
        GatewayDevice gatewayDevice = gatewayDeviceMapper.selectOne(queryWrapper);
        if (ObjUtil.isEmpty(gatewayDevice)) {
            return true;
        }
        if (BootNettyClientChannelCache.channelMapCache.size() <= 0) {
            return true;
        }
        for (Map.Entry<String, BootNettyClientChannel> entry :
                BootNettyClientChannelCache.channelMapCache.entrySet()) {
            BootNettyClientChannel bootNettyChannel = entry.getValue();
            if (bootNettyChannel != null && bootNettyChannel.getChannel().isOpen() && bootNettyChannel.getCode().equals(ip)) {
                bootNettyChannel.getChannel().pipeline().close();
                bootNettyChannel.getChannel().close();
                bootNettyChannel.getScheduledTaskPool().stopSendCommandTask();
                BootNettyClientChannelCache.remove(entry.getKey());
                EventLoopGroupManager.shutdownEventLoopGroup(ip);

                gatewayDevice.setStatus("02");
                gatewayDeviceMapper.updateById(gatewayDevice);
                List<DeviceSignal> list = deviceSignalMapper.selectDeviceSignalByIp(ip);
                String message = JSONUtil.toJsonStr(list);
                try {
                    WebSocketServer.sendInfo(message);
                } catch (IOException e) {
                    log.error("Exception caught", e);
                }
            }
        }
        return true;
    }

    /**********************************
     * 用途说明: 查询网关机列表
     * 参数说明 stationId 变电站ID
     * 返回值说明: java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
     ***********************************/
    @Override
    public List<Map<String, Object>> getGatewayList(String stationId) {
        LambdaQueryWrapper<GatewayDevice> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StrUtil.isNotBlank(stationId), GatewayDevice::getStationId, stationId).select(GatewayDevice::getIpAddr, GatewayDevice::getDeviceName);
        return this.listMaps(queryWrapper);
    }
}
