using NATS.Server.Auth;
using NATS.Server.Subscriptions;

namespace NATS.Server.Events;

/// <summary>
/// System event subject patterns.
/// Maps to Go events.go:41-97 subject constants.
/// </summary>
public static class EventSubjects
{
    // Account-scoped events
    public const string ConnectEvent = "$SYS.ACCOUNT.{0}.CONNECT";
    public const string DisconnectEvent = "$SYS.ACCOUNT.{0}.DISCONNECT";
    public const string AccountConnsNew = "$SYS.ACCOUNT.{0}.SERVER.CONNS";
    public const string AccountConnsOld = "$SYS.SERVER.ACCOUNT.{0}.CONNS";

    // Server-scoped events
    public const string ServerStats = "$SYS.SERVER.{0}.STATSZ";
    public const string ServerShutdown = "$SYS.SERVER.{0}.SHUTDOWN";
    public const string ServerLameDuck = "$SYS.SERVER.{0}.LAMEDUCK";
    public const string AuthError = "$SYS.SERVER.{0}.CLIENT.AUTH.ERR";
    public const string AuthErrorAccount = "$SYS.ACCOUNT.CLIENT.AUTH.ERR";

    // Remote server and leaf node events
    public const string RemoteServerShutdown = "$SYS.SERVER.{0}.REMOTE.SHUTDOWN";
    public const string RemoteServerUpdate = "$SYS.SERVER.{0}.REMOTE.UPDATE";
    public const string LeafNodeConnected = "$SYS.ACCOUNT.{0}.LEAFNODE.CONNECT";
    public const string LeafNodeDisconnected = "$SYS.SERVER.{0}.LEAFNODE.DISCONNECT";
    public const string RemoteLatency = "$SYS.SERVER.{0}.ACC.{1}.LATENCY.M2";

    // Request-reply subjects (server-specific)
    public const string ServerReq = "$SYS.REQ.SERVER.{0}.{1}";

    // Wildcard ping subjects (all servers respond)
    public const string ServerPing = "$SYS.REQ.SERVER.PING.{0}";

    // Account-scoped request subjects
    public const string AccountReq = "$SYS.REQ.ACCOUNT.{0}.{1}";
    public const string UserDirectInfo = "$SYS.REQ.USER.INFO";
    public const string UserDirectReq = "$SYS.REQ.USER.{0}.INFO";
    public const string AccountNumSubsReq = "$SYS.REQ.ACCOUNT.NSUBS";
    public const string AccountSubs = "$SYS._INBOX_.{0}.NSUBS";
    public const string ClientKickReq = "$SYS.REQ.SERVER.{0}.KICK";
    public const string ClientLdmReq = "$SYS.REQ.SERVER.{0}.LDM";
    public const string ServerStatsPingReq = "$SYS.REQ.SERVER.PING.STATSZ";
    public const string ServerReloadReq = "$SYS.REQ.SERVER.{0}.RELOAD";

    // Inbox for responses
    public const string InboxResponse = "$SYS._INBOX_.{0}";

    // OCSP advisory events
    // Go reference: ocsp.go — OCSP peer reject and chain validation subjects.
    public const string OcspPeerReject = "$SYS.SERVER.{0}.OCSP.PEER.CONN.REJECT";
    public const string OcspPeerChainlinkInvalid = "$SYS.SERVER.{0}.OCSP.PEER.LINK.INVALID";
    public const string OcspChainValidation = "$SYS.SERVER.{0}.OCSP.CHAIN.VALIDATION";

    // JetStream advisory events
    // Go reference: jetstream_api.go advisory subjects
    public const string JsAdvisoryStreamCreated = "$JS.EVENT.ADVISORY.STREAM.CREATED.{0}";
    public const string JsAdvisoryStreamDeleted = "$JS.EVENT.ADVISORY.STREAM.DELETED.{0}";
    public const string JsAdvisoryStreamUpdated = "$JS.EVENT.ADVISORY.STREAM.UPDATED.{0}";
    public const string JsAdvisoryConsumerCreated = "$JS.EVENT.ADVISORY.CONSUMER.CREATED.{0}.{1}";
    public const string JsAdvisoryConsumerDeleted = "$JS.EVENT.ADVISORY.CONSUMER.DELETED.{0}.{1}";
    public const string JsAdvisoryStreamSnapshotCreated = "$JS.EVENT.ADVISORY.STREAM.SNAPSHOT_CREATE.{0}";
    public const string JsAdvisoryStreamSnapshotCompleted = "$JS.EVENT.ADVISORY.STREAM.SNAPSHOT_COMPLETE.{0}";
    public const string JsAdvisoryStreamRestoreCreated = "$JS.EVENT.ADVISORY.STREAM.RESTORE_CREATE.{0}";
    public const string JsAdvisoryStreamRestoreCompleted = "$JS.EVENT.ADVISORY.STREAM.RESTORE_COMPLETE.{0}";
    public const string JsAdvisoryStreamLeaderElected = "$JS.EVENT.ADVISORY.STREAM.LEADER_ELECTED.{0}";
    public const string JsAdvisoryStreamQuorumLost = "$JS.EVENT.ADVISORY.STREAM.QUORUM_LOST.{0}";
}

/// <summary>
/// Callback signature for system message handlers.
/// Maps to Go's sysMsgHandler type in events.go:109.
/// </summary>
public delegate void SystemMessageHandler(
    Subscription? sub,
    INatsClient? client,
    Account? account,
    string subject,
    string? reply,
    ReadOnlyMemory<byte> headers,
    ReadOnlyMemory<byte> message);
