using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;

/// <summary>
/// GuideConfig.txt 可视化编辑器
/// 菜单路径: 程序工具/策划工具/引导配置编辑器
/// </summary>
public class GuideConfigEditor : EditorWindow
{
    #region 数据结构

    [Serializable]
    public class GuideConditions
    {
        public List<string> Satisfy = new List<string>();
        public int CheckAgain;
        public List<string> Trigger = new List<string>();
        public string End = "";
        public float Delay;
        public int Limit;
    }

    [Serializable]
    public class GuideShowUI
    {
        public string LangText = "";
        public string RoleExpression = "";
        public string DialogPos = "";
        public int OkBtn;
        public int ClickSg;
        public string ClickPos = "";
        public string FocusPos = "";
        public int Phone;
        public int ClickToSkip;
    }

    [Serializable]
    public class GuideEntry
    {
        public int Id;
        public string Name = "";
        public int Priority;
        public GuideConditions Conditions = new GuideConditions();
        public GuideShowUI ShowUI = new GuideShowUI();
    }

    #endregion

    #region 字段

    private static readonly string ConfigPath = "Assets/Scripts/Preload/GuideConfig.txt";

    private List<GuideEntry> _entries = new List<GuideEntry>();
    private Vector2 _listScroll;
    private Vector2 _detailScroll;
    private int _selectedIndex = -1;
    private string _searchText = "";
    private string _searchId = "";
    private bool _isDirty;
    private bool _showConditions = true;
    private bool _showShowUI = true;
    private bool _showSatisfy = true;
    private bool _showTrigger = true;

    // 列表排序
    private enum SortMode { Id, Priority, Name }
    private SortMode _sortMode = SortMode.Id;

    // 预设值缓存（从现有数据中收集）
    private List<string> _satisfyPresets = new List<string>();
    private List<string> _triggerPresets = new List<string>();
    private List<string> _endPresets = new List<string>();
    private List<string> _roleExpressionPresets = new List<string>();
    private List<string> _dialogPosPresets = new List<string>();
    private List<string> _clickPosPresets = new List<string>();
    private List<string> _focusPosPresets = new List<string>();
    private bool _presetsDirty = true;

    // 样式缓存
    private GUIStyle _headerStyle;
    private GUIStyle _selectedStyle;
    private GUIStyle _entryStyle;
    private bool _stylesInited;

    #endregion

    [MenuItem("策划工具/引导配置编辑器")]
    public static void ShowWindow()
    {
        var win = GetWindow<GuideConfigEditor>("引导配置编辑器");
        win.minSize = new Vector2(900, 500);
        win.LoadConfig();
    }

    private void OnEnable()
    {
        LoadConfig();
    }

    private void InitStyles()
    {
        if (_stylesInited) return;
        _headerStyle = new GUIStyle(EditorStyles.boldLabel) { fontSize = 13 };
        _selectedStyle = new GUIStyle("TV Selection");
        _entryStyle = new GUIStyle(EditorStyles.label) { richText = true };
        _stylesInited = true;
    }

    #region 加载 / 保存

    private void LoadConfig()
    {
        string fullPath = Path.Combine(Application.dataPath, "..", ConfigPath);
        if (!File.Exists(fullPath))
        {
            Debug.LogError($"[GuideConfigEditor] 文件不存在: {fullPath}");
            return;
        }

        string json = File.ReadAllText(fullPath);
        _entries = ParseJsonArray(json);
        _isDirty = false;
        _selectedIndex = -1;
        _presetsDirty = true;
        Debug.Log($"[GuideConfigEditor] 已加载 {_entries.Count} 条引导配置");
    }

    /// <summary>
    /// 从所有现有条目中收集去重的预设值，用于快速选择
    /// </summary>
    private void RebuildPresets()
    {
        if (!_presetsDirty) return;
        _presetsDirty = false;

        var satisfySet = new HashSet<string>();
        var triggerSet = new HashSet<string>();
        var endSet = new HashSet<string>();
        var roleExprSet = new HashSet<string>();
        var dialogPosSet = new HashSet<string>();
        var clickPosSet = new HashSet<string>();
        var focusPosSet = new HashSet<string>();

        foreach (var e in _entries)
        {
            if (e.Conditions.Satisfy != null)
                foreach (var s in e.Conditions.Satisfy)
                    if (!string.IsNullOrEmpty(s)) satisfySet.Add(s);

            if (e.Conditions.Trigger != null)
                foreach (var t in e.Conditions.Trigger)
                    if (!string.IsNullOrEmpty(t)) triggerSet.Add(t);

            if (!string.IsNullOrEmpty(e.Conditions.End))
                endSet.Add(e.Conditions.End);

            if (!string.IsNullOrEmpty(e.ShowUI.RoleExpression))
                roleExprSet.Add(e.ShowUI.RoleExpression);

            if (!string.IsNullOrEmpty(e.ShowUI.DialogPos))
                dialogPosSet.Add(e.ShowUI.DialogPos);

            if (!string.IsNullOrEmpty(e.ShowUI.ClickPos))
                clickPosSet.Add(e.ShowUI.ClickPos);

            if (!string.IsNullOrEmpty(e.ShowUI.FocusPos))
                focusPosSet.Add(e.ShowUI.FocusPos);
        }

        _satisfyPresets = satisfySet.OrderBy(s => s).ToList();
        _triggerPresets = triggerSet.OrderBy(s => s).ToList();
        _endPresets = endSet.OrderBy(s => s).ToList();
        _roleExpressionPresets = roleExprSet.OrderBy(s => s).ToList();
        _dialogPosPresets = dialogPosSet.OrderBy(s => s).ToList();
        _clickPosPresets = clickPosSet.OrderBy(s => s).ToList();
        _focusPosPresets = focusPosSet.OrderBy(s => s).ToList();
    }

    private void SaveConfig()
    {
        string fullPath = Path.Combine(Application.dataPath, "..", ConfigPath);
        string json = SerializeToJson(_entries);
        File.WriteAllText(fullPath, json);
        _isDirty = false;
        AssetDatabase.Refresh();
        Debug.Log($"[GuideConfigEditor] 已保存 {_entries.Count} 条引导配置到 {ConfigPath}");
    }

    #endregion

    #region GUI

    private void OnGUI()
    {
        InitStyles();
        RebuildPresets();
        DrawToolbar();

        EditorGUILayout.BeginHorizontal();
        {
            // 左侧列表
            EditorGUILayout.BeginVertical(GUILayout.Width(320));
            DrawList();
            EditorGUILayout.EndVertical();

            // 分割线
            GUILayout.Box("", GUILayout.Width(2), GUILayout.ExpandHeight(true));

            // 右侧详情
            EditorGUILayout.BeginVertical();
            DrawDetail();
            EditorGUILayout.EndVertical();
        }
        EditorGUILayout.EndHorizontal();
    }

    private void DrawToolbar()
    {
        EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
        {
            if (GUILayout.Button("重新加载", EditorStyles.toolbarButton, GUILayout.Width(60)))
            {
                if (!_isDirty || EditorUtility.DisplayDialog("确认", "有未保存的修改，确定重新加载？", "确定", "取消"))
                    LoadConfig();
            }

            GUI.backgroundColor = _isDirty ? Color.yellow : Color.white;
            if (GUILayout.Button(_isDirty ? "保存 *" : "保存", EditorStyles.toolbarButton, GUILayout.Width(60)))
            {
                SaveConfig();
            }
            GUI.backgroundColor = Color.white;

            GUILayout.Space(10);

            if (GUILayout.Button("+ 新建", EditorStyles.toolbarButton, GUILayout.Width(50)))
            {
                AddNewEntry();
            }

            if (GUILayout.Button("复制当前", EditorStyles.toolbarButton, GUILayout.Width(60)))
            {
                DuplicateSelected();
            }

            if (GUILayout.Button("删除当前", EditorStyles.toolbarButton, GUILayout.Width(60)))
            {
                DeleteSelected();
            }

            GUILayout.FlexibleSpace();

            // 排序
            GUILayout.Label("排序:", EditorStyles.toolbarButton, GUILayout.Width(30));
            var newSort = (SortMode)EditorGUILayout.EnumPopup(_sortMode, EditorStyles.toolbarPopup, GUILayout.Width(70));
            if (newSort != _sortMode)
            {
                _sortMode = newSort;
            }

            GUILayout.Space(5);
            GUILayout.Label("全局搜索:", EditorStyles.toolbarButton, GUILayout.Width(50));
            _searchText = EditorGUILayout.TextField(_searchText, EditorStyles.toolbarSearchField, GUILayout.Width(120));

            GUILayout.Label("ID:", EditorStyles.toolbarButton, GUILayout.Width(20));
            _searchId = EditorGUILayout.TextField(_searchId, EditorStyles.toolbarSearchField, GUILayout.Width(60));
        }
        EditorGUILayout.EndHorizontal();
    }

    private void DrawList()
    {
        _listScroll = EditorGUILayout.BeginScrollView(_listScroll);

        var filtered = GetFilteredAndSorted();

        for (int i = 0; i < filtered.Count; i++)
        {
            var entry = filtered[i];
            int realIndex = _entries.IndexOf(entry);
            bool isSelected = realIndex == _selectedIndex;

            Rect rect = EditorGUILayout.BeginHorizontal(isSelected ? _selectedStyle : GUIStyle.none, GUILayout.Height(22));
            {
                string label = $"<color=#888888>[{entry.Id}]</color> {entry.Name}";
                if (entry.Priority > 0)
                    label += $" <color=#cc8800>P{entry.Priority}</color>";

                GUILayout.Label(label, _entryStyle);
            }
            EditorGUILayout.EndHorizontal();

            if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition))
            {
                _selectedIndex = realIndex;
                GUI.FocusControl(null);
                Repaint();
            }
        }

        EditorGUILayout.EndScrollView();

        // 底部统计
        EditorGUILayout.LabelField($"共 {_entries.Count} 条 | 显示 {filtered.Count} 条", EditorStyles.centeredGreyMiniLabel);
    }

    private void DrawDetail()
    {
        if (_selectedIndex < 0 || _selectedIndex >= _entries.Count)
        {
            EditorGUILayout.HelpBox("← 请在左侧列表中选择一条引导配置", MessageType.Info);
            return;
        }

        var entry = _entries[_selectedIndex];
        _detailScroll = EditorGUILayout.BeginScrollView(_detailScroll);

        EditorGUILayout.LabelField("基本信息", _headerStyle);
        EditorGUI.indentLevel++;
        DrawField("Id", ref entry.Id);
        DrawField("Name (名称)", ref entry.Name);
        DrawField("Priority (优先级)", ref entry.Priority);
        EditorGUI.indentLevel--;

        EditorGUILayout.Space(8);

        // Conditions
        _showConditions = EditorGUILayout.Foldout(_showConditions, "Conditions (触发条件)", true);
        if (_showConditions)
        {
            EditorGUI.indentLevel++;
            DrawStringListWithPresets("Satisfy (满足条件)", ref entry.Conditions.Satisfy, ref _showSatisfy, _satisfyPresets);
            DrawField("CheckAgain", ref entry.Conditions.CheckAgain);
            DrawStringListWithPresets("Trigger (触发器)", ref entry.Conditions.Trigger, ref _showTrigger, _triggerPresets);
            DrawFieldWithPresets("End (结束条件)", ref entry.Conditions.End, _endPresets);
            DrawField("Delay (延迟秒)", ref entry.Conditions.Delay);
            DrawField("Limit (限制次数)", ref entry.Conditions.Limit);
            EditorGUI.indentLevel--;
        }

        EditorGUILayout.Space(8);

        // ShowUI
        _showShowUI = EditorGUILayout.Foldout(_showShowUI, "ShowUI (显示配置)", true);
        if (_showShowUI)
        {
            EditorGUI.indentLevel++;
            DrawField("LangText (多语言Key)", ref entry.ShowUI.LangText);
            DrawFieldWithPresets("RoleExpression (角色表情)", ref entry.ShowUI.RoleExpression, _roleExpressionPresets);
            DrawFieldWithPresets("DialogPos (对话位置)", ref entry.ShowUI.DialogPos, _dialogPosPresets);
            DrawField("OkBtn (确认按钮)", ref entry.ShowUI.OkBtn);
            DrawField("ClickSg (点击信号)", ref entry.ShowUI.ClickSg);
            DrawFieldWithPresets("ClickPos (点击位置)", ref entry.ShowUI.ClickPos, _clickPosPresets);
            DrawFieldWithPresets("FocusPos (聚焦位置)", ref entry.ShowUI.FocusPos, _focusPosPresets);
            DrawField("Phone (手机引导)", ref entry.ShowUI.Phone);
            DrawField("ClickToSkip (点击跳过)", ref entry.ShowUI.ClickToSkip);
            EditorGUI.indentLevel--;
        }

        EditorGUILayout.EndScrollView();
    }

    #endregion

    #region 辅助绘制

    private void DrawField(string label, ref int value)
    {
        int newVal = EditorGUILayout.IntField(label, value);
        if (newVal != value) { value = newVal; _isDirty = true; }
    }

    private void DrawField(string label, ref float value)
    {
        float newVal = EditorGUILayout.FloatField(label, value);
        if (!Mathf.Approximately(newVal, value)) { value = newVal; _isDirty = true; }
    }

    private void DrawField(string label, ref string value)
    {
        string newVal = EditorGUILayout.TextField(label, value ?? "");
        if (newVal != (value ?? "")) { value = newVal; _isDirty = true; }
    }

    /// <summary>
    /// 带预设下拉的文本字段：点击▼按钮弹出已有值列表快速选择
    /// </summary>
    private void DrawFieldWithPresets(string label, ref string value, List<string> presets)
    {
        EditorGUILayout.BeginHorizontal();
        string newVal = EditorGUILayout.TextField(label, value ?? "");
        if (newVal != (value ?? "")) { value = newVal; _isDirty = true; }

        if (presets != null && presets.Count > 0)
        {
            if (GUILayout.Button("▼", GUILayout.Width(20)))
            {
                // 记录当前选中条目和字段信息，在回调中通过索引赋值
                int entryIdx = _selectedIndex;
                string fieldLabel = label;
                ShowPresetMenu(presets, selected =>
                {
                    ApplyPresetToField(entryIdx, fieldLabel, selected);
                });
            }
        }
        EditorGUILayout.EndHorizontal();
    }

    /// <summary>
    /// 预设回调：根据字段标签将选中值写回对应字段
    /// </summary>
    private void ApplyPresetToField(int entryIdx, string fieldLabel, string selected)
    {
        if (entryIdx < 0 || entryIdx >= _entries.Count) return;
        var entry = _entries[entryIdx];

        if (fieldLabel.StartsWith("End"))
            entry.Conditions.End = selected;
        else if (fieldLabel.StartsWith("RoleExpression"))
            entry.ShowUI.RoleExpression = selected;
        else if (fieldLabel.StartsWith("DialogPos"))
            entry.ShowUI.DialogPos = selected;
        else if (fieldLabel.StartsWith("ClickPos"))
            entry.ShowUI.ClickPos = selected;
        else if (fieldLabel.StartsWith("FocusPos"))
            entry.ShowUI.FocusPos = selected;

        _isDirty = true;
        _presetsDirty = true;
        Repaint();
    }

    /// <summary>
    /// 带预设快速选择的字符串列表（Satisfy / Trigger）
    /// 点击 "+" 新增空行，点击 "▼" 从已有值中选择并新增
    /// </summary>
    private void DrawStringListWithPresets(string label, ref List<string> list, ref bool foldout, List<string> presets)
    {
        EditorGUILayout.BeginHorizontal();
        foldout = EditorGUILayout.Foldout(foldout, $"{label} ({list.Count})", true);
        if (GUILayout.Button("+", GUILayout.Width(20)))
        {
            list.Add("");
            _isDirty = true;
        }
        // 预设快速添加按钮
        if (presets != null && presets.Count > 0)
        {
            if (GUILayout.Button("▼选择", GUILayout.Width(45)))
            {
                var listRef = list;
                ShowPresetMenu(presets, selected =>
                {
                    listRef.Add(selected);
                    _isDirty = true;
                    _presetsDirty = true;
                    Repaint();
                });
            }
        }
        EditorGUILayout.EndHorizontal();

        if (!foldout) return;

        EditorGUI.indentLevel++;
        for (int i = 0; i < list.Count; i++)
        {
            EditorGUILayout.BeginHorizontal();
            string newVal = EditorGUILayout.TextField($"[{i}]", list[i] ?? "");
            if (newVal != (list[i] ?? "")) { list[i] = newVal; _isDirty = true; }

            // 每行也有预设选择按钮，可以替换当前值
            if (presets != null && presets.Count > 0)
            {
                int idx = i;
                if (GUILayout.Button("▼", GUILayout.Width(20)))
                {
                    var listRef = list;
                    ShowPresetMenu(presets, selected =>
                    {
                        if (idx < listRef.Count)
                        {
                            listRef[idx] = selected;
                            _isDirty = true;
                            _presetsDirty = true;
                            Repaint();
                        }
                    });
                }
            }

            if (GUILayout.Button("↑", GUILayout.Width(20)) && i > 0)
            {
                (list[i - 1], list[i]) = (list[i], list[i - 1]);
                _isDirty = true;
            }
            if (GUILayout.Button("↓", GUILayout.Width(20)) && i < list.Count - 1)
            {
                (list[i], list[i + 1]) = (list[i + 1], list[i]);
                _isDirty = true;
            }
            if (GUILayout.Button("×", GUILayout.Width(20)))
            {
                list.RemoveAt(i);
                _isDirty = true;
                break;
            }
            EditorGUILayout.EndHorizontal();
        }
        EditorGUI.indentLevel--;
    }

    /// <summary>
    /// 显示预设值的下拉菜单（GenericMenu），按前缀分组
    /// </summary>
    private void ShowPresetMenu(List<string> presets, Action<string> onSelect)
    {
        var menu = new GenericMenu();
        // 按前缀分组显示
        var groups = new Dictionary<string, List<string>>();
        foreach (var p in presets)
        {
            string prefix = ExtractPrefix(p);
            if (!groups.ContainsKey(prefix))
                groups[prefix] = new List<string>();
            groups[prefix].Add(p);
        }

        // 如果分组数 > 1 且有明显前缀，按分组显示
        if (groups.Count > 1 && groups.Keys.Any(k => k != ""))
        {
            foreach (var kvp in groups.OrderBy(g => g.Key))
            {
                string groupLabel = string.IsNullOrEmpty(kvp.Key) ? "其他" : kvp.Key;
                foreach (var item in kvp.Value)
                {
                    // 用 \u2215 (除号斜杠) 替换 / 避免被 GenericMenu 当作子菜单分隔符
                    string safeItem = item.Replace("/", "\u2215");
                    string menuPath = $"{groupLabel}/{safeItem}";
                    string captured = item;
                    menu.AddItem(new GUIContent(menuPath), false, () => onSelect(captured));
                }
            }
        }
        else
        {
            // 数量少或无明显前缀，平铺显示
            foreach (var item in presets)
            {
                string safeItem = item.Replace("/", "\u2215");
                string captured = item;
                menu.AddItem(new GUIContent(safeItem), false, () => onSelect(captured));
            }
        }

        menu.ShowAsContext();
    }

    /// <summary>
    /// 提取条件字符串的前缀（如 "LevelEqual_1" → "LevelEqual"，"UIPanel_MainHomeUI_1" → "UIPanel"）
    /// </summary>
    private string ExtractPrefix(string value)
    {
        if (string.IsNullOrEmpty(value)) return "";
        int idx = value.IndexOf('_');
        if (idx > 0 && idx < value.Length - 1)
            return value.Substring(0, idx);
        return "";
    }

    private void DrawStringList(string label, ref List<string> list, ref bool foldout)
    {
        EditorGUILayout.BeginHorizontal();
        foldout = EditorGUILayout.Foldout(foldout, $"{label} ({list.Count})", true);
        if (GUILayout.Button("+", GUILayout.Width(20)))
        {
            list.Add("");
            _isDirty = true;
        }
        EditorGUILayout.EndHorizontal();

        if (!foldout) return;

        EditorGUI.indentLevel++;
        for (int i = 0; i < list.Count; i++)
        {
            EditorGUILayout.BeginHorizontal();
            string newVal = EditorGUILayout.TextField($"[{i}]", list[i] ?? "");
            if (newVal != (list[i] ?? "")) { list[i] = newVal; _isDirty = true; }

            if (GUILayout.Button("↑", GUILayout.Width(20)) && i > 0)
            {
                (list[i - 1], list[i]) = (list[i], list[i - 1]);
                _isDirty = true;
            }
            if (GUILayout.Button("↓", GUILayout.Width(20)) && i < list.Count - 1)
            {
                (list[i], list[i + 1]) = (list[i + 1], list[i]);
                _isDirty = true;
            }
            if (GUILayout.Button("×", GUILayout.Width(20)))
            {
                list.RemoveAt(i);
                _isDirty = true;
                break;
            }
            EditorGUILayout.EndHorizontal();
        }
        EditorGUI.indentLevel--;
    }

    #endregion

    #region 操作

    private List<GuideEntry> GetFilteredAndSorted()
    {
        IEnumerable<GuideEntry> result = _entries;

        // 全字段搜索（Name、Conditions、ShowUI 所有文本字段）
        if (!string.IsNullOrEmpty(_searchText))
        {
            string lower = _searchText.ToLower();
            result = result.Where(e => EntryMatchesSearch(e, lower));
        }

        // 按ID搜索
        if (!string.IsNullOrEmpty(_searchId))
        {
            result = result.Where(e => e.Id.ToString().Contains(_searchId));
        }

        // 排序
        switch (_sortMode)
        {
            case SortMode.Id:
                result = result.OrderBy(e => e.Id);
                break;
            case SortMode.Priority:
                result = result.OrderByDescending(e => e.Priority).ThenBy(e => e.Id);
                break;
            case SortMode.Name:
                result = result.OrderBy(e => e.Name ?? "");
                break;
        }

        return result.ToList();
    }

    /// <summary>
    /// 全字段匹配：搜索 Name、Conditions（Satisfy/Trigger/End）、ShowUI 所有文本字段
    /// </summary>
    private bool EntryMatchesSearch(GuideEntry e, string lower)
    {
        // 基本信息
        if ((e.Name ?? "").ToLower().Contains(lower))
            return true;

        // Conditions
        if (e.Conditions.Satisfy != null && e.Conditions.Satisfy.Any(s => (s ?? "").ToLower().Contains(lower)))
            return true;
        if (e.Conditions.Trigger != null && e.Conditions.Trigger.Any(s => (s ?? "").ToLower().Contains(lower)))
            return true;
        if ((e.Conditions.End ?? "").ToLower().Contains(lower))
            return true;
        if (e.Conditions.CheckAgain.ToString().Contains(lower))
            return true;
        if (e.Conditions.Delay.ToString("G").ToLower().Contains(lower))
            return true;
        if (e.Conditions.Limit.ToString().Contains(lower))
            return true;

        // ShowUI
        if ((e.ShowUI.LangText ?? "").ToLower().Contains(lower))
            return true;
        if ((e.ShowUI.RoleExpression ?? "").ToLower().Contains(lower))
            return true;
        if ((e.ShowUI.DialogPos ?? "").ToLower().Contains(lower))
            return true;
        if ((e.ShowUI.ClickPos ?? "").ToLower().Contains(lower))
            return true;
        if ((e.ShowUI.FocusPos ?? "").ToLower().Contains(lower))
            return true;
        if (e.ShowUI.OkBtn.ToString().Contains(lower))
            return true;
        if (e.ShowUI.ClickSg.ToString().Contains(lower))
            return true;
        if (e.ShowUI.Phone.ToString().Contains(lower))
            return true;
        if (e.ShowUI.ClickToSkip.ToString().Contains(lower))
            return true;

        return false;
    }

    private void AddNewEntry()
    {
        int maxId = _entries.Count > 0 ? _entries.Max(e => e.Id) : 0;
        var newEntry = new GuideEntry
        {
            Id = maxId + 1,
            Name = "新引导步骤",
        };
        _entries.Add(newEntry);
        _selectedIndex = _entries.Count - 1;
        _isDirty = true;
    }

    private void DuplicateSelected()
    {
        if (_selectedIndex < 0 || _selectedIndex >= _entries.Count) return;
        var src = _entries[_selectedIndex];
        string json = JsonUtility.ToJson(src);
        var copy = JsonUtility.FromJson<GuideEntry>(json);
        // 深拷贝列表字段 (JsonUtility 会处理)
        copy.Id = _entries.Max(e => e.Id) + 1;
        copy.Name = src.Name + "_副本";
        _entries.Insert(_selectedIndex + 1, copy);
        _selectedIndex = _selectedIndex + 1;
        _isDirty = true;
    }

    private void DeleteSelected()
    {
        if (_selectedIndex < 0 || _selectedIndex >= _entries.Count) return;
        var entry = _entries[_selectedIndex];
        if (EditorUtility.DisplayDialog("确认删除", $"确定删除引导 [{entry.Id}] {entry.Name}？", "删除", "取消"))
        {
            _entries.RemoveAt(_selectedIndex);
            _selectedIndex = Mathf.Min(_selectedIndex, _entries.Count - 1);
            _isDirty = true;
        }
    }

    #endregion

    #region JSON 解析/序列化 (手写，兼容原文件格式)

    /// <summary>
    /// 使用 Unity 内置 JsonUtility 无法直接解析顶层数组，这里包装一下。
    /// 原文件存在尾逗号等不规范 JSON，需要预处理。
    /// </summary>
    private List<GuideEntry> ParseJsonArray(string json)
    {
        // 预处理：移除尾逗号 (trailing commas before ] or })
        json = Regex.Replace(json, @",(\s*[\]\}])", "$1");

        // 包装成对象让 JsonUtility 能解析
        string wrapped = "{\"items\":" + json + "}";
        var wrapper = JsonUtility.FromJson<GuideEntryArrayWrapper>(wrapped);
        return wrapper != null && wrapper.items != null ? wrapper.items : new List<GuideEntry>();
    }

    [Serializable]
    private class GuideEntryArrayWrapper
    {
        public List<GuideEntry> items;
    }

    /// <summary>
    /// 序列化回原始格式（带缩进的 JSON 数组，保持和原文件一致的风格）
    /// </summary>
    private string SerializeToJson(List<GuideEntry> entries)
    {
        var sb = new System.Text.StringBuilder();
        sb.AppendLine("[");

        for (int i = 0; i < entries.Count; i++)
        {
            var e = entries[i];
            sb.AppendLine("  {");
            sb.AppendLine($"    \"Id\": {e.Id},");
            sb.AppendLine($"    \"Name\":\"{EscapeJson(e.Name)}\",");
            sb.AppendLine($"    \"Priority\":{e.Priority},");

            // Conditions
            sb.AppendLine("    \"Conditions\":{");
            sb.AppendLine("        \"Satisfy\":[");
            for (int s = 0; s < e.Conditions.Satisfy.Count; s++)
            {
                string comma = s < e.Conditions.Satisfy.Count - 1 ? "," : "";
                sb.AppendLine($"            \"{EscapeJson(e.Conditions.Satisfy[s])}\"{comma}");
            }
            sb.AppendLine("        ],");
            sb.AppendLine($"        \"CheckAgain\":{e.Conditions.CheckAgain},");
            sb.AppendLine("        \"Trigger\":[");
            for (int t = 0; t < e.Conditions.Trigger.Count; t++)
            {
                string comma = t < e.Conditions.Trigger.Count - 1 ? "," : "";
                sb.AppendLine($"            \"{EscapeJson(e.Conditions.Trigger[t])}\"{comma}");
            }
            sb.AppendLine("        ],");
            sb.AppendLine($"        \"End\":\"{EscapeJson(e.Conditions.End)}\",");
            sb.AppendLine($"        \"Delay\":{FormatFloat(e.Conditions.Delay)},");
            sb.AppendLine($"        \"Limit\":{e.Conditions.Limit}");
            sb.AppendLine("    },");

            // ShowUI
            sb.AppendLine("    \"ShowUI\": {");
            sb.AppendLine($"        \"LangText\":\"{EscapeJson(e.ShowUI.LangText)}\",");
            sb.AppendLine($"        \"RoleExpression\":\"{EscapeJson(e.ShowUI.RoleExpression)}\",");
            sb.AppendLine($"        \"DialogPos\":\"{EscapeJson(e.ShowUI.DialogPos)}\",");
            sb.AppendLine($"        \"OkBtn\":{e.ShowUI.OkBtn},");
            sb.AppendLine($"        \"ClickSg\":{e.ShowUI.ClickSg},");
            sb.AppendLine($"        \"ClickPos\":\"{EscapeJson(e.ShowUI.ClickPos)}\",");
            sb.AppendLine($"        \"FocusPos\":\"{EscapeJson(e.ShowUI.FocusPos)}\",");
            sb.AppendLine($"        \"Phone\":{e.ShowUI.Phone},");
            sb.AppendLine($"        \"ClickToSkip\":{e.ShowUI.ClickToSkip}");
            sb.AppendLine("    }");

            string entryComma = i < entries.Count - 1 ? "," : "";
            sb.AppendLine($"  }}{entryComma}");
        }

        sb.Append("]");
        return sb.ToString();
    }

    private string FormatFloat(float val)
    {
        // 如果是整数值，输出不带小数点的格式（和原文件保持一致）
        if (Mathf.Approximately(val, Mathf.Round(val)))
            return ((int)val).ToString();
        return val.ToString("G");
    }

    private string EscapeJson(string s)
    {
        if (string.IsNullOrEmpty(s)) return "";
        return s.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n").Replace("\r", "\\r").Replace("\t", "\\t");
    }

    #endregion
}
