#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using System.Diagnostics;
using System.Linq;
using IStalk.Core;
using IStalk.Data;
using IStalk.Network;

namespace IStalk.Editor.MapGen
{
    public class MapGenTestWindow : EditorWindow
    {
        private int _seed;
        private int _testCount = 100;
        private string _lastResult;
        private Vector2 _scrollPos;
        private bool _lastTestPassed;

        [MenuItem("IStalk/Map Generation Tester")]
        public static void ShowWindow()
        {
            var window = GetWindow<MapGenTestWindow>("Map Gen Tester");
            window.minSize = new Vector2(380, 500);
        }

        private void OnGUI()
        {
            EditorGUILayout.LabelField("Map Generation Tester", EditorStyles.boldLabel);
            EditorGUILayout.HelpBox("Test procedural map generation without entering Play mode. Use to validate room pool and GlobalRules settings.", MessageType.None);
            EditorGUILayout.Space();

            DrawPreflightCheck();

            EditorGUILayout.Space(10);
            EditorGUILayout.LabelField("Single Generation", EditorStyles.boldLabel);

            EditorGUILayout.BeginHorizontal();
            _seed = EditorGUILayout.IntField("Seed", _seed);
            if (GUILayout.Button("Random", GUILayout.Width(60)))
                _seed = Random.Range(int.MinValue, int.MaxValue);
            EditorGUILayout.EndHorizontal();

            if (GUILayout.Button("Generate Single Map (Preview)", GUILayout.Height(28)))
                GenerateSingle();

            EditorGUILayout.Space(10);
            EditorGUILayout.LabelField("Stress Test", EditorStyles.boldLabel);
            _testCount = EditorGUILayout.IntSlider("Iterations", _testCount, 10, 1000);

            if (GUILayout.Button($"Run {_testCount} Generations (target: 0 failures, <10ms avg)", GUILayout.Height(28)))
                StressTest();

            if (!string.IsNullOrEmpty(_lastResult))
            {
                EditorGUILayout.Space(10);
                _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos, GUILayout.MinHeight(180));
                EditorGUILayout.TextArea(_lastResult, GUILayout.ExpandHeight(true));
                EditorGUILayout.EndScrollView();
            }
        }

        private void DrawPreflightCheck()
        {
            string[] rulesGuids = AssetDatabase.FindAssets("t:GlobalRules_SO");
            var rooms = Resources.LoadAll<RoomNode_SO>("Items/Rooms");

            if (rulesGuids.Length == 0)
            {
                EditorGUILayout.HelpBox("No GlobalRules_SO found! Create one first: IStalk > Create > Global Rules SO", MessageType.Error);
                return;
            }
            if (rooms.Length == 0)
            {
                EditorGUILayout.HelpBox("No RoomNode_SO assets found in Resources/Items/Rooms/. Create rooms first.", MessageType.Error);
                return;
            }

            int withPrefab = rooms.Count(r => r.roomPrefab != null);
            EditorGUILayout.LabelField($"  Room pool: {rooms.Length} rooms ({withPrefab} with prefabs assigned)");
        }

        private void GenerateSingle()
        {
            var rules = FindGlobalRules();
            if (rules == null) return;
            rules.Initialize();

            GameStartData.MapSeed = _seed;

            var go = new GameObject("_TestMapGenerator");
            var gen = go.AddComponent<MapGenerator>();

            var sw = Stopwatch.StartNew();
            gen.Generate();
            sw.Stop();

            bool roomCountOk = gen.PlacedRooms.Count >= rules.minRoomsPerMap && gen.PlacedRooms.Count <= rules.maxRoomsPerMap;
            bool altarCountOk = gen.AltarPositions.Count >= rules.minAltars;
            _lastTestPassed = roomCountOk && altarCountOk;

            _lastResult = $"Single Map — Seed: {_seed}\n" +
                          $"─────────────────────────────\n" +
                          $"Rooms placed: {gen.PlacedRooms.Count} (target: {rules.minRoomsPerMap}–{rules.maxRoomsPerMap}) {(roomCountOk ? "✓" : "✗")}\n" +
                          $"Altars: {gen.AltarPositions.Count} (target: {rules.minAltars}–{rules.maxAltars}) {(altarCountOk ? "✓" : "✗")}\n" +
                          $"Loot slots: {gen.LootSlotPositions.Count}\n" +
                          $"Generation time: {sw.ElapsedMilliseconds}ms\n" +
                          $"Map bounds: {gen.GetMapBounds()}\n\n" +
                          "Room breakdown:\n";

            var categoryCounts = new System.Collections.Generic.Dictionary<RoomCategory, int>();
            foreach (var room in gen.PlacedRooms)
            {
                if (!categoryCounts.ContainsKey(room.Data.category))
                    categoryCounts[room.Data.category] = 0;
                categoryCounts[room.Data.category]++;
            }
            foreach (var kvp in categoryCounts)
                _lastResult += $"  {kvp.Key}: {kvp.Value}\n";

            _lastResult += $"\nVerdict: {(_lastTestPassed ? "PASS" : "ISSUES DETECTED — check room pool")}";


            DestroyImmediate(go);
            Repaint();
        }

        private void StressTest()
        {
            var rules = FindGlobalRules();
            if (rules == null) return;
            rules.Initialize();

            var go = new GameObject("_TestMapGenerator");
            var gen = go.AddComponent<MapGenerator>();

            int failures = 0;
            long totalMs = 0;
            int minRooms = int.MaxValue;
            int maxRooms = 0;

            for (int i = 0; i < _testCount; i++)
            {
                GameStartData.MapSeed = _seed + i;
                var sw = Stopwatch.StartNew();

                try
                {
                    gen.Generate();
                    sw.Stop();
                    totalMs += sw.ElapsedMilliseconds;

                    int count = gen.PlacedRooms.Count;
                    if (count < rules.minRoomsPerMap) failures++;
                    minRooms = Mathf.Min(minRooms, count);
                    maxRooms = Mathf.Max(maxRooms, count);
                }
                catch (System.Exception ex)
                {
                    failures++;
                    UnityEngine.Debug.LogError($"Seed {GameStartData.MapSeed} failed: {ex.Message}");
                }
            }

            DestroyImmediate(go);

            _lastTestPassed = failures == 0;
            string verdict = _lastTestPassed ? "PASS" : "FAIL";
            _lastResult = $"Stress Test Results ({_testCount} iterations) — {verdict}\n" +
                          $"─────────────────────────────\n" +
                          $"Failures: {failures}/{_testCount}\n" +
                          $"Avg time: {totalMs / _testCount}ms\n" +
                          $"Total time: {totalMs}ms\n" +
                          $"Room range: {minRooms}–{maxRooms}\n" +
                          $"Success rate: {((_testCount - failures) * 100f / _testCount):F1}%\n\n" +
                          (failures > 0 ? "Fix: Check room connector directions and GlobalRules min/max room counts." : "All maps generated successfully.");

            Repaint();
        }

        private GlobalRules_SO FindGlobalRules()
        {
            string[] guids = AssetDatabase.FindAssets("t:GlobalRules_SO");
            if (guids.Length == 0)
            {
                EditorUtility.DisplayDialog("Error", "No GlobalRules_SO asset found. Create one via Assets > Create > IStalk > Global Rules.", "OK");
                return null;
            }
            string path = AssetDatabase.GUIDToAssetPath(guids[0]);
            return AssetDatabase.LoadAssetAtPath<GlobalRules_SO>(path);
        }
    }
}
#endif
