package ru.zetit.bridgeandjoins.crypto;

import io.grpc.Server;
import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder;
import io.grpc.netty.shaded.io.netty.channel.epoll.EpollEventLoopGroup;
import io.grpc.netty.shaded.io.netty.channel.epoll.EpollServerDomainSocketChannel;
import io.grpc.netty.shaded.io.netty.channel.unix.DomainSocketAddress;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.logging.Logger;

/**
 * Точка входа crypto-service.
 *
 * Слушает Unix Domain Socket по пути из переменной окружения
 * BJ_CRYPTO_SOCKET (по умолчанию /run/bj/crypto.sock).
 * Используется UDS вместо TCP — минимальная задержка и изоляция
 * от сети.
 */
public final class CryptoServer {

    private static final Logger LOG = Logger.getLogger(CryptoServer.class.getName());
    private static final String DEFAULT_SOCKET = "/run/bj/crypto.sock";

    private CryptoServer() {
        // utility
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        String socketPath = System.getenv().getOrDefault("BJ_CRYPTO_SOCKET", DEFAULT_SOCKET);
        String provider = System.getenv().getOrDefault("BJ_CRYPTO_PROVIDER", "stub");

        Files.deleteIfExists(Path.of(socketPath));

        KeystoreProvider keystore = KeystoreProvider.byName(provider);
        VerifyHandler verifyHandler = new VerifyHandler(keystore);
        SignHandler signHandler = new SignHandler(keystore);
        HealthHandler healthHandler = new HealthHandler(provider);

        CryptoServiceImpl service = new CryptoServiceImpl(verifyHandler, signHandler, healthHandler);

        Server server = NettyServerBuilder
                .forAddress(new DomainSocketAddress(socketPath))
                .channelType(EpollServerDomainSocketChannel.class)
                .bossEventLoopGroup(new EpollEventLoopGroup(1))
                .workerEventLoopGroup(new EpollEventLoopGroup())
                .addService(service)
                .build()
                .start();

        LOG.info("crypto-service: UDS " + socketPath + ", provider=" + provider);

        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            LOG.info("crypto-service: graceful shutdown");
            server.shutdown();
        }));

        server.awaitTermination();
    }
}
