using System.Security.Cryptography;
using NATS.Server.Auth;

namespace NATS.Server.Imports;

/// <summary>
/// Handles response routing for service imports.
/// Maps to Go's service reply prefix generation and response cleanup.
/// Reference: golang/nats-server/server/accounts.go — addRespServiceImport, removeRespServiceImport
/// </summary>
public static class ResponseRouter
{
    private static readonly char[] Base62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".ToCharArray();

    /// <summary>
    /// Generates a unique reply prefix for response routing.
    /// Format: "_R_.{10 random base62 chars}."
    /// </summary>
    public static string GenerateReplyPrefix()
    {
        Span<byte> bytes = stackalloc byte[10];
        RandomNumberGenerator.Fill(bytes);
        var chars = new char[10];
        for (int i = 0; i < 10; i++)
            chars[i] = Base62[bytes[i] % 62];
        return $"_R_.{new string(chars)}.";
    }

    /// <summary>
    /// Creates a response service import that maps the generated reply prefix
    /// back to the original reply subject on the requesting account.
    /// </summary>
    public static ServiceImport CreateResponseImport(
        Account exporterAccount,
        ServiceImport originalImport,
        string originalReply)
    {
        var replyPrefix = GenerateReplyPrefix();

        var responseSi = new ServiceImport
        {
            DestinationAccount = exporterAccount,
            From = replyPrefix + ">",
            To = originalReply,
            IsResponse = true,
            ResponseType = originalImport.ResponseType,
            Export = originalImport.Export,
            TimestampTicks = DateTime.UtcNow.Ticks,
        };

        exporterAccount.Exports.Responses[replyPrefix] = responseSi;
        return responseSi;
    }

    /// <summary>
    /// Removes a response import from the account's export map.
    /// For Singleton responses, this is called after the first reply is delivered.
    /// For Streamed/Chunked, it is called when the response stream ends.
    /// </summary>
    public static void CleanupResponse(Account account, string replyPrefix, ServiceImport responseSi)
    {
        account.Exports.Responses.Remove(replyPrefix);
    }
}
