#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using IStalk.Data;
using IStalk.EditorTools.MapGen;

namespace IStalk.Editor.MapGen
{
    public class RoomValidator : EditorWindow
    {
        private Vector2 _scrollPos;
        private List<ValidationResult> _results = new();
        private int _errorCount;
        private int _warningCount;
        private int _passCount;

        [MenuItem("IStalk/Room Validator")]
        public static void ShowWindow()
        {
            var window = GetWindow<RoomValidator>("Room Validator");
            window.minSize = new Vector2(400, 350);
        }

        private void OnGUI()
        {
            EditorGUILayout.LabelField("Room Validator", EditorStyles.boldLabel);
            EditorGUILayout.HelpBox("Validates all RoomNode_SO assets against their assigned prefabs. Run after editing any room.", MessageType.None);
            EditorGUILayout.Space();

            EditorGUILayout.BeginHorizontal();
            if (GUILayout.Button("Validate All Rooms", GUILayout.Height(28)))
                ValidateAll();
            if (GUILayout.Button("Validate Selected", GUILayout.Height(28)))
                ValidateSelected();
            if (GUILayout.Button("Auto-Fix All IDs", GUILayout.Height(28)))
                AutoFixIds();
            EditorGUILayout.EndHorizontal();

            if (_results.Count > 0)
            {
                EditorGUILayout.Space(5);
                EditorGUILayout.LabelField($"Results: {_errorCount} errors, {_warningCount} warnings, {_passCount} passed",
                    _errorCount > 0 ? EditorStyles.boldLabel : EditorStyles.label);
            }

            EditorGUILayout.Space();
            DrawResults();
        }

        private void AutoFixIds()
        {
            var rooms = Resources.LoadAll<RoomNode_SO>("Items/Rooms");
            int fixed_ = 0;
            foreach (var room in rooms)
            {
                if (string.IsNullOrEmpty(room.roomId))
                {
                    Undo.RecordObject(room, "Auto-Fix Room ID");
                    room.roomId = room.name.Replace(" ", "_").ToLower();
                    EditorUtility.SetDirty(room);
                    fixed_++;
                }
            }
            Debug.Log($"[RoomValidator] Auto-fixed {fixed_} room IDs.");
            ValidateAll();
        }

        private void ValidateAll()
        {
            _results.Clear();
            var rooms = Resources.LoadAll<RoomNode_SO>("Items/Rooms");

            foreach (var room in rooms)
                _results.AddRange(ValidateRoom(room));

            _errorCount = _results.Count(r => r.Severity == MessageType.Error);
            _warningCount = _results.Count(r => r.Severity == MessageType.Warning);
            _passCount = _results.Count(r => r.Severity == MessageType.Info);
            Debug.Log($"[RoomValidator] Validated {rooms.Length} rooms: {_errorCount} errors, {_warningCount} warnings, {_passCount} passed");
        }

        private void ValidateSelected()
        {
            _results.Clear();
            var selected = Selection.activeObject as RoomNode_SO;
            if (selected == null)
            {
                EditorUtility.DisplayDialog("Room Validator", "Select a RoomNode_SO asset in the Project window first.", "OK");
                return;
            }
            _results.AddRange(ValidateRoom(selected));
            _errorCount = _results.Count(r => r.Severity == MessageType.Error);
            _warningCount = _results.Count(r => r.Severity == MessageType.Warning);
            _passCount = _results.Count(r => r.Severity == MessageType.Info);
        }

        private List<ValidationResult> ValidateRoom(RoomNode_SO room)
        {
            var results = new List<ValidationResult>();
            string ctx = room.roomId ?? room.name;

            if (string.IsNullOrEmpty(room.roomId))
                results.Add(new ValidationResult(ctx, "Room ID is empty", MessageType.Error));

            if (room.roomPrefab == null)
            {
                results.Add(new ValidationResult(ctx, "No prefab assigned", MessageType.Error));
                return results;
            }

            var connectors = room.roomPrefab.GetComponentsInChildren<ConnectorMarker>(true);
            var slots = room.roomPrefab.GetComponentsInChildren<SpawnSlot>(true);
            var bounds = room.roomPrefab.GetComponentInChildren<RoomBounds>(true);

            if (connectors.Length == 0)
                results.Add(new ValidationResult(ctx, "Prefab has no ConnectorMarker components", MessageType.Error));

            if (bounds == null)
                results.Add(new ValidationResult(ctx, "Prefab has no RoomBounds component", MessageType.Warning));
            else if (bounds.gridSize != room.gridSize)
                results.Add(new ValidationResult(ctx, $"RoomBounds gridSize ({bounds.gridSize}) != SO gridSize ({room.gridSize})", MessageType.Warning));

            var soConnections = room.openConnections;
            var prefabConnections = connectors.Select(c => c.connectionDirection).Distinct().ToList();
            foreach (var dir in soConnections)
            {
                if (!prefabConnections.Contains(dir))
                    results.Add(new ValidationResult(ctx, $"SO declares {dir} connection but prefab has no marker for it", MessageType.Error));
            }
            foreach (var dir in prefabConnections)
            {
                if (!soConnections.Contains(dir))
                    results.Add(new ValidationResult(ctx, $"Prefab has {dir} marker but SO doesn't declare it", MessageType.Warning));
            }

            int lootSlots = slots.Count(s => s.slotType == SpawnSlotType.LootItem);
            if (lootSlots != room.lootSpawnSlots)
                results.Add(new ValidationResult(ctx, $"Loot slots mismatch: prefab={lootSlots}, SO={room.lootSpawnSlots}", MessageType.Warning));

            if (results.Count == 0)
                results.Add(new ValidationResult(ctx, "PASS — all checks OK", MessageType.Info));

            return results;
        }

        private void DrawResults()
        {
            _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos);
            foreach (var result in _results)
            {
                EditorGUILayout.HelpBox($"[{result.RoomId}] {result.Message}", result.Severity);
            }
            EditorGUILayout.EndScrollView();
        }

        private struct ValidationResult
        {
            public string RoomId;
            public string Message;
            public MessageType Severity;

            public ValidationResult(string roomId, string message, MessageType severity)
            {
                RoomId = roomId;
                Message = message;
                Severity = severity;
            }
        }
    }
}
#endif
