using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using FinlyticCore.Dtos;
using FinlyticCore.Dtos.Bot;
using FinlyticCore.Dtos.News;
using FinlyticCore.Dtos.Settings;
using FinlyticCore.Dtos.Trading;
using FinlyticCore.Models;
using FinlyticCore.Services;
using FinlyticCore.Util;
using FinlyticNotify.Settings;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace FinlyticNotify.Services;
///
/// Managed MQTT client for FinlyticNotify. Listens strictly to existing MQTT broadcast topics,
/// resolves trade ownership, and dispatches rich push notifications via ntfy.
///
public class NotifyMqttClient : ManagedMqttClient, IHostedService
{
private readonly IConfiguration _configuration;
private readonly IServiceScopeFactory _scopeFactory;
private readonly INtfyClient _ntfyClient;
private readonly INotificationFormatter _formatter;
private readonly IUserTradeResolver _userTradeResolver;
private readonly ISettingsService? _settingsService;
private readonly IFinlyticLogger? _finlyticLogger;
private readonly ILogger _logger;
///
/// Initializes a new instance of the class.
///
public NotifyMqttClient(
IConfiguration configuration,
IServiceScopeFactory scopeFactory,
INtfyClient ntfyClient,
INotificationFormatter formatter,
IUserTradeResolver userTradeResolver,
ILogger logger,
ISettingsService? settingsService = null,
IFinlyticLogger? finlyticLogger = null) : base(logger)
{
_configuration = configuration;
_scopeFactory = scopeFactory;
_ntfyClient = ntfyClient;
_formatter = formatter;
_userTradeResolver = userTradeResolver;
_settingsService = settingsService;
_finlyticLogger = finlyticLogger;
_logger = logger;
}
///
public async Task StartAsync(CancellationToken cancellationToken)
{
var config = MqttConfiguration.FromConfiguration(_configuration, "FinlyticNotify");
_logger.LogInformation("[NotifyMqttClient] Starting FinlyticNotify MQTT client (Broker: {Host}:{Port}, ClientId: {ClientId})",
config.Host, config.Port, config.ClientId);
await ConnectAsync(config);
}
///
public async Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("[NotifyMqttClient] Stopping FinlyticNotify MQTT client.");
if (_finlyticLogger != null)
{
await _finlyticLogger.LogInfoAsync(NotifySettingKeys.MqttChannel, "[NotifyMqttClient] Stopping FinlyticNotify MQTT client.");
}
await DisconnectAsync();
}
///
protected override async Task OnConnectedAsync()
{
_logger.LogInformation("[NotifyMqttClient] Connected to MQTT broker. Subscribing to trade event topics...");
await SubscribeAsync(MqttTopics.ResponseWildcard);
// 1. Subscribe to Trade Proposals (New Trades / Setups)
await SubscribeAsync(MqttTopics.EngineProposalsCreated);
// 2. Subscribe to Trade Lifecycle Status Changes (Fills, SL-Updates, TPs, Exits)
await SubscribeAsync(MqttTopics.EngineTradesStatusChanged);
// 3. Subscribe to Bot Paper-Trading Streams
await SubscribeAsync(MqttTopics.BotTradesStream);
// 4. Subscribe to News Status Update requests to capture analyzed news events
await SubscribeAsync(
MqttTopics.RequestFilter(MqttTopics.Channels.NewsUpdateStatus), HandleNewsStatusUpdateRequestAsync);
// 5. Subscribe to Service Health Ping for fleet monitoring
await SubscribeAsync