using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Newtonsoft.Json;

namespace MusicBeePlugin.Clouseau.Core
{
    /// <summary>
    /// Session state tracking for Clouseau plugin.
    /// Tracks session timing, event counts, and persists state to JSON.
    /// </summary>
    public class StateManager
    {
        private static readonly string StateFileName = "state.json";
        private readonly string _dataPath;
        private readonly string _stateFilePath;
        private readonly object _lock = new object();

        // Session state
        public DateTime SessionStartTime { get; private set; }
        public DateTime? SessionEndTime { get; private set; }
        public long TotalEventCount { get; private set; }
        public Dictionary<string, long> EventCounts { get; private set; }

        // MusicBee process info
        public DateTime? MusicBeeStartTime { get; private set; }
        public int MusicBeeProcessId { get; private set; }

        // Persisted state
        private ClouseauState _persistedState;

        public StateManager(string dataPath)
        {
            _dataPath = dataPath;
            _stateFilePath = Path.Combine(dataPath, StateFileName);
            EventCounts = new Dictionary<string, long>();

            // Load persisted state
            _persistedState = LoadState();

            // Get MusicBee process info
            try
            {
                var currentProcess = Process.GetCurrentProcess();
                MusicBeeProcessId = currentProcess.Id;
                MusicBeeStartTime = currentProcess.StartTime;
            }
            catch
            {
                MusicBeeProcessId = 0;
                MusicBeeStartTime = null;
            }
        }

        /// <summary>
        /// Start a new session
        /// </summary>
        public void StartSession()
        {
            lock (_lock)
            {
                SessionStartTime = DateTime.Now;
                SessionEndTime = null;
                TotalEventCount = 0;
                EventCounts.Clear();

                // Update persisted state
                _persistedState.TotalSessions++;
                _persistedState.LastSessionStart = SessionStartTime;
                SaveState();

                LogManager.Core.Info($"Session started at {SessionStartTime}");
            }
        }

        /// <summary>
        /// End the current session
        /// </summary>
        public void EndSession()
        {
            lock (_lock)
            {
                SessionEndTime = DateTime.Now;

                // Update persisted state
                _persistedState.LastSessionEnd = SessionEndTime;
                _persistedState.TotalEventsProcessed += TotalEventCount;
                _persistedState.LastEventCounts = new Dictionary<string, long>(EventCounts);
                SaveState();

                var duration = SessionEndTime.Value - SessionStartTime;
                LogManager.Core.Info($"Session ended. Duration: {duration.TotalMinutes:F1} min, Events: {TotalEventCount}");
            }
        }

        /// <summary>
        /// Increment event count for a specific event type
        /// </summary>
        public void IncrementEventCount(string eventType)
        {
            lock (_lock)
            {
                TotalEventCount++;

                if (EventCounts.ContainsKey(eventType))
                {
                    EventCounts[eventType]++;
                }
                else
                {
                    EventCounts[eventType] = 1;
                }

                // Periodic save (every 100 events)
                if (TotalEventCount % 100 == 0)
                {
                    SaveState();
                }
            }
        }

        /// <summary>
        /// Get the count for a specific event type
        /// </summary>
        public long GetEventCount(string eventType)
        {
            lock (_lock)
            {
                return EventCounts.TryGetValue(eventType, out var count) ? count : 0;
            }
        }

        /// <summary>
        /// Get session duration
        /// </summary>
        public TimeSpan GetSessionDuration()
        {
            var endTime = SessionEndTime ?? DateTime.Now;
            return endTime - SessionStartTime;
        }

        /// <summary>
        /// Get events per minute rate
        /// </summary>
        public double GetEventsPerMinute()
        {
            var duration = GetSessionDuration();
            if (duration.TotalMinutes < 0.01) return 0;
            return TotalEventCount / duration.TotalMinutes;
        }

        /// <summary>
        /// Get MusicBee uptime
        /// </summary>
        public TimeSpan? GetMusicBeeUptime()
        {
            if (!MusicBeeStartTime.HasValue) return null;
            return DateTime.Now - MusicBeeStartTime.Value;
        }

        /// <summary>
        /// Load persisted state from JSON file
        /// </summary>
        private ClouseauState LoadState()
        {
            try
            {
                if (File.Exists(_stateFilePath))
                {
                    var json = File.ReadAllText(_stateFilePath);
                    var state = JsonConvert.DeserializeObject<ClouseauState>(json);
                    if (state != null)
                    {
                        return state;
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"Failed to load state: {ex.Message}");
            }

            return new ClouseauState();
        }

        /// <summary>
        /// Save state to JSON file
        /// </summary>
        private void SaveState()
        {
            try
            {
                // Update current session info in persisted state
                _persistedState.CurrentSessionEventCounts = new Dictionary<string, long>(EventCounts);
                _persistedState.CurrentSessionEventCount = TotalEventCount;

                var json = JsonConvert.SerializeObject(_persistedState, Formatting.Indented);
                File.WriteAllText(_stateFilePath, json);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"Failed to save state: {ex.Message}");
            }
        }

        /// <summary>
        /// Get summary of session state
        /// </summary>
        public string GetSessionSummary()
        {
            var duration = GetSessionDuration();
            var eventsPerMin = GetEventsPerMinute();
            var mbUptime = GetMusicBeeUptime();

            return $"Session: {SessionStartTime:HH:mm:ss} | " +
                   $"Duration: {duration.Hours:D2}:{duration.Minutes:D2}:{duration.Seconds:D2} | " +
                   $"Events: {TotalEventCount} ({eventsPerMin:F1}/min)" +
                   (mbUptime.HasValue ? $" | MB Uptime: {mbUptime.Value.Hours:D2}:{mbUptime.Value.Minutes:D2}" : "");
        }

        /// <summary>
        /// Reset all counters
        /// </summary>
        public void Reset()
        {
            lock (_lock)
            {
                TotalEventCount = 0;
                EventCounts.Clear();
                SessionStartTime = DateTime.Now;
                SessionEndTime = null;
                SaveState();
            }
        }

        /// <summary>
        /// Get persisted state info
        /// </summary>
        public ClouseauState GetPersistedState()
        {
            return _persistedState;
        }
    }

    /// <summary>
    /// Persisted state data structure
    /// </summary>
    public class ClouseauState
    {
        public int TotalSessions { get; set; } = 0;
        public long TotalEventsProcessed { get; set; } = 0;
        public DateTime? FirstSessionStart { get; set; }
        public DateTime? LastSessionStart { get; set; }
        public DateTime? LastSessionEnd { get; set; }
        public Dictionary<string, long> LastEventCounts { get; set; } = new Dictionary<string, long>();
        public Dictionary<string, long> CurrentSessionEventCounts { get; set; } = new Dictionary<string, long>();
        public long CurrentSessionEventCount { get; set; } = 0;

        // Cumulative statistics
        public Dictionary<string, long> AllTimeEventCounts { get; set; } = new Dictionary<string, long>();
        public TimeSpan TotalSessionTime { get; set; } = TimeSpan.Zero;

        // Plugin info
        public string PluginVersion { get; set; } = "";
        public string MusicBeeVersion { get; set; } = "";
        public DateTime? LastUpdated { get; set; }
    }
}
