using System.Collections.Generic;
using System.IO;
using UnityEngine;

namespace JebAI
{
    /// <summary>
    /// Saves and loads mission memories plus recent per-interaction outputs per Kerbal.
    /// </summary>
    public static class KerbalMemory
    {
        private const int MaxMemories = 10;
        private const int MaxRecentOutputsPerType = 3;
        private static readonly string SavePath = Path.Combine(
            KSPUtil.ApplicationRootPath, "GameData", "JebAI", "PluginData", "memories.cfg");

        private static readonly Dictionary<string, List<string>> _store = new Dictionary<string, List<string>>();
        private static readonly Dictionary<string, Dictionary<string, List<string>>> _recentOutputs =
            new Dictionary<string, Dictionary<string, List<string>>>();
        private static bool _loaded = false;

        public static void EnsureLoaded()
        {
            if (_loaded) return;
            Load();
            _loaded = true;
        }

        public static void AddMemory(string kerbalName, string memory)
        {
            EnsureLoaded();
            if (!_store.ContainsKey(kerbalName))
                _store[kerbalName] = new List<string>();

            _store[kerbalName].Add(memory);
            Trim(_store[kerbalName], MaxMemories);
            Save();
        }

        public static string GetMemorySummary(string kerbalName)
        {
            EnsureLoaded();
            if (!_store.ContainsKey(kerbalName) || _store[kerbalName].Count == 0)
                return "No notable experiences yet.";
            return string.Join(" ", _store[kerbalName]);
        }

        public static void AddRecentOutput(string kerbalName, InteractionType type, string output)
        {
            EnsureLoaded();
            if (string.IsNullOrWhiteSpace(output)) return;

            string bucket = type.ToString();
            if (!_recentOutputs.TryGetValue(kerbalName, out Dictionary<string, List<string>> perType))
            {
                perType = new Dictionary<string, List<string>>();
                _recentOutputs[kerbalName] = perType;
            }

            if (!perType.TryGetValue(bucket, out List<string> outputs))
            {
                outputs = new List<string>();
                perType[bucket] = outputs;
            }

            outputs.Add(output.Trim());
            Trim(outputs, MaxRecentOutputsPerType);
            Save();
        }

        public static string GetRecentOutputSummary(string kerbalName, InteractionType type)
        {
            EnsureLoaded();

            if (!_recentOutputs.TryGetValue(kerbalName, out Dictionary<string, List<string>> perType))
                return null;

            if (!perType.TryGetValue(type.ToString(), out List<string> outputs) || outputs.Count == 0)
                return null;

            return string.Join(" || ", outputs.ToArray());
        }

        public static void ClearKerbal(string kerbalName)
        {
            _store.Remove(kerbalName);
            _recentOutputs.Remove(kerbalName);
            Save();
        }

        private static void Load()
        {
            _store.Clear();
            _recentOutputs.Clear();

            if (!File.Exists(SavePath))
            {
                Debug.Log("[JebAI] No memories file found - starting fresh.");
                return;
            }

            try
            {
                ConfigNode root = ConfigNode.Load(SavePath);
                if (root == null) return;

                foreach (ConfigNode kerbalNode in root.GetNodes("KERBAL"))
                {
                    string name = kerbalNode.GetValue("name");
                    if (string.IsNullOrEmpty(name)) continue;

                    var memories = new List<string>();
                    foreach (string memory in kerbalNode.GetValues("memory"))
                    {
                        if (!string.IsNullOrEmpty(memory))
                            memories.Add(memory);
                    }
                    if (memories.Count > 0)
                        _store[name] = memories;

                    foreach (ConfigNode outputNode in kerbalNode.GetNodes("RECENT_OUTPUT"))
                    {
                        string type = outputNode.GetValue("type");
                        if (string.IsNullOrEmpty(type)) continue;

                        var outputs = new List<string>();
                        foreach (string output in outputNode.GetValues("output"))
                        {
                            if (!string.IsNullOrEmpty(output))
                                outputs.Add(output);
                        }

                        if (outputs.Count == 0) continue;
                        Trim(outputs, MaxRecentOutputsPerType);

                        if (!_recentOutputs.TryGetValue(name, out Dictionary<string, List<string>> perType))
                        {
                            perType = new Dictionary<string, List<string>>();
                            _recentOutputs[name] = perType;
                        }

                        perType[type] = outputs;
                    }
                }
            }
            catch (System.Exception e)
            {
                Debug.LogError($"[JebAI] Failed to load memories: {e.Message}");
            }
        }

        private static void Save()
        {
            try
            {
                Directory.CreateDirectory(Path.GetDirectoryName(SavePath));

                var root = new ConfigNode("JEBAI_MEMORIES");
                var allNames = new HashSet<string>(_store.Keys);
                foreach (string name in _recentOutputs.Keys)
                    allNames.Add(name);

                foreach (string name in allNames)
                {
                    ConfigNode node = root.AddNode("KERBAL");
                    node.AddValue("name", name);

                    if (_store.TryGetValue(name, out List<string> memories))
                    {
                        foreach (string memory in memories)
                            node.AddValue("memory", memory);
                    }

                    if (_recentOutputs.TryGetValue(name, out Dictionary<string, List<string>> perType))
                    {
                        foreach (KeyValuePair<string, List<string>> pair in perType)
                        {
                            ConfigNode outputNode = node.AddNode("RECENT_OUTPUT");
                            outputNode.AddValue("type", pair.Key);
                            foreach (string output in pair.Value)
                                outputNode.AddValue("output", output);
                        }
                    }
                }

                root.Save(SavePath);
            }
            catch (System.Exception e)
            {
                Debug.LogError($"[JebAI] Failed to save memories: {e.Message}");
            }
        }

        private static void Trim(List<string> items, int maxCount)
        {
            while (items.Count > maxCount)
                items.RemoveAt(0);
        }
    }
}
