using System.IO;
using UnityEngine;
using Newtonsoft.Json;

namespace IntelligentProjectAnalyzer.Helper
{
    /// <summary>
    /// A utility class for writing serializable objects to JSON files using Newtonsoft JSON.
    /// </summary>
    public static class JsonFileSystem
    {
        /// <summary>
        /// Writes a serializable object to a JSON file at a specified path.
        /// </summary>
        /// <typeparam name="T">The type of the data object to serialize.</typeparam>
        /// <param name="data">The object to serialize.</param>
        /// <param name="fullPath">The absolute path where the file will be saved.</param>
        /// <param name="prettyPrint">If true, the JSON will be formatted for human readability.</param>
        /// <param name="debugLogJson">If true, the generated JSON content will be logged to the console.</param>
        public static void Write<T>(T data, string fullPath, bool prettyPrint = false, bool debugLogJson = false)
        {
            if (data == null)
            {
                Debug.LogError("[JsonFileSystem] The data object provided is null. Cannot write file.");
                return;
            }

            if (string.IsNullOrEmpty(fullPath))
            {
                Debug.LogError("[JsonFileSystem] The full path provided is null or empty. Cannot write file.");
                return;
            }

            try
            {
                // Ensure the output directory exists.
                var outputDirectory = Path.GetDirectoryName(fullPath);
                if (!string.IsNullOrEmpty(outputDirectory) && !Directory.Exists(outputDirectory))
                {
                    Directory.CreateDirectory(outputDirectory);
                }

                // Serialize the object to a JSON string using Newtonsoft JSON
                var json = GetJson(data, prettyPrint);

                // Optionally, log the JSON to the console for debugging.
                if (debugLogJson)
                {
                    var fileName = Path.GetFileName(fullPath);
                    Debug.Log($"[JsonFileSystem] JSON content for '{fileName}':\n{json}");
                }

                // Write the JSON string to the file.
                File.WriteAllText(fullPath, json);

                // Log a clickable link to the created file.
                Debug.Log($"[JsonFileSystem] Successfully wrote file to: <a href=\"{fullPath}\">{fullPath}</a>");
            }
            catch (System.Exception e)
            {
                // Catch any potential exceptions during file I/O or serialization.
                Debug.LogError($"[JsonFileSystem] An error occurred while writing file at '{fullPath}'.\nException: {e.Message}");
            }
        }

        public static string GetJson(object data, bool prettyPrint = false)
        {
            // Configure JSON serialization settings
            var settings = new JsonSerializerSettings
            {
                Formatting = prettyPrint ? Formatting.Indented : Formatting.None,
                NullValueHandling = NullValueHandling.Ignore,
                DefaultValueHandling = DefaultValueHandling.Include,
                TypeNameHandling = TypeNameHandling.Auto, // This handles derived classes
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            };
            var json = JsonConvert.SerializeObject(data, settings);
            return json;
        } 

        /// <summary>
        /// Reads and deserializes a JSON file.
        /// </summary>
        /// <typeparam name="T">The type to deserialize to.</typeparam>
        /// <param name="fullPath">The absolute path to the JSON file.</param>
        /// <returns>The deserialized object, or default(T) if failed.</returns>
        public static T Read<T>(string fullPath)
        {
            if (string.IsNullOrEmpty(fullPath) || !File.Exists(fullPath))
            {
                Debug.LogError($"[JsonFileSystem] File not found: {fullPath}");
                return default;
            }

            try
            {
                var json = File.ReadAllText(fullPath);
                var settings = new JsonSerializerSettings
                {
                    TypeNameHandling = TypeNameHandling.Auto,
                    NullValueHandling = NullValueHandling.Ignore
                };

                return JsonConvert.DeserializeObject<T>(json, settings);
            }
            catch (System.Exception e)
            {
                Debug.LogError($"[JsonFileSystem] Error reading file '{fullPath}': {e.Message}");
                return default;
            }
        }
        
        public static object Read(string data, System.Type type)
        {
            if (string.IsNullOrEmpty(data))
            {
                Debug.LogError($"[JsonFileSystem] Data is null or empty");
                return null;
            }

            try
            {
                var settings = new JsonSerializerSettings
                {
                    TypeNameHandling = TypeNameHandling.Auto,
                    NullValueHandling = NullValueHandling.Ignore
                };
                
                return JsonConvert.DeserializeObject(data, type, settings);
            }
            catch (System.Exception e)
            {
                Debug.LogError($"[JsonFileSystem] Error reading passed data '{data}': {e.Message}");
                return null;
            }
        }
    }
}