package com.zt.plat.module.qms.iot.controller.admin;

import com.alibaba.fastjson.JSONObject;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.datapermission.core.annotation.DeptDataPermissionIgnore;
import com.zt.plat.module.qms.iot.service.IotConnectManagerStatsService;
import com.zt.plat.module.qms.iot.tcpserver.cluster.TioServerMessageConfig;
import com.zt.plat.module.qms.iot.tcpserver.cluster.TioServerMessagePublisher;
import com.zt.plat.module.qms.iot.tcpserver.cluster.TioServerMessageVo;
import com.zt.plat.module.qms.iot.tcpserver.core.*;
import com.github.xingfudeshi.knife4j.annotations.ApiOperationSupport;
import com.zt.plat.module.qms.iot.tcpserver.device.RedisSessionComponent;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import tech.zzjc.tio.core.ChannelContext;
import tech.zzjc.tio.core.Tio;
import tech.zzjc.tio.core.stat.ChannelStat;
import tech.zzjc.tio.starter.TioServerBootstrap;
import tech.zzjc.tio.utils.lock.SetWithLock;

import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;

import static java.lang.Thread.sleep;

/**
 * <b>IotManagerStatsController</b>
 * iot 管理统计 
 * <p>更新历史：</p>
 * <pre> 版本         更新时间            更新者        更新内容
 * V1.0      2021-12-1          王兴荣         Add</pre>
 * <b>Copyright (C)  云南志者竟成科技有限公司</b> 
 * @author 王兴荣 &lt;xingrong_wang@will-way.cn&gt;
 * @version V1.0 
 * @since 2021-12-1
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/qms/resource/iot/connect-manager-stats")
@Tag(name = "iot连接管理-连接统计")
@DeptDataPermissionIgnore(enable = "true")
public class IotConnectManagerStatsController {

    @Autowired private TioServerBootstrap tioServerBootstrap;
    @Autowired public RedisSessionComponent redisSessionComponent;
    @Autowired private Environment environment;
    @Autowired private TioServerMessagePublisher tioServerMessagePublisher;
    @Autowired private IotConnectManagerStatsService iotConnectManagerStatsService;
    @GetMapping("/all-connect")
    @ApiOperationSupport(order = 1)
    @Operation(summary = "获取当前所有连接")
    public CommonResult<?> currentAllConnect(@RequestParam(name = "clientIp", required = false) String clientIp) {

        //获取spring服务端口
        String serverPort = environment.getProperty("server.port");
        String serverName = environment.getProperty("spring.application.name");
        String msg = "当前服务端口:" + serverPort + "，服务名称:" + serverName;
        log.error(msg);
        List<ChannelStatInfo> list = new ArrayList<>();
        Set<String> deviceKeys = redisSessionComponent.scanKeys(IotDeviceSessionContext.DEFAULT_DEVICE_SESSION_CONTEXT_KEY + "*");
        Set<String> clientKeys = redisSessionComponent.scanKeys(IotClientSessionContext.DEFAULT_CLIENT_SESSION_CONTEXT_KEY + "*");

        for(String key : deviceKeys){
            IotDeviceSessionForRedisContext deviceContext = redisSessionComponent.getByKey( key);
            String deviceId = deviceContext.getDeviceId();
            String bsId = Long.toString(Long.valueOf(deviceId), Character.MAX_RADIX);
            ChannelStatInfo info = new ChannelStatInfo();
            info.setId(deviceContext.getChannelId());
//            info.setId(deviceContext.getDeviceCode());
            info.setBsId(bsId);
            String controlRealName = ObjectUtils.isEmpty(deviceContext.getControlRealName())? "无" : deviceContext.getControlRealName();
            String deviceName = deviceContext.getDeviceName();
            String deviceCode = deviceContext.getDeviceCode();
//            info.setRealName(userRealName);
//            info.setRemarks("操作人:" + userRealName);
            info.setDeviceId(deviceContext.getDeviceId());
            info.setDeviceCode(deviceCode);
            info.setDeviceType(deviceContext.getDeviceType());
            info.setDeviceName(deviceName);
            StringBuilder sb = new StringBuilder();
            if (StringUtils.isNoneBlank(deviceName)) {
                sb.append("设备名称：").append(deviceName).append(";");
            } else {
                sb.append("注册号:").append(deviceCode).append(";");
                //deviceInfo.append("设备Id:").append(deviceId).append(";");
            }
            sb.append("控制人:").append(controlRealName);
            info.setRemarks(sb.toString());
            info.setClientIp(deviceContext.getClientIp());
            info.setClientPort(deviceContext.getClientPort());
            info.setClientProtocol(deviceContext.getClientProtocol());
            info.setProxyIp(deviceContext.getProxyIp());
            info.setProxyPort(deviceContext.getProxyPort());
            info.setProxyProtocol(deviceContext.getProxyProtocol());
            info.setConnectType(deviceContext.getConnectType());
            //info.setReConnCount(reconnCount);
            info.setDecodeFailCount(deviceContext.getDecodeFailCount());
            info.setUserId(deviceContext.getUserId());
//            info.setToken(token);
            info.setGmtCreate(deviceContext.getGmtCreate());
            info.setReceivedBytes(deviceContext.getReceivedBytes());
            info.setReceivedPackets(deviceContext.getReceivedPackets());
            info.setReceivedTcps(deviceContext.getReceivedTcps());
            info.setBytesPerTcpReceive(deviceContext.getBytesPerTcpReceive());
            info.setPacketsPerTcpReceive(deviceContext.getPacketsPerTcpReceive());
            info.setHandledBytes(deviceContext.getHandledBytes());
            info.setHandledPackets(deviceContext.getHandledPackets());
            info.setSentBytes(deviceContext.getSentBytes());
            info.setSentPackets(deviceContext.getSentPackets());
            if(deviceContext.getLastBalanceDataTime() != null)
                info.setGmtLatestCommunicate(new Date(deviceContext.getLastBalanceDataTime()));
            if(deviceContext.getRegTime() != null)
                info.setRegTime(deviceContext.getRegTime());

            list.add(info);

        }

        for(String key : clientKeys){
            IotClientSessionForRedisContext clientContext = redisSessionComponent.getClientByKey( key);
            ChannelStatInfo info = new ChannelStatInfo();
            info.setId(clientContext.getChannelId());
            String controlRealName = ObjectUtils.isEmpty(clientContext.getControlRealName())? "无" : clientContext.getControlRealName();
//            info.setRealName(userRealName);
//            info.setRemarks("操作人:" + userRealName);
            StringBuilder sb = new StringBuilder();
            sb.append("操作人:").append(controlRealName);
            info.setRemarks(sb.toString());
            info.setClientIp(clientContext.getClientIp());
            info.setClientPort(clientContext.getClientPort());
            info.setClientProtocol(clientContext.getClientProtocol());
            info.setProxyIp(clientContext.getProxyIp());
            info.setProxyPort(clientContext.getProxyPort());
            info.setProxyProtocol(clientContext.getProxyProtocol());
            info.setConnectType(clientContext.getConnectType());
            //info.setReConnCount(reconnCount);
            info.setDecodeFailCount(clientContext.getDecodeFailCount());
            info.setUserId(clientContext.getUserId());
//            info.setToken(token);
            info.setGmtCreate(clientContext.getGmtCreate());
            info.setReceivedBytes(clientContext.getReceivedBytes());
            info.setReceivedPackets(clientContext.getReceivedPackets());
            info.setReceivedTcps(clientContext.getReceivedTcps());
            info.setBytesPerTcpReceive(clientContext.getBytesPerTcpReceive());
            info.setPacketsPerTcpReceive(clientContext.getPacketsPerTcpReceive());
            info.setHandledBytes(clientContext.getHandledBytes());
            info.setHandledPackets(clientContext.getHandledPackets());
            info.setSentBytes(clientContext.getSentBytes());
            info.setSentPackets(clientContext.getSentPackets());
            info.setGmtLatestCommunicate(clientContext.getLastCommunicateTime());
            info.setRegTime(clientContext.getRegTime());

            list.add(info);

        }

        SetWithLock<ChannelContext> setWithLock = Tio.getAll(tioServerBootstrap.getServerTioConfig());
        Set<ChannelContext> set = null;
        ReentrantReadWriteLock.ReadLock readLock = setWithLock.getLock().readLock();

//        try {
//            readLock.lock();
//            set = setWithLock.getObj();
//            for (ChannelContext channelContext : set) {
//
//                ChannelStatInfo info = new ChannelStatInfo();
//                ChannelStat stat = channelContext.stat;
//
//
//                String id = channelContext.getId();
//                String bsId = channelContext.getBsId();
//                Date regTime = channelContext.get("regTime") == null ? null : (Date) channelContext.get("regTime");
//                String ip = channelContext.get("realClientIp") == null ? channelContext.getClientNode().getIp() : channelContext.get("realClientIp").toString(); // 客户端IP
//                int port = channelContext.get("realClientPort") == null ? channelContext.getClientNode().getPort() : Integer.parseInt(channelContext.get("realClientPort").toString()); // 客户端端口
//                String protocol = channelContext.get("realClientProtocol") == null ? channelContext.getClientNode().getProtocol() : channelContext.get("realClientProtocol").toString();//协议
//                String ipProxy = channelContext.getProxyClientNode() == null ? "" : channelContext.getProxyClientNode().getIp();//代理 ip
//                int portProxy = channelContext.getProxyClientNode() == null ? -1 : channelContext.getProxyClientNode().getPort();//代理 端口
//                String protocolProxy = channelContext.getProxyClientNode() == null ? "" : channelContext.getProxyClientNode().getProtocol(); //代理协议
//
//                //连接类型
//                String connectType = channelContext.get(ChannelContextConstant.CONNECT_TYPE) == null ? "" : channelContext.get(ChannelContextConstant.CONNECT_TYPE).toString();
//                if(connectType.equals(ChannelContextConstant.CONNECT_DEVICE))   //设备
//                    continue;
//                switch (connectType) {
//				case ChannelContextConstant.CONNECT_CONSOLE_CLIENT://控制客户端
//			        String userRealName = channelContext.get("user-real-name") == null ? "无" : channelContext.get("user-real-name").toString();
//					info.setRealName(userRealName);
//					info.setRemarks("操作人:" + userRealName);
//					break;
//				case ChannelContextConstant.CONNECT_CAA_CLIENT://平板端
//			        String caaUserRealName = channelContext.get("user-real-name") == null ? "无" : channelContext.get("user-real-name").toString();
//					info.setRealName(caaUserRealName);
//					info.setRemarks("操作人:" + caaUserRealName);
//					break;
//				case ChannelContextConstant.CONNECT_DEVICE://设备
//					IotDeviceSessionContext deviceSessionContext = (IotDeviceSessionContext) channelContext.get(IotDeviceSessionContext.DEFAULT_DEVICE_SESSION_CONTEXT_KEY);
//					String deviceCode = deviceSessionContext.getDeviceCode();
//                    IotDeviceSessionForRedisContext deviceContext = redisSessionComponent.getByDeviceCode(deviceCode);
//                    String deviceId = "";
//                    String deviceType = "";
//                    String deviceName = "";
//                    String controlRealName = "";
//                    if(deviceContext != null){
//                        deviceId = deviceContext.getDeviceId();
//                        deviceType = deviceContext.getDeviceType();
//                        deviceName = deviceContext.getDeviceName();
//                        controlRealName = deviceContext.getControlRealName();
//                    }
//					info.setDeviceId(deviceId);
//					info.setDeviceCode(deviceCode);
//					info.setDeviceType(deviceType);
//					info.setDeviceName(deviceName);
//					info.setControlRealName(controlRealName);
//					StringBuilder deviceInfo = new StringBuilder();
//					if (StringUtils.isNoneBlank(deviceName)) {
//						deviceInfo.append("设备名称：").append(deviceName).append(";");
//					} else {
//						deviceInfo.append("注册号:").append(deviceCode).append(";");
//						//deviceInfo.append("设备Id:").append(deviceId).append(";");
//					}
//					deviceInfo.append("控制人:").append(controlRealName);
//					info.setRemarks(deviceInfo.toString());
//					break;
//
//				default:
//					break;
//				}
//
//
//                int decodeFailCount = stat.getDecodeFailCount(); // 解码异常次数
//                String userId = channelContext.userid; // 用户ID
//                String token = channelContext.getToken(); // 用户token
//                long timeStart = stat.getTimeCreated(); // 统计开始时间
//                // 统计时长
//                AtomicLong receivedBytes = stat.getReceivedBytes(); // 已接收字节
//                AtomicLong receivedPackets = stat.getReceivedPackets(); // 已接收业务包
//                AtomicLong receivedTcps = stat.getReceivedTcps(); // 已接收TCP包
//
//                double bytesPerTcpReceive = stat.getBytesPerTcpReceive(); // 平均每次TCP包接收的字节数
//                double packetsPerTcpReceive = stat.getPacketsPerTcpReceive(); // 平均每次TCP包接收的业务包
//
//                AtomicLong handledBytes = stat.getHandledBytes(); // 已处理字节
//                AtomicLong handledPackets = stat.getHandledPackets(); // 已处理业务包
//
//                AtomicLong sentBytes = stat.getSentBytes(); // 已发送字节数
//                AtomicLong sentPackets = stat.getSentPackets(); // 已发送业务包
//
//                long timeLatestReceivedMsg = stat.getLatestTimeOfReceivedByte();
//                long timeLatestSentMsg = stat.getLatestTimeOfSentPacket();
//                long latestCommunicateTime = Math.max(timeLatestReceivedMsg, timeLatestSentMsg); // 最近一次通信时间
//
//                info.setId(id);
//                info.setBsId(bsId);
//                info.setClientIp(ip);
//                info.setClientPort(port);
//                info.setClientProtocol(protocol);
//                info.setProxyIp(ipProxy);
//                info.setProxyPort(portProxy);
//                info.setProxyProtocol(protocolProxy);
//                info.setConnectType(connectType);
//                //info.setReConnCount(reconnCount);
//                info.setDecodeFailCount(decodeFailCount);
//                info.setUserId(userId);
//                info.setToken(token);
//                info.setGmtCreate(new Date(timeStart));
//                info.setReceivedBytes(receivedBytes);
//                info.setReceivedPackets(receivedPackets);
//                info.setReceivedTcps(receivedTcps);
//                info.setBytesPerTcpReceive(bytesPerTcpReceive);
//                info.setPacketsPerTcpReceive(packetsPerTcpReceive);
//                info.setHandledBytes(handledBytes);
//                info.setHandledPackets(handledPackets);
//                info.setSentBytes(sentBytes);
//                info.setSentPackets(sentPackets);
//                info.setGmtLatestCommunicate(new Date(latestCommunicateTime));
//                info.setRegTime(regTime);
//
//                list.add(info);
//
////                log.info("Current Client Info : [{}].", info);
//            }
//        } catch (Throwable e) {
//            log.error("获取在线连接失败！", e);
//        } finally {
//            readLock.unlock();
//        }
        
//		List<ChannelStatInfo> resultList = list.stream().filter(f -> {
//			if (StringUtils.isNotBlank(clientIp)) {
//				return clientIp.equals(f.getClientIp());
//			}
//			return true;
//		}).sorted(Comparator.comparing(ChannelStatInfo::getClientIp).thenComparing(ChannelStatInfo::getConnectType).thenComparing(ChannelStatInfo::getClientPort)).collect(Collectors.toList());
        return CommonResult.success(list);
    }
    
    /**
     * 关闭连接
     * @param id ChannelContextId
     * @return
     */
    @PostMapping("/close")
    @ApiOperationSupport(order = 6)
    @Operation(summary = "关闭连接")
    public CommonResult<?> close(@RequestParam(name="id",required=true) String id) throws InterruptedException {
        return iotConnectManagerStatsService.close(id, "0");
    }
    
    /**
     * 清除设备控制
     * @param id
     * @return
     */
    @PostMapping("/clearDeviceControl")
    @ApiOperationSupport(order = 7)
    @Operation(summary = "清除设备控制")
    public CommonResult<?> clearDeviceControl(@RequestParam(name="id") String id) throws InterruptedException {
        return iotConnectManagerStatsService.clearDeviceControl(id, "0");
    }

    @RequestMapping("/testMsg")
    public CommonResult<?> testMsg() {

        TioServerMessageVo vo = new TioServerMessageVo();
        vo.setServerClusterMsgType("type1");
        vo.setGroup("aaaa");
        tioServerMessagePublisher.publish( vo);
        return CommonResult.success("ok");
    }
}
