// Copyright 2020-2026 The NATS Authors
// Licensed under the Apache License, Version 2.0

using System.Text.Json;

namespace ZB.MOM.NatsNet.Server;

public sealed partial class NatsServer
{
    internal bool PublishAdvisory(Account? acc, string subject, object advisory) =>
        PublishAdvisory(acc, subject, advisory, SendInternalAccountMsg);

    internal bool PublishAdvisory(
        Account? acc,
        string subject,
        object advisory,
        Func<Account, string, byte[], Exception?> sendInternalAccountMessage,
        Func<Account, string, bool>? hasGatewayInterest = null)
    {
        ArgumentNullException.ThrowIfNull(sendInternalAccountMessage);

        var account = acc ?? SystemAccount();
        if (account is null)
        {
            return false;
        }

        var sublist = account.Sublist;
        var gatewayInterestCheck = hasGatewayInterest ?? HasGatewayInterest;
        var hasLocalInterest = sublist != null && sublist.HasInterest(subject);
        if (!hasLocalInterest && !gatewayInterestCheck(account, subject))
        {
            return false;
        }

        byte[] payload;
        try
        {
            payload = JsonSerializer.SerializeToUtf8Bytes(advisory);
        }
        catch (Exception ex)
        {
            Warnf("Advisory could not be serialized for account {0}: {1}", account.Name, ex);
            return false;
        }

        Exception? err;
        try
        {
            err = sendInternalAccountMessage(account, subject, payload);
        }
        catch (Exception ex)
        {
            err = ex;
        }

        if (err != null)
        {
            Warnf("Advisory could not be sent for account {0}: {1}", account.Name, err);
            return false;
        }

        return true;
    }

    internal Exception? SendInternalAccountMsg(Account account, string subject, byte[] message)
    {
        try
        {
            var sendQueue = account.GetSendQueue() ?? NewSendQueue(account);
            SendQueue.Send(sendQueue, subject, string.Empty, [], message);
            return null;
        }
        catch (Exception ex)
        {
            return ex;
        }
    }

    internal bool HasGatewayInterest(Account account, string subject)
    {
        _ = account;
        _ = subject;
        return false;
    }
}
