using System.Collections.Generic;
using System.Linq;
using AssetBank.Editor.SchemaConverter.Data.Input;
using AssetBank.Editor.SchemaConverter.Data.Output;
using AssetBank.Editor.SchemaConverter.Processors;
using Newtonsoft.Json;

namespace AssetBank.Editor.SchemaConverter
{
    /// <summary>
    /// Public-facing static class to orchestrate the JSON schema conversion.
    /// </summary>
    public static class JsonSchemaConverter
    {
        /// <summary>
        /// Converts a raw JSON string from the original format to the new, hierarchical SceneGraph format.
        /// </summary>
        /// <param name="originalJson">The raw JSON string to convert.</param>
        /// <param name="isRecursiveCall">Internal flag to prevent infinite loops when processing prefabs inside prefabs.</param>
        /// <returns>A new JSON string representing the structured SceneGraph.</returns>
        public static string Convert(string originalJson, bool isRecursiveCall = false)
        {
            var sceneGraph = ConvertToSceneGraph(originalJson, isRecursiveCall);
            return JsonConvert.SerializeObject(sceneGraph, Formatting.None);
        }

        /// <summary>
        /// Converts the JSON to a SceneGraph object. This is the core logic.
        /// </summary>
        public static SceneGraph ConvertToSceneGraph(string originalJson, bool isRecursiveCall = false)
        {
            var allNodes = JsonConvert.DeserializeObject<List<OriginalNode>>(originalJson);
            if (allNodes == null) return new SceneGraph();

            var warnings = new List<string>();
            var sceneGraph = new SceneGraph();

            // 1. Process Prefabs first to get a definitive list of all GUIDs.
            var prefabInstanceNodes = allNodes.Where(n => n.type_id == "1001").ToList();
            var (prefabGuids, prefabWarnings) = PrefabProcessor.Process(prefabInstanceNodes);
            if (!isRecursiveCall)
            {
                sceneGraph.prefabs = prefabGuids;
            }
            warnings.AddRange(prefabWarnings);
            
            // 2. Process Hierarchy, passing the prefab GUID list for context.
            var prefabInstanceMap = prefabInstanceNodes.ToDictionary(n => n.anchor_id);
            var hierarchyProcessor = new HierarchyProcessor();
            var (rootNodes, hierarchyWarnings, consumedIds) = hierarchyProcessor.Process(allNodes, prefabInstanceMap, prefabGuids);
            sceneGraph.hierarchy = rootNodes;
            warnings.AddRange(hierarchyWarnings);

            // Also mark all prefab instances themselves as "consumed"
            foreach (var key in prefabInstanceMap.Keys)
            {
                consumedIds.Add(key);
            }

            // 3. Process Scene Data with the remaining, unconsumed nodes
            // sceneGraph.scene_data = SceneDataProcessor.Process(allNodes, consumedIds);
            
            // 4. Assemble Metadata
            sceneGraph.metadata = new Metadata
            {
                warnings = warnings.Count > 0 ? warnings : null
            };

            return sceneGraph;
        }
    }
}
