// Copyright 2012-2025 The NATS Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Adapted from server/signal.go in the NATS server Go source.

using System.Runtime.InteropServices;

namespace ZB.MOM.NatsNet.Server;

/// <summary>
/// OS signal handling for <see cref="NatsServer"/>.
/// Mirrors Go <c>signal.go</c>.
/// </summary>
public sealed partial class NatsServer
{
    private PosixSignalRegistration? _sigHup;
    private PosixSignalRegistration? _sigTerm;
    private PosixSignalRegistration? _sigInt;

    /// <summary>
    /// Registers OS signal handlers (SIGHUP, SIGTERM, SIGINT).
    /// On Windows, falls back to <see cref="Console.CancelKeyPress"/>.
    /// Mirrors Go <c>Server.handleSignals</c>.
    /// </summary>
    internal void HandleSignals()
    {
        if (GetOpts()?.NoSigs == true) return;

        if (OperatingSystem.IsWindows())
        {
            Console.CancelKeyPress += (_, e) =>
            {
                e.Cancel = true;
                Noticef("Caught interrupt signal, shutting down...");
                _ = ShutdownAsync();
            };
            return;
        }

        // SIGHUP — reload configuration
        _sigHup = PosixSignalRegistration.Create(PosixSignal.SIGHUP, ctx =>
        {
            ctx.Cancel = true;
            Noticef("Trapped SIGHUP signal, reloading configuration...");
            try { Reload(); }
            catch (Exception ex) { Errorf("Config reload failed: {0}", ex.Message); }
        });

        // SIGTERM — graceful shutdown
        _sigTerm = PosixSignalRegistration.Create(PosixSignal.SIGTERM, ctx =>
        {
            ctx.Cancel = true;
            Noticef("Trapped SIGTERM signal, shutting down...");
            _ = ShutdownAsync();
        });

        // SIGINT — interrupt (Ctrl+C)
        _sigInt = PosixSignalRegistration.Create(PosixSignal.SIGINT, ctx =>
        {
            ctx.Cancel = true;
            Noticef("Trapped SIGINT signal, shutting down...");
            _ = ShutdownAsync();
        });
    }

    internal void DisposeSignalHandlers()
    {
        _sigHup?.Dispose();
        _sigTerm?.Dispose();
        _sigInt?.Dispose();
    }
}
