package com.ruoyi.mill.udp;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * UDP 接收服务
 * 监听来自 L3 的下行电文，解析电文号后交 TelegramDispatcher 处理
 *
 * 电文帧结构（iXComPCS 第18章）：
 *   前6字节 ASCII = 电文号 (TC_NO)
 *   后续字节       = 电文体 (payload)
 */
@Component
public class UdpServer {

    private static final Logger log = LoggerFactory.getLogger(UdpServer.class);
    private static final int TC_NO_LEN = 6;

    @Autowired
    private UdpProperties props;

    @Autowired
    private TelegramDispatcher dispatcher;

    private DatagramSocket socket;
    private volatile boolean running;
    private final ExecutorService executor = Executors.newSingleThreadExecutor(
            r -> { Thread t = new Thread(r, "udp-receiver"); t.setDaemon(true); return t; });

    @PostConstruct
    public void start() throws Exception {
        socket = new DatagramSocket(props.getLocalPort());
        running = true;
        executor.submit(this::receiveLoop);
        log.info("[UDP-SERVER] 已启动，监听端口: {}", props.getLocalPort());
    }

    @PreDestroy
    public void stop() {
        running = false;
        if (socket != null && !socket.isClosed()) socket.close();
        executor.shutdownNow();
        log.info("[UDP-SERVER] 已停止");
    }

    private void receiveLoop() {
        byte[] buf = new byte[props.getBufferSize()];
        while (running) {
            try {
                DatagramPacket pkt = new DatagramPacket(buf, buf.length);
                socket.receive(pkt);
                byte[] data = Arrays.copyOf(pkt.getData(), pkt.getLength());
                if (data.length < TC_NO_LEN) {
                    log.warn("[UDP-SERVER] 收到过短数据包，长度={}", data.length);
                    continue;
                }
                String tcNo   = new String(data, 0, TC_NO_LEN, StandardCharsets.US_ASCII).trim();
                byte[] payload = Arrays.copyOfRange(data, TC_NO_LEN, data.length);
                dispatcher.dispatch(tcNo, payload);
            } catch (Exception e) {
                if (running) log.error("[UDP-SERVER] 接收异常", e);
            }
        }
    }
}
