package org.framework.lazy.cloud.network.heartbeat.server.netty.udp.handler;


import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.InternalNetworkServerPermeateServerRealServer;
import org.framework.lazy.cloud.network.heartbeat.common.adapter.ChannelFlowAdapter;
import org.framework.lazy.cloud.network.heartbeat.common.enums.ChannelFlowEnum;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.server.netty.flow.ServerChannelFlow;
import org.framework.lazy.cloud.network.heartbeat.server.netty.udp.socket.NettyUdpServerPermeateServerConnectRealSocket;

import java.util.UUID;

@Slf4j
public class NettyUdpServerPermeateServerVisitorHandler extends SimpleChannelInboundHandler<ByteBuf> {
    private final InternalNetworkServerPermeateServerRealServer internalNetworkServerPermeateServerRealServer;
    private final ChannelFlowAdapter channelFlowAdapter;// 流量适配器
//    private final NettyChannelPool nettyChannelPool = new DefaultNettyChannelPool(10);

    public NettyUdpServerPermeateServerVisitorHandler(InternalNetworkServerPermeateServerRealServer internalNetworkServerPermeateServerRealServer, ChannelFlowAdapter channelFlowAdapter) {
        this.internalNetworkServerPermeateServerRealServer = internalNetworkServerPermeateServerRealServer;
        this.channelFlowAdapter = channelFlowAdapter;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 访客连接上代理服务器了
        Channel visitorChannel = ctx.channel();
        // 先不读取访客数据
        visitorChannel.config().setOption(ChannelOption.AUTO_READ, false);


        // 生成访客ID
        String visitorId = UUID.randomUUID().toString();
        // 当前通道绑定访客ID
        ChannelAttributeKeyUtils.buildVisitorId(visitorChannel, visitorId);

        // 判断是否有可用的通道 如果没有创建新的通道

        log.info("开始准备绑定渗透真实通道: {}", internalNetworkServerPermeateServerRealServer.getVisitorPort());
        // 创建这是客户端通道池

        NettyUdpServerPermeateServerConnectRealSocket.buildRealServer(internalNetworkServerPermeateServerRealServer, visitorChannel, visitorId);

        log.info("内网渗透 服务端访客端口连接成功了");

        super.channelActive(ctx);
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, ByteBuf buf) {

        // 访客通道
        Channel visitorChannel = ctx.channel();
        Integer visitorPort = internalNetworkServerPermeateServerRealServer.getVisitorPort();
        byte[] bytes = new byte[buf.readableBytes()];
        buf.readBytes(bytes);
        // 获取客户端通道，而后进行数据下发
        log.debug("【服务端】访客端口成功接收数据:{}", new String(bytes));

        // 使用访客的通信通道

        Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(visitorChannel);
        // 下一个通道开启自动读写
        log.info("write data to channelId:{}",nextChannel.id().asLongText());
        nextChannel.config().setOption(ChannelOption.AUTO_READ, true);
        // 绑定数据流量
        ChannelAttributeKeyUtils.buildInFlow(nextChannel, bytes.length);

        // 将二进制数组转换成 ByteBuf 然后进行发送
        ByteBuf visitorBuf = visitorChannel.config().getAllocator().buffer(bytes.length);
        visitorBuf.writeBytes(bytes);

        nextChannel.writeAndFlush(visitorBuf);

        // 处理访客流量
        ServerChannelFlow serverChannelFlow = ServerChannelFlow
                .builder()
                .clientId("server_id")
                .channelFlowEnum(ChannelFlowEnum.IN_FLOW)
                .port(visitorPort)
                .flow(bytes.length)
                .build();
        channelFlowAdapter.asyncHandler(visitorChannel, serverChannelFlow);
        log.debug("服务端访客端口成功发送数据了");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {

        // 通信通道自动读写打开 ，然后关闭通信通道
        Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(ctx.channel());
        if (nextChannel != null && nextChannel.isActive()) {

            nextChannel.config().setOption(ChannelOption.AUTO_READ, true);
            //  通知服务端 关闭访问通道、真实通道
            nextChannel.close();
        }
        log.warn("服务端访客端口断开连接");
        super.channelInactive(ctx);
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(ctx.channel());
        if (nextChannel != null) {
            log.debug("transfer AUTO_READ:{} ", ctx.channel().isWritable());
            nextChannel.config().setOption(ChannelOption.AUTO_READ, ctx.channel().isWritable());
        }
        if (ctx.channel().isWritable()) {
            log.debug("Channel is writable again");
            // 恢复之前暂停的操作，如写入数据
        } else {
            log.debug("Channel is not writable");
            // 暂停写入操作，等待可写状态
        }
        log.info("visitorId:{} channelWritabilityChanged!");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("exceptionCaught");
        // 使用通信通道 下发关闭访客
        Channel nextChannel = ChannelAttributeKeyUtils.getNextChannel(ctx.channel());
        if (nextChannel != null) {
            // 下发关闭访客
            nextChannel.close();
        }

        ctx.close();
    }
}