using Predictalytics.Application.DTOs;
using Predictalytics.Application.Interfaces;
using Predictalytics.Domain.Entities;
using Predictalytics.Domain.Enums;
using Predictalytics.Domain.Interfaces;
using Microsoft.Extensions.Logging;

namespace Predictalytics.Application.Services;

/// <summary>
/// Alert evaluation and management service.
/// </summary>
public class AlertService : IAlertService
{
    private readonly IAlertRepository _alertRepo;
    private readonly ITradeRepository _tradeRepo;
    private readonly ITraderRepository _traderRepo;
    private readonly ILogger<AlertService> _logger;

    // Alert thresholds (configurable in future)
    private const decimal LargePositionThresholdUsd = 5000m;

    public AlertService(
        IAlertRepository alertRepo,
        ITradeRepository tradeRepo,
        ITraderRepository traderRepo,
        ILogger<AlertService> logger)
    {
        _alertRepo = alertRepo;
        _tradeRepo = tradeRepo;
        _traderRepo = traderRepo;
        _logger = logger;
    }

    public async Task EvaluateAlertsAsync(CancellationToken ct = default)
    {
        _logger.LogDebug("Evaluating alert rules...");

        // Check for large recent trades
        var recentTrades = await _tradeRepo.GetRecentAsync(100, ct: ct);
        var thirtyMinAgo = DateTime.UtcNow.AddMinutes(-30);

        foreach (var trade in recentTrades.Where(t => t.ExecutedAt > thirtyMinAgo))
        {
            if (trade.Amount >= LargePositionThresholdUsd)
            {
                var trader = await _traderRepo.GetByIdAsync(trade.TraderId, ct);
                var marketRef = trade.DbMarketId.HasValue
                    ? $"Market #{trade.DbMarketId}"
                    : (!string.IsNullOrEmpty(trade.MarketId) ? $"Market {trade.MarketId[..Math.Min(12, trade.MarketId.Length)]}..." : "Unknown Market");
                await CreateAlertAsync(new Alert
                {
                    Type = AlertType.LargePosition,
                    Platform = trade.Platform,
                    TraderId = trade.TraderId,
                    Title = $"Large {trade.Side} detected",
                    Message = $"{trader?.DisplayName ?? "Unknown"} {trade.Side} ${trade.Amount:N0} on {marketRef} ({trade.Outcome} @ {trade.Price:P0})",
                    Severity = trade.Amount >= 25000 ? 4 : trade.Amount >= 10000 ? 3 : 2
                }, ct);
            }
        }
    }

    public async Task CreateAlertAsync(Alert alert, CancellationToken ct = default)
    {
        await _alertRepo.AddAsync(alert, ct);
        _logger.LogInformation("🔔 Alert [{Type}]: {Title}", alert.Type, alert.Title);
    }

    public async Task<IReadOnlyList<AlertDto>> GetRecentAlertsAsync(int count = 50, bool unreadOnly = false, CancellationToken ct = default)
    {
        var alerts = await _alertRepo.GetRecentAsync(count, unreadOnly, ct);
        var result = new List<AlertDto>();

        foreach (var a in alerts)
        {
            string? traderName = null;
            if (a.TraderId.HasValue)
            {
                var trader = await _traderRepo.GetByIdAsync(a.TraderId.Value, ct);
                traderName = trader?.DisplayName;
            }

            result.Add(new AlertDto(
                a.Id, a.Type.ToString(), a.Platform.ToString(),
                a.Title, a.Message, a.Severity, a.IsRead, a.CreatedAt, traderName));
        }

        return result;
    }

    public async Task MarkAsReadAsync(int alertId, CancellationToken ct = default)
    {
        await _alertRepo.MarkAsReadAsync(alertId, ct);
    }
}
