using System;
using System.Collections.Generic;
using System.Threading;

namespace MusicBeePlugin.Clouseau.Logging
{
    /// <summary>
    /// Represents a structured log entry for MusicBee events.
    /// Thread-safe for sequence number generation; entries should be
    /// fully constructed before being shared across threads.
    /// </summary>
    public class LogEntry
    {
        private static long _sequenceCounter = 0;

        /// <summary>
        /// The timestamp when this event occurred.
        /// </summary>
        public DateTime Timestamp { get; set; }

        /// <summary>
        /// A monotonically increasing sequence number for ordering events.
        /// </summary>
        public long SequenceNumber { get; set; }

        /// <summary>
        /// The category of the event (Core, Player, Queue, Library, Tags, Playlist, Download, UI, System).
        /// </summary>
        public string Category { get; set; }

        /// <summary>
        /// The NotificationType name (e.g., "TrackChanged", "PlayStateChanged").
        /// </summary>
        public string EventType { get; set; }

        /// <summary>
        /// The numeric value of the NotificationType enum.
        /// </summary>
        public int EventTypeValue { get; set; }

        /// <summary>
        /// The log level (Info, Debug, Warn, Error).
        /// </summary>
        public string Level { get; set; }

        /// <summary>
        /// The currently playing file path, if applicable.
        /// </summary>
        public string SourceFile { get; set; }

        /// <summary>
        /// Human-readable description of the event.
        /// </summary>
        public string Message { get; set; }

        /// <summary>
        /// Rich context data specific to the event type.
        /// </summary>
        public Dictionary<string, object> Context { get; set; }

        /// <summary>
        /// Creates a new LogEntry with default values.
        /// </summary>
        public LogEntry()
        {
            Timestamp = DateTime.Now;
            Context = new Dictionary<string, object>();
            Level = "Info";
            SequenceNumber = Interlocked.Increment(ref _sequenceCounter);
        }

        /// <summary>
        /// Creates a new LogEntry with the specified values.
        /// </summary>
        /// <param name="category">The event category.</param>
        /// <param name="eventType">The NotificationType name.</param>
        /// <param name="eventTypeValue">The numeric value of the NotificationType.</param>
        /// <param name="message">Human-readable description.</param>
        /// <param name="level">Log level (defaults to "Info").</param>
        public LogEntry(string category, string eventType, int eventTypeValue, string message, string level = "Info")
            : this()
        {
            Category = category;
            EventType = eventType;
            EventTypeValue = eventTypeValue;
            Message = message;
            Level = level;
        }

        /// <summary>
        /// Adds context data to the log entry.
        /// </summary>
        /// <param name="key">The context key.</param>
        /// <param name="value">The context value.</param>
        /// <returns>This LogEntry for fluent chaining.</returns>
        public LogEntry WithContext(string key, object value)
        {
            if (Context == null)
            {
                Context = new Dictionary<string, object>();
            }
            Context[key] = value;
            return this;
        }

        /// <summary>
        /// Sets the source file for this log entry.
        /// </summary>
        /// <param name="sourceFile">The file path.</param>
        /// <returns>This LogEntry for fluent chaining.</returns>
        public LogEntry WithSourceFile(string sourceFile)
        {
            SourceFile = sourceFile;
            return this;
        }

        /// <summary>
        /// Sets the log level for this entry.
        /// </summary>
        /// <param name="level">The log level.</param>
        /// <returns>This LogEntry for fluent chaining.</returns>
        public LogEntry WithLevel(string level)
        {
            Level = level;
            return this;
        }

        /// <summary>
        /// Returns a string representation of this log entry.
        /// </summary>
        public override string ToString()
        {
            var sourceInfo = string.IsNullOrEmpty(SourceFile) ? "" : $" [{SourceFile}]";
            return $"[{Timestamp:HH:mm:ss.fff}] [{Level}] [{Category}] {EventType}: {Message}{sourceInfo}";
        }

        /// <summary>
        /// Resets the sequence counter. Useful for testing.
        /// </summary>
        internal static void ResetSequenceCounter()
        {
            Interlocked.Exchange(ref _sequenceCounter, 0);
        }
    }

    /// <summary>
    /// Log level constants for consistency.
    /// </summary>
    public static class LogLevel
    {
        public const string Debug = "Debug";
        public const string Info = "Info";
        public const string Warn = "Warn";
        public const string Error = "Error";
    }

    /// <summary>
    /// Event category constants for MusicBee notifications.
    /// </summary>
    public static class EventCategory
    {
        public const string Core = "Core";
        public const string Player = "Player";
        public const string Queue = "Queue";
        public const string Library = "Library";
        public const string Tags = "Tags";
        public const string Playlist = "Playlist";
        public const string Download = "Download";
        public const string UI = "UI";
        public const string System = "System";
        public const string Sync = "Sync";
    }
}
