using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ChillConnect;

public class ArrowLevelAutoGenerator : EditorWindow
{
    // ----- 参数 -----
    private int _levelCount = 10;
    private bool _autoSizeByDifficulty = true;
    private int _gridRows = 8;
    private int _gridCols = 8;
    private int _pointSpacing = 60;
    private Difficulty _difficulty = Difficulty.Hard;
    private GenerationMode _mode = GenerationMode.Random;
    private PatternType _pattern = PatternType.Heart;
    private bool _randomPattern = false;
    private string _outputFileName = "all_levels.json";

    private enum Difficulty { Easy, Medium, Hard }
    private enum GenerationMode { Random, Pattern }
    private enum PatternType { Heart, Star, LetterA, Diamond, Circle, XShape, Random }

    [MenuItem("Tools/Arrow Level Auto Generator")]
    public static void ShowWindow()
    {
        GetWindow<ArrowLevelAutoGenerator>("自动生成关卡");
    }

    private void OnGUI()
    {
        GUILayout.Label("自动化关卡生成器", EditorStyles.boldLabel);
        EditorGUILayout.Space();

        _levelCount = EditorGUILayout.IntField("关卡数量", _levelCount);
        _autoSizeByDifficulty = EditorGUILayout.Toggle("根据难度自动调整网格尺寸", _autoSizeByDifficulty);
        if (!_autoSizeByDifficulty)
        {
            _gridRows = EditorGUILayout.IntField("网格行数", _gridRows);
            _gridCols = EditorGUILayout.IntField("网格列数", _gridCols);
        }
        else
        {
            EditorGUILayout.HelpBox("网格尺寸：简单6×6，中等8×8，困难34×21", MessageType.Info);
        }

        _pointSpacing = EditorGUILayout.IntField("点间距", _pointSpacing);
        _difficulty = (Difficulty)EditorGUILayout.EnumPopup("难度", _difficulty);
        _mode = (GenerationMode)EditorGUILayout.EnumPopup("生成模式", _mode);

        if (_mode == GenerationMode.Pattern)
        {
            _randomPattern = EditorGUILayout.Toggle("随机图案", _randomPattern);
            if (!_randomPattern)
            {
                _pattern = (PatternType)EditorGUILayout.EnumPopup("指定图案", _pattern);
            }
        }

        _outputFileName = EditorGUILayout.TextField("输出文件名", _outputFileName);

        EditorGUILayout.Space();
        if (GUILayout.Button("生成关卡", GUILayout.Height(40)))
        {
            GenerateLevels();
        }
    }

    private void GenerateLevels()
    {
        if (_levelCount <= 0)
        {
            EditorUtility.DisplayDialog("错误", "关卡数量必须大于0", "确定");
            return;
        }

        List<LevelConfig> levels = new List<LevelConfig>();

        for (int i = 0; i < _levelCount; i++)
        {
            LevelConfig lv = null;
            int rows, cols;
            if (_autoSizeByDifficulty)
                GetSizeByDifficulty(out rows, out cols);
            else
            {
                rows = _gridRows;
                cols = _gridCols;
            }

            if (_mode == GenerationMode.Pattern)
            {
                PatternType selectedPattern = _pattern;
                if (_randomPattern)
                    selectedPattern = (PatternType)Random.Range(0, System.Enum.GetValues(typeof(PatternType)).Length - 1);
                lv = GeneratePatternLevel(selectedPattern, i + 1, rows, cols);
                if (lv == null)
                {
                    Debug.LogWarning($"图案生成失败，回退到随机");
                    lv = GenerateRandomLevel(i + 1, rows, cols);
                }
            }
            else
            {
                lv = GenerateRandomLevel(i + 1, rows, cols);
            }

            if (lv != null)
                levels.Add(lv);
        }

        if (levels.Count == 0)
        {
            EditorUtility.DisplayDialog("错误", "没有生成任何有效关卡", "确定");
            return;
        }

        AllLevelRoot root = new AllLevelRoot();
        root.levels = levels;
        string json = JsonUtility.ToJson(root, true);
        string path = EditorUtility.SaveFilePanel("保存关卡配置", Application.dataPath, _outputFileName, "json");
        if (!string.IsNullOrEmpty(path))
        {
            File.WriteAllText(path, json);
            EditorUtility.DisplayDialog("成功", $"已生成 {levels.Count} 个关卡并保存到 {path}", "确定");
        }
    }

    private void GetSizeByDifficulty(out int rows, out int cols)
    {
        switch (_difficulty)
        {
            case Difficulty.Easy:   rows = 6; cols = 6; break;
            case Difficulty.Medium: rows = 8; cols = 8; break;
            case Difficulty.Hard:   rows = 34; cols = 21; break;
            default: rows = 8; cols = 8; break;
        }
    }

    // ========== 改进的随机生成（无交叉） ==========
    private LevelConfig GenerateRandomLevel(int levelId, int rows, int cols)
    {
        LevelConfig lv = new LevelConfig();
        lv.levelId = levelId;
        lv.levelName = $"第{levelId}关";
        lv.gridRows = rows;
        lv.gridCols = cols;
        lv.pointSpacing = _pointSpacing;
        lv.arrows = new List<ArrowConfig>();

        int arrowCount = 0;
        int minPathLen=0,maxPathLen=0;
        int maxTurns = 0;
        switch (_difficulty)
        {
            case Difficulty.Easy:   arrowCount = Random.Range(3, 6);  minPathLen = 1; maxPathLen = 3; maxTurns = 1; break;
            case Difficulty.Medium: arrowCount = Random.Range(6, 10); minPathLen = 2; maxPathLen = 5; maxTurns = 2; break;
            case Difficulty.Hard:   arrowCount = Random.Range(25, 40); minPathLen = 4; maxPathLen = 10; maxTurns = 5; break;
        }

        HashSet<int> occupiedPoints = new HashSet<int>();
        int maxAttemptsPerArrow = 200;
        int totalAttempts = 0;
        int maxTotalAttempts = arrowCount * 50;

        for (int i = 0; i < arrowCount; i++)
        {
            bool success = false;
            int attempts = 0;
            while (!success && attempts < maxAttemptsPerArrow && totalAttempts < maxTotalAttempts)
            {
                attempts++;
                totalAttempts++;

                int start = Random.Range(0, rows * cols);
                if (occupiedPoints.Contains(start))
                    continue;

                int pathLen = Random.Range(minPathLen, maxPathLen + 1);
                List<string> dirs = new List<string>();
                int cur = start;
                bool valid = true;
                int turns = 0;
                string lastDir = "";
                List<int> pathPoints = new List<int> { start };

                for (int j = 0; j < pathLen; j++)
                {
                    List<string> validDirs = GetValidDirections(cur, rows, cols);
                    if (validDirs.Count == 0) { valid = false; break; }
                    string chosenDir = "";
                    if (turns < maxTurns && !string.IsNullOrEmpty(lastDir))
                    {
                        var otherDirs = validDirs.Where(d => d != lastDir).ToList();
                        if (otherDirs.Count > 0)
                            chosenDir = otherDirs[Random.Range(0, otherDirs.Count)];
                        else
                            chosenDir = validDirs[Random.Range(0, validDirs.Count)];
                    }
                    else
                    {
                        chosenDir = validDirs[Random.Range(0, validDirs.Count)];
                    }
                    if (chosenDir != lastDir && !string.IsNullOrEmpty(lastDir))
                        turns++;
                    dirs.Add(chosenDir);
                    cur = GetNextPoint(cur, chosenDir, cols, rows);
                    if (cur < 0) { valid = false; break; }
                    pathPoints.Add(cur);
                    lastDir = chosenDir;
                }

                if (!valid) continue;

                // 检测冲突
                bool conflict = false;
                foreach (int p in pathPoints)
                {
                    if (occupiedPoints.Contains(p))
                    {
                        conflict = true;
                        break;
                    }
                }
                if (conflict) continue;

                // 无冲突，添加箭头
                ArrowConfig arrow = new ArrowConfig();
                arrow.id = i + 1;
                arrow.startPoint = start;
                arrow.path = dirs;
                lv.arrows.Add(arrow);

                foreach (int p in pathPoints)
                    occupiedPoints.Add(p);

                success = true;
            }

            if (!success)
                Debug.LogWarning($"生成第 {levelId} 关时，第 {i+1} 个箭头生成失败，跳过");
        }

        if (lv.arrows.Count == 0) return null;
        return lv;
    }

    private List<string> GetValidDirections(int point, int rows, int cols)
    {
        List<string> dirs = new List<string>();
        int row = point / cols;
        int col = point % cols;
        if (row > 0) dirs.Add("up");
        if (row < rows - 1) dirs.Add("down");
        if (col > 0) dirs.Add("left");
        if (col < cols - 1) dirs.Add("right");
        return dirs;
    }

    // ========== 图案生成（简单版） ==========
    private LevelConfig GeneratePatternLevel(PatternType pattern, int levelId, int rows, int cols)
    {
        // 这里仅实现菱形图案，您可自行扩展
        return GenerateDiamondPattern(levelId, rows, cols);
    }

    private LevelConfig GenerateDiamondPattern(int levelId, int rows, int cols)
    {
        if (rows < 5 || cols < 5) return null;
        LevelConfig lv = new LevelConfig();
        lv.levelId = levelId;
        lv.levelName = $"图案Diamond_{levelId}";
        lv.gridRows = rows;
        lv.gridCols = cols;
        lv.pointSpacing = _pointSpacing;
        lv.arrows = new List<ArrowConfig>();

        int centerRow = rows / 2;
        int centerCol = cols / 2;
        int radius = Mathf.Min(rows, cols) / 2 - 1;
        if (radius < 2) return null;

        List<int> points = new List<int>();
        for (int i = 0; i <= radius; i++)
        {
            int r = centerRow - i;
            int c = centerCol + i;
            if (r >= 0 && c < cols) points.Add(r * cols + c);
        }
        for (int i = 1; i <= radius; i++)
        {
            int r = centerRow + i;
            int c = centerCol + radius - i;
            if (r < rows && c >= 0) points.Add(r * cols + c);
        }
        for (int i = 1; i <= radius; i++)
        {
            int r = centerRow + radius - i;
            int c = centerCol - i;
            if (r >= 0 && c >= 0) points.Add(r * cols + c);
        }
        for (int i = 1; i < radius; i++)
        {
            int r = centerRow - i;
            int c = centerCol - radius + i;
            if (r >= 0 && c >= 0) points.Add(r * cols + c);
        }
        if (points.Count < 3) return null;

        int maxStep = 4;
        int arrowId = 1;
        for (int i = 0; i < points.Count - 1;)
        {
            int remaining = points.Count - 1 - i;
            int step = Mathf.Min(maxStep, remaining);
            var segment = points.Skip(i).Take(step + 1).ToList();
            if (segment.Count >= 2)
            {
                ArrowConfig arrow = new ArrowConfig();
                arrow.id = arrowId++;
                arrow.startPoint = segment[0];
                arrow.path = new List<string>();
                for (int j = 0; j < segment.Count - 1; j++)
                {
                    string dir = GetDirection(segment[j], segment[j + 1], cols);
                    arrow.path.Add(dir);
                }
                lv.arrows.Add(arrow);
            }
            i += step;
        }
        return lv;
    }

    // ========== 工具方法 ==========
    private int GetNextPoint(int current, string dir, int cols, int rows)
    {
        int row = current / cols;
        int col = current % cols;
        switch (dir)
        {
            case "up": row--; break;
            case "down": row++; break;
            case "left": col--; break;
            case "right": col++; break;
        }
        if (row < 0 || row >= rows || col < 0 || col >= cols) return -1;
        return row * cols + col;
    }

    private string GetDirection(int from, int to, int cols)
    {
        int fromRow = from / cols, fromCol = from % cols;
        int toRow = to / cols, toCol = to % cols;
        if (toRow < fromRow) return "up";
        if (toRow > fromRow) return "down";
        if (toCol < fromCol) return "left";
        if (toCol > fromCol) return "right";
        return "up";
    }
}