//package com.ruoyi.web.core.nfid;
//
//import io.netty.bootstrap.Bootstrap;
//import io.netty.buffer.ByteBuf;
//import io.netty.buffer.Unpooled;
//import io.netty.channel.*;
//import io.netty.channel.nio.NioEventLoopGroup;
//import io.netty.channel.socket.SocketChannel;
//import io.netty.channel.socket.nio.NioSocketChannel;
//import io.netty.handler.timeout.IdleState;
//import io.netty.handler.timeout.IdleStateEvent;
//import io.netty.handler.timeout.IdleStateHandler;
//
//import java.util.Arrays;
//import java.util.List;
//import java.util.Random;
//import java.util.concurrent.TimeUnit;
//
//public class NFIDTestClient {
//    private static final String HOST = "localhost";
//    private static final int PORT = 3728;
//    private static final int HEARTBEAT_INTERVAL = 30; // 秒
//    private static final int RECONNECT_DELAY = 5; // 重试间隔(秒)
//
//    // 测试帧数据
//    private static final List<byte[]> TEST_FRAMES = Arrays.asList(
//            hexStringToByteArray("5A000112000018000C00010000F04EE845D972D375340002013D08000DE3AA3482"),
//            hexStringToByteArray("5A000112000018000CE28068940000502F57B4B649300002010D08000DE3AAF63F"),
//            hexStringToByteArray("5A000112000018000C2C14F77EF04EE845D974502A340002012C08000DE3AA7930"),
//            hexStringToByteArray("5A00010100004B00145238303038303030303230323030303030303038000001A1000C4A756E203130203230323000010011000002000E56312E30305F323031393036303903000A323032302D30362D31308FC5")
//    );
//
//    // 心跳帧
//    private static final byte[] HEARTBEAT_FRAME = hexStringToByteArray("5A00000001000000000000");
//
//    // 测试模式枚举
//    private enum TestMode {
//        NORMAL,      // 正常发送
//        STICKY,      // 粘包模式
//        SPLIT,       // 拆包模式
//        MIXED        // 混合模式
//    }
//
//    private static TestMode currentMode = TestMode.MIXED; // 默认使用混合模式
//
//    public static void main(String[] args) throws Exception {
//        if (args.length > 0) {
//            currentMode = TestMode.valueOf(args[0].toUpperCase());
//        }
//        System.out.println("Starting NFID test client in " + currentMode + " mode");
//
//        EventLoopGroup group = new NioEventLoopGroup();
//        Bootstrap bootstrap = createBootstrap(group);
//        connect(bootstrap, 0);
//    }
//
//    private static Bootstrap createBootstrap(EventLoopGroup group) {
//        Bootstrap b = new Bootstrap();
//        b.group(group)
//                .channel(NioSocketChannel.class)
//                .handler(new ChannelInitializer<SocketChannel>() {
//                    @Override
//                    protected void initChannel(SocketChannel ch) {
//                        ch.pipeline()
//                                .addLast(new IdleStateHandler(0, HEARTBEAT_INTERVAL, 0, TimeUnit.SECONDS))
//                                .addLast(new HeartbeatHandler())
//                                .addLast(new FrameSenderHandler())
//                                .addLast(new ResponseHandler());
//                    }
//                });
//        return b;
//    }
//
//    private static void connect(Bootstrap bootstrap, int attempt) {
//        bootstrap.connect(HOST, PORT).addListener(new ChannelFutureListener() {
//            @Override
//            public void operationComplete(ChannelFuture future) throws Exception {
//                if (future.isSuccess()) {
//                    System.out.println("Connected to NFID server at " + HOST + ":" + PORT);
//                    Channel channel = future.channel();
//
//                    channel.closeFuture().addListener(closeFuture -> {
//                        System.out.println("Connection lost, attempting to reconnect...");
//                        scheduleReconnect(bootstrap);
//                    });
//
//                } else {
//                    System.err.println("Connection attempt " + (attempt + 1) + " failed: " + future.cause().getMessage());
//                    scheduleReconnect(bootstrap);
//                }
//            }
//        });
//    }
//
//    private static void scheduleReconnect(Bootstrap bootstrap) {
//        bootstrap.config().group().schedule(() -> {
//            System.out.println("Reconnecting...");
//            connect(bootstrap, 0);
//        }, RECONNECT_DELAY, TimeUnit.SECONDS);
//    }
//
//    /**
//     * 心跳处理器
//     */
//    private static class HeartbeatHandler extends ChannelInboundHandlerAdapter {
//        @Override
//        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
//            if (evt instanceof IdleStateEvent) {
//                IdleStateEvent e = (IdleStateEvent) evt;
//                if (e.state() == IdleState.WRITER_IDLE) {
//                    ctx.writeAndFlush(Unpooled.wrappedBuffer(HEARTBEAT_FRAME));
//                    System.out.println("Sent heartbeat at " + System.currentTimeMillis());
//                }
//            }
//        }
//    }
//
//    /**
//     * 数据帧发送处理器
//     */
//    private static class FrameSenderHandler extends ChannelInboundHandlerAdapter {
//        private final Random random = new Random();
//        private final int MIN_INTERVAL = 500; // 1秒
//        private final int MAX_INTERVAL = 1500; // 3秒
//
//        @Override
//        public void channelActive(ChannelHandlerContext ctx) {
//            System.out.println("Channel active, starting frame sender in " + currentMode + " mode");
//            scheduleSendFrame(ctx);
//        }
//
//        private void scheduleSendFrame(ChannelHandlerContext ctx) {
//            if (!ctx.channel().isActive()) return;
//
//            int delay = MIN_INTERVAL + random.nextInt(MAX_INTERVAL - MIN_INTERVAL);
//            ctx.executor().schedule(() -> {
//                if (ctx.channel().isActive()) {
//                    sendFrameAccordingToMode(ctx);
//                    scheduleSendFrame(ctx);
//                }
//            }, delay, TimeUnit.MILLISECONDS);
//        }
//
//        private void sendFrameAccordingToMode(ChannelHandlerContext ctx) {
//            switch (currentMode) {
//                case NORMAL:
//                    sendNormalFrame(ctx);
//                    break;
//                case STICKY:
//                    sendStickyPackets(ctx);
//                    break;
//                case SPLIT:
//                    sendSplitFrame(ctx);
//                    break;
//                case MIXED:
//                    if (random.nextBoolean()) {
//                        sendNormalFrame(ctx);
//                    } else if (random.nextBoolean()) {
//                        sendStickyPackets(ctx);
//                    } else {
//                        sendSplitFrame(ctx);
//                    }
//                    break;
//            }
//        }
//
//        private void sendNormalFrame(ChannelHandlerContext ctx) {
//            byte[] frame = TEST_FRAMES.get(random.nextInt(TEST_FRAMES.size()));
//            ctx.writeAndFlush(Unpooled.wrappedBuffer(frame));
//            System.out.println("[NORMAL] Sent single frame: " + bytesToHex(frame));
//        }
//
//        private void sendStickyPackets(ChannelHandlerContext ctx) {
//            // 随机合并2-4个帧一起发送
//            int frameCount = 2 + random.nextInt(3);
//            ByteBuf buffer = ctx.alloc().buffer();
//
//            for (int i = 0; i < frameCount; i++) {
//                byte[] frame = TEST_FRAMES.get(random.nextInt(TEST_FRAMES.size()));
//                buffer.writeBytes(frame);
//                System.out.println("[STICKY] Adding frame " + (i+1) + ": " + bytesToHex(frame));
//            }
//
//            ctx.writeAndFlush(buffer);
//            System.out.println("[STICKY] Sent " + frameCount + " frames as sticky packet");
//        }
//
//        private void sendSplitFrame(ChannelHandlerContext ctx) {
//            byte[] frame = TEST_FRAMES.get(random.nextInt(TEST_FRAMES.size()));
//            int splitPoint = 5 + random.nextInt(frame.length - 10); // 确保分割点在中间
//
//            byte[] part1 = Arrays.copyOfRange(frame, 0, splitPoint);
//            byte[] part2 = Arrays.copyOfRange(frame, splitPoint, frame.length);
//
//            System.out.println("[SPLIT] Splitting frame at position " + splitPoint +
//                    " (total length: " + frame.length + ")");
//
//            // 发送第一部分
//            ctx.writeAndFlush(Unpooled.wrappedBuffer(part1));
//            System.out.println("[SPLIT] Sent first part: " + bytesToHex(part1));
//
//            // 延迟发送第二部分
//            ctx.executor().schedule(() -> {
//                if (ctx.channel().isActive()) {
//                    ctx.writeAndFlush(Unpooled.wrappedBuffer(part2));
//                    System.out.println("[SPLIT] Sent second part: " + bytesToHex(part2));
//                }
//            }, 100 + random.nextInt(400), TimeUnit.MILLISECONDS); // 100-500ms延迟
//        }
//    }
//
//    /**
//     * 响应处理器
//     */
//    private static class ResponseHandler extends SimpleChannelInboundHandler<Object> {
//        @Override
//        protected void channelRead0(ChannelHandlerContext ctx, Object msg) {
//            System.out.println("Received server response: " + msg);
//        }
//
//        @Override
//        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
//            System.err.println("Connection error: " + cause.getMessage());
//            ctx.close();
//        }
//    }
//
//    // 辅助方法
//    private static byte[] hexStringToByteArray(String s) {
//        int len = s.length();
//        byte[] data = new byte[len / 2];
//        for (int i = 0; i < len; i += 2) {
//            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
//                    + Character.digit(s.charAt(i+1), 16));
//        }
//        return data;
//    }
//
//    private static String bytesToHex(byte[] bytes) {
//        StringBuilder sb = new StringBuilder();
//        for (byte b : bytes) {
//            sb.append(String.format("%02X ", b));
//        }
//        return sb.toString().trim();
//    }
//}