// Copyright 2022-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/auth_callout.go in the NATS server Go source.

namespace ZB.MOM.NatsNet.Server.Auth;

/// <summary>
/// External auth callout support.
/// Mirrors Go <c>auth_callout.go</c>.
/// </summary>
internal static class AuthCallout
{
    /// <summary>
    /// Publishes an auth request to the configured callout account and awaits
    /// a signed JWT response that authorises or rejects the connecting client.
    /// Mirrors Go <c>processClientOrLeafCallout</c> in auth_callout.go.
    /// </summary>
    public static bool ProcessClientOrLeafCallout(NatsServer server, ClientConnection c, ServerOptions opts)
    {
        // Full implementation requires internal NATS pub/sub with async request/reply.
        // This is intentionally left as a stub until the internal NATS connection layer is available.
        throw new NotImplementedException(
            "Auth callout requires internal NATS pub/sub — implement when connection layer is available.");
    }

    /// <summary>
    /// Populates an authorization request payload with client connection info.
    /// Mirrors Go <c>client.fillClientInfo</c> in auth_callout.go.
    /// </summary>
    public static void FillClientInfo(AuthorizationRequest req, ClientConnection c)
    {
        req.ClientInfoObj = new AuthorizationClientInfo
        {
            Host = c.Host,
            Id   = c.Cid,
            Kind = c.Kind.ToString().ToLowerInvariant(),
            Type = "client",
        };
    }

    /// <summary>
    /// Populates an authorization request payload with connect options.
    /// Mirrors Go <c>client.fillConnectOpts</c> in auth_callout.go.
    /// </summary>
    public static void FillConnectOpts(AuthorizationRequest req, ClientConnection c)
    {
        req.ConnectOptions = new AuthorizationConnectOpts
        {
            Username  = c.GetUsername(),
            Password  = c.GetPassword(),
            AuthToken = c.GetAuthToken(),
            Nkey      = c.GetNkey(),
        };
    }
}

/// <summary>Authorization request sent to auth callout service.</summary>
public sealed class AuthorizationRequest
{
    public string ServerId   { get; set; } = string.Empty;
    public string UserNkey   { get; set; } = string.Empty;
    public AuthorizationClientInfo?  ClientInfoObj  { get; set; }
    public AuthorizationConnectOpts? ConnectOptions { get; set; }
}

/// <summary>Client info portion of an authorization request.</summary>
public sealed class AuthorizationClientInfo
{
    public string Host { get; set; } = string.Empty;
    public ulong  Id   { get; set; }
    public string Kind { get; set; } = string.Empty;
    public string Type { get; set; } = string.Empty;
}

/// <summary>Connect options portion of an authorization request.</summary>
public sealed class AuthorizationConnectOpts
{
    public string Username  { get; set; } = string.Empty;
    public string Password  { get; set; } = string.Empty;
    public string AuthToken { get; set; } = string.Empty;
    public string Nkey      { get; set; } = string.Empty;
}
