/*
 * 文 件 名:  ChargingPileServer
 * 版    权:  华设设计集团股份有限公司
 * 描    述:  充电桩TCP服务器
 * 修 改 人:  lvwenbin
 * 修改时间:  2025/12/22
 */
package com.ruoyi.ems.charging.config;

import com.ruoyi.ems.charging.core.ChargingPileChannelInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * 充电桩TCP服务器
 * 作为服务端监听充电桩的连接请求
 *
 * @author lvwenbin
 * @version [版本号, 2025/12/22]
 */
@Component
public class ChargingPileServer {

    private static final Logger log = LoggerFactory.getLogger(ChargingPileServer.class);

    @Value("${adapter.charging-pile.server.port:8234}")
    private int port;

    @Value("${adapter.charging-pile.server.boss-threads:1}")
    private int bossThreads;

    @Value("${adapter.charging-pile.server.worker-threads:4}")
    private int workerThreads;

    @Autowired
    private ChargingPileChannelInitializer channelInitializer;

    private EventLoopGroup bossGroup;

    private EventLoopGroup workerGroup;

    private Channel serverChannel;

    /**
     * 启动服务器
     */
    @PostConstruct
    public void start() {
        new Thread(this::doStart, "charging-pile-server").start();
    }

    private void doStart() {
        try {
            bossGroup = new NioEventLoopGroup(bossThreads);
            workerGroup = new NioEventLoopGroup(workerThreads);

            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 1024).option(ChannelOption.SO_REUSEADDR, true)
                .childOption(ChannelOption.SO_KEEPALIVE, true).childOption(ChannelOption.TCP_NODELAY, true)
                .childOption(ChannelOption.SO_RCVBUF, 65536).childOption(ChannelOption.SO_SNDBUF, 65536)
                .childHandler(channelInitializer);

            ChannelFuture future = bootstrap.bind(port).sync();
            serverChannel = future.channel();

            log.info("充电桩TCP服务器启动成功，监听端口: {}", port);

            // 阻塞直到服务器通道关闭
            serverChannel.closeFuture().sync();

        }
        catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("充电桩TCP服务器启动被中断", e);
        }
        catch (Exception e) {
            log.error("充电桩TCP服务器启动失败", e);
        }
        finally {
            shutdown();
        }
    }

    /**
     * 关闭服务器
     */
    @PreDestroy
    public void shutdown() {
        log.info("正在关闭充电桩TCP服务器...");

        if (serverChannel != null) {
            try {
                serverChannel.close().sync();
            }
            catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }

        if (bossGroup != null) {
            bossGroup.shutdownGracefully();
        }

        if (workerGroup != null) {
            workerGroup.shutdownGracefully();
        }

        log.info("充电桩TCP服务器已关闭");
    }

    /**
     * 获取服务器是否运行中
     */
    public boolean isRunning() {
        return serverChannel != null && serverChannel.isActive();
    }

    /**
     * 获取监听端口
     */
    public int getPort() {
        return port;
    }
}
