using TradingBot.Models;
using System.Collections.Concurrent;

namespace TradingBot.Services;

/// <summary>
/// Centralized logging service for application events
/// </summary>
public class LoggingService
{
    private readonly ConcurrentQueue<LogEntry> _logs = new();
    private const int MaxLogEntries = 500;

    public event Action? OnLogAdded;

    /// <summary>
    /// Get all log entries
    /// </summary>
    public IReadOnlyList<LogEntry> GetLogs()
    {
        return _logs.ToList().AsReadOnly();
    }

    /// <summary>
    /// Add a debug log entry
    /// </summary>
    public void LogDebug(string category, string message, string? details = null)
    {
        AddLog(Models.LogLevel.Debug, category, message, details);
    }

    /// <summary>
    /// Add an info log entry
    /// </summary>
    public void LogInfo(string category, string message, string? details = null, string? symbol = null)
    {
        AddLog(Models.LogLevel.Info, category, message, details, symbol);
    }

    /// <summary>
    /// Add a warning log entry
    /// </summary>
    public void LogWarning(string category, string message, string? details = null, string? symbol = null)
    {
        AddLog(Models.LogLevel.Warning, category, message, details, symbol);
    }

    /// <summary>
    /// Add an error log entry
    /// </summary>
    public void LogError(string category, string message, string? details = null, string? symbol = null)
    {
        AddLog(Models.LogLevel.Error, category, message, details, symbol);
    }

    /// <summary>
    /// Add a trade log entry
    /// </summary>
    public void LogTrade(string symbol, string message, string? details = null)
    {
        AddLog(Models.LogLevel.Trade, "Trading", message, details, symbol);
    }

    /// <summary>
    /// Clear all logs
    /// </summary>
    public void ClearLogs()
    {
        _logs.Clear();
        OnLogAdded?.Invoke();
    }

    /// <summary>
    /// Get logs filtered by level
    /// </summary>
    public IReadOnlyList<LogEntry> GetLogsByLevel(Models.LogLevel level)
    {
        return _logs.Where(l => l.Level == level).ToList().AsReadOnly();
    }

    /// <summary>
    /// Get logs filtered by category
    /// </summary>
    public IReadOnlyList<LogEntry> GetLogsByCategory(string category)
    {
        return _logs.Where(l => l.Category.Equals(category, StringComparison.OrdinalIgnoreCase))
            .ToList()
            .AsReadOnly();
    }

    /// <summary>
    /// Get logs filtered by symbol
    /// </summary>
    public IReadOnlyList<LogEntry> GetLogsBySymbol(string symbol)
    {
        return _logs.Where(l => l.Symbol != null && l.Symbol.Equals(symbol, StringComparison.OrdinalIgnoreCase))
            .ToList()
            .AsReadOnly();
    }

    private void AddLog(Models.LogLevel level, string category, string message, string? details = null, string? symbol = null)
    {
        var logEntry = new LogEntry
        {
            Level = level,
            Category = category,
            Message = message,
            Details = details,
            Symbol = symbol
        };

        _logs.Enqueue(logEntry);

        // Maintain max size
        while (_logs.Count > MaxLogEntries)
        {
            _logs.TryDequeue(out _);
        }

        OnLogAdded?.Invoke();
    }
}
