// Copyright 2012-2026 The NATS Authors
// Licensed under the Apache License, Version 2.0 (the "License");

using ZB.MOM.NatsNet.Server.Internal;
using System.IO;

namespace ZB.MOM.NatsNet.Server;

public sealed partial class NatsServer
{
    internal void SendSubsToRoute(ClientConnection route, int idx, string account)
    {
        if (route == null)
            return;

        var allSubs = new List<Subscription>(1024);
        if (idx < 0 || !string.IsNullOrEmpty(account))
        {
            var (acc, _) = LookupAccount(account);
            acc?.Sublist?.LocalSubs(allSubs, includeLeafHubs: false);
        }
        else
        {
            foreach (var acc in _accounts.Values)
            {
                if (acc.RoutePoolIdx != idx)
                    continue;
                acc.Sublist?.LocalSubs(allSubs, includeLeafHubs: false);
            }
        }

        route.SendRouteSubProtos(allSubs, trace: false, sub => route.CanImport(System.Text.Encoding.ASCII.GetString(sub.Subject)));
    }

    internal ClientConnection? CreateRoute(Stream? conn, Uri? routeUrl, RouteType routeType, byte gossipMode, string accName)
    {
        var opts = GetOpts();
        var didSolicit = routeUrl != null;
        var c = new ClientConnection(ClientKind.Router, this, conn ?? new MemoryStream())
        {
            Opts = ClientOptions.Default,
            Route = new Route
            {
                Url = routeUrl,
                RouteType = routeType,
                DidSolicit = didSolicit,
                PoolIdx = -1,
                GossipMode = gossipMode,
                AccName = string.IsNullOrEmpty(accName) ? null : System.Text.Encoding.ASCII.GetBytes(accName),
            },
            Start = DateTime.UtcNow,
        };

        lock (c)
        {
            c.InitClient();
            if (didSolicit)
                c.SetRoutePermissions(opts.Cluster.Permissions);
            c.SetFirstPingTimer();
        }

        if (didSolicit)
        {
            var sendErr = c.SendRouteConnect(_info.Cluster ?? string.Empty, _routeInfo.TlsRequired);
            if (sendErr != null)
            {
                c.CloseConnection(ClosedState.ProtocolViolation);
                return null;
            }
        }

        return c;
    }
}
