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

namespace DesignTools.Scene
{
    /// <summary>
    /// 装饰场景消耗/批次配置工具
    /// 读取 Docs/config/DecorateCost.xlsx 的 DecorateCost Sheet，供策划编辑每步消耗与批次。
    /// </summary>
    public class DecorateCostPlannerEditor : BaseDesignToolEditor
    {
        private static readonly string[] BATCH_NAMES =
        {
            string.Empty,
            "first",
            "second",
            "third",
            "four",
            "five",
            "six",
            "seven",
            "eight",
            "nine",
            "ten",
            "eleven",
            "twelve",
            "thirteen",
            "fourteen",
            "fifteen",
            "sixteen",
            "seventeen",
            "eighteen",
            "nineteen",
            "twenty",
            "twentyone",
            "twentytwo",
            "twentythree",
            "twentyfour",
            "twentyfive",
            "twentysix",
            "twentyseven",
            "twentyeight",
            "twentynine",
            "thirty",
            "thirtyone",
            "thirtytwo",
            "thirtythree",
            "thirtyfour",
            "thirtyfive",
            "thirtysix",
            "thirtyseven",
            "thirtyeight",
            "thirtynine",
            "forty",
            "fortyone"
        };

        private const string DECORATE_COST_EXCEL_NAME = "DecorateCost.xlsx";
        private const string DECORATE_COST_SHEET_NAME = "DecorateCost";
        private const int DATA_START_ROW = 3;
        private const int TOTAL_COL_COUNT = 17;

        private const int COL_ID = 1;
        private const int COL_AREA_ID = 2;
        private const int COL_SORT_ID = 3;
        private const int COL_COST_COUNT = 4;
        private const int COL_POS = 7;

        private readonly List<DecorateCostExcelRow> allRows = new List<DecorateCostExcelRow>();
        private readonly Dictionary<int, DecorateCostExcelRow> rowIndexMap = new Dictionary<int, DecorateCostExcelRow>();
        private readonly HashSet<int> dirtyRowIndexes = new HashSet<int>();
        private List<int> availableAreaIds = new List<int>();
        private List<DecorateCostExcelRow> currentAreaStepRows = new List<DecorateCostExcelRow>();

        private int selectedAreaId = -1;
        private int areaIdInput = 2;
        private int currentAreaExpectedStepCount;

        [MenuItem("策划工具/场景/装饰场景消耗与批次")]
        public static void ShowWindow()
        {
            var window = GetWindow<DecorateCostPlannerEditor>("装饰场景消耗与批次");
            window.minSize = window.GetMinWindowSize();
            window.Show();
        }

        protected override string GetDocsPathPrefKey()
        {
            return "DecorateCostPlannerEditor_DocsPath";
        }

        protected override string GetWindowTitle()
        {
            return "装饰场景消耗与批次工具";
        }

        protected override Vector2 GetMinWindowSize()
        {
            return new Vector2(920, 680);
        }

        protected override void LoadConfigData()
        {
            LoadDecorateCostExcel();
            currentAreaStepRows.Clear();
            currentAreaExpectedStepCount = 0;
            selectedAreaId = -1;
            areaIdInput = GetDefaultAreaId();

            if (availableAreaIds.Count == 0)
            {
                EditorUtility.DisplayDialog("提示", "DecorateCost 中没有可编辑的 AreaId 数据。", "确定");
                return;
            }

            EditorApplication.delayCall += ShowAreaInputDialog;
        }

        protected override void DrawDataEditor()
        {
            DrawAreaSelector();
            EditorGUILayout.Space(6);

            if (selectedAreaId < 0)
            {
                EditorGUILayout.HelpBox("请先输入并加载 AreaId。AreaId=1 不允许编辑；AreaId=2-5 为 20 步；AreaId>=6 为 25 步。", MessageType.Info);
                return;
            }

            DrawAreaSummary();
            EditorGUILayout.Space(6);
            DrawQuickActions();
            EditorGUILayout.Space(6);
            DrawStepTable();
        }

        protected override void SaveDataToExcel()
        {
            SaveDecorateCostExcel();
        }

        private void LoadDecorateCostExcel()
        {
            allRows.Clear();
            rowIndexMap.Clear();
            dirtyRowIndexes.Clear();

            string excelPath = GetDocsConfigFilePath(DECORATE_COST_EXCEL_NAME);
            if (!File.Exists(excelPath))
            {
                throw new FileNotFoundException($"未找到 {DECORATE_COST_EXCEL_NAME}", excelPath);
            }

            using (ExcelPackage package = new ExcelPackage(new FileInfo(excelPath)))
            {
                ExcelWorksheet worksheet = package.Workbook.Worksheets[DECORATE_COST_SHEET_NAME];
                if (worksheet == null)
                {
                    throw new Exception($"未找到 Sheet: {DECORATE_COST_SHEET_NAME}");
                }

                if (worksheet.Dimension == null)
                {
                    availableAreaIds = new List<int>();
                    return;
                }

                int rowCount = worksheet.Dimension.End.Row;
                for (int row = DATA_START_ROW; row <= rowCount; row++)
                {
                    string idText = worksheet.Cells[row, COL_ID].Text.Trim();
                    string areaIdText = worksheet.Cells[row, COL_AREA_ID].Text.Trim();
                    string sortIdText = worksheet.Cells[row, COL_SORT_ID].Text.Trim();

                    if (string.IsNullOrEmpty(idText) && string.IsNullOrEmpty(areaIdText) && string.IsNullOrEmpty(sortIdText))
                    {
                        continue;
                    }

                    string[] fields = new string[TOTAL_COL_COUNT];
                    for (int col = 1; col <= TOTAL_COL_COUNT; col++)
                    {
                        fields[col - 1] = worksheet.Cells[row, col].Text ?? string.Empty;
                    }

                    DecorateCostExcelRow dataRow = new DecorateCostExcelRow(row, fields);
                    allRows.Add(dataRow);
                    rowIndexMap[row] = dataRow;
                }
            }

            availableAreaIds = allRows
                .Select(row => row.AreaId)
                .Where(areaId => areaId > 1)
                .Distinct()
                .OrderBy(areaId => areaId)
                .ToList();
        }

        private void DrawAreaSelector()
        {
            EditorGUILayout.BeginVertical("box");
            EditorGUILayout.LabelField("AreaId 选择", EditorStyles.boldLabel);

            EditorGUILayout.BeginHorizontal();
            areaIdInput = EditorGUILayout.IntField("AreaId", areaIdInput, GUILayout.Width(240));

            if (GUILayout.Button("加载 AreaId", GUILayout.Width(120), GUILayout.Height(24)))
            {
                TrySelectArea(areaIdInput, true);
            }

            if (GUILayout.Button("重新输入", GUILayout.Width(100), GUILayout.Height(24)))
            {
                ShowAreaInputDialog();
            }

            GUILayout.FlexibleSpace();
            EditorGUILayout.EndHorizontal();

            string previewText = availableAreaIds.Count <= 15
                ? string.Join(", ", availableAreaIds)
                : string.Join(", ", availableAreaIds.Take(15)) + " ...";
            EditorGUILayout.HelpBox($"可编辑 AreaId：{previewText}", MessageType.None);
            EditorGUILayout.EndVertical();
        }

        private void DrawAreaSummary()
        {
            List<int> missingSortIds = GetMissingSortIds();
            int actualCount = currentAreaStepRows.Count;
            string summary = $"当前 AreaId：{selectedAreaId}\n期望步数：{currentAreaExpectedStepCount}\n实际可编辑步数：{actualCount}\n未保存修改：{dirtyRowIndexes.Count} 行";

            if (missingSortIds.Count > 0)
            {
                string missingText = string.Join(", ", missingSortIds.Take(10));
                if (missingSortIds.Count > 10)
                {
                    missingText += " ...";
                }

                EditorGUILayout.HelpBox(summary + $"\n\n⚠ 缺失步骤：{missingText}", MessageType.Warning);
                return;
            }

            EditorGUILayout.HelpBox(summary, MessageType.Info);
        }

        private void DrawQuickActions()
        {
            using (new EditorGUI.DisabledScope(currentAreaStepRows.Count == 0 || currentAreaExpectedStepCount <= 0))
            {
                EditorGUILayout.BeginHorizontal();

                GUI.backgroundColor = new Color(0.78f, 0.92f, 1f);
                if (GUILayout.Button("快捷设置资源消耗", GUILayout.Width(180), GUILayout.Height(28)))
                {
                    DecorateCostPlannerBatchCostWindow.ShowWindow(currentAreaExpectedStepCount, ApplyBatchCostSettings);
                }

                GUI.backgroundColor = new Color(1f, 0.9f, 0.65f);
                if (GUILayout.Button("快捷设置步骤批次", GUILayout.Width(180), GUILayout.Height(28)))
                {
                    DecorateCostPlannerBatchSkipWindow.ShowWindow(currentAreaExpectedStepCount, ApplyBatchBatchSettings);
                }

                GUI.backgroundColor = Color.white;
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();
            }

            GUI.backgroundColor = Color.white;
        }

        private void DrawStepTable()
        {
            EditorGUILayout.BeginVertical("box");
            EditorGUILayout.LabelField("步骤配置", EditorStyles.boldLabel);
            EditorGUILayout.Space(4);

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("SortId", EditorStyles.boldLabel, GUILayout.Width(70));
            EditorGUILayout.LabelField("CostCount", EditorStyles.boldLabel, GUILayout.Width(120));
            EditorGUILayout.LabelField("步骤批次", EditorStyles.boldLabel, GUILayout.Width(140));
            EditorGUILayout.LabelField("批次映射", EditorStyles.boldLabel, GUILayout.Width(120));
            EditorGUILayout.LabelField("Title", EditorStyles.boldLabel, GUILayout.Width(260));
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space(2);
            scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);

            foreach (DecorateCostExcelRow row in currentAreaStepRows.OrderBy(item => item.SortId))
            {
                DrawSingleStepRow(row);
            }

            EditorGUILayout.EndScrollView();
            EditorGUILayout.EndVertical();
        }

        private void DrawSingleStepRow(DecorateCostExcelRow row)
        {
            EditorGUILayout.BeginHorizontal("box");
            EditorGUILayout.LabelField(row.SortId.ToString(), GUILayout.Width(70));

            EditorGUI.BeginChangeCheck();
            int newCostCount = EditorGUILayout.IntField(row.CostCount, GUILayout.Width(120));
            if (EditorGUI.EndChangeCheck())
            {
                row.CostCount = Mathf.Max(0, newCostCount);
                MarkRowDirty(row);
            }

            EditorGUI.BeginChangeCheck();
            int newBatchValue = EditorGUILayout.IntField(row.BatchValue, GUILayout.Width(140));
            if (EditorGUI.EndChangeCheck())
            {
                row.BatchValue = Mathf.Max(0, newBatchValue);
                MarkRowDirty(row);
            }

            EditorGUILayout.LabelField(GetBatchDisplayName(row.BatchValue), GUILayout.Width(120));

            EditorGUILayout.LabelField(string.IsNullOrEmpty(row.Title) ? "-" : row.Title, GUILayout.Width(260));
            GUILayout.FlexibleSpace();
            EditorGUILayout.EndHorizontal();
        }

        private void ApplyBatchCostSettings(int[] costs)
        {
            if (costs == null || costs.Length == 0)
            {
                return;
            }

            int updatedCount = 0;
            List<int> missingSortIds = new List<int>();

            for (int step = 1; step <= currentAreaExpectedStepCount; step++)
            {
                DecorateCostExcelRow row = currentAreaStepRows.FirstOrDefault(item => item.SortId == step);
                if (row == null)
                {
                    missingSortIds.Add(step);
                    continue;
                }

                int groupIndex = Mathf.Clamp((step - 1) / 5, 0, costs.Length - 1);
                if (row.CostCount != costs[groupIndex])
                {
                    row.CostCount = Mathf.Max(0, costs[groupIndex]);
                    MarkRowDirty(row);
                    updatedCount++;
                }
            }

            ShowBatchApplyResult("资源消耗", updatedCount, missingSortIds);
        }

        private void ApplyBatchBatchSettings(int[] batches)
        {
            if (batches == null || batches.Length == 0)
            {
                return;
            }

            int updatedCount = 0;
            List<int> missingSortIds = new List<int>();

            for (int step = 1; step <= currentAreaExpectedStepCount; step++)
            {
                DecorateCostExcelRow row = currentAreaStepRows.FirstOrDefault(item => item.SortId == step);
                if (row == null)
                {
                    missingSortIds.Add(step);
                    continue;
                }

                int batchValue = step - 1 < batches.Length ? Mathf.Max(0, batches[step - 1]) : 0;
                if (row.BatchValue != batchValue)
                {
                    row.BatchValue = batchValue;
                    MarkRowDirty(row);
                    updatedCount++;
                }
            }

            ShowBatchApplyResult("步骤批次", updatedCount, missingSortIds);
        }

        private void ShowBatchApplyResult(string label, int updatedCount, List<int> missingSortIds)
        {
            string message = $"已应用{label}快捷设置，更新 {updatedCount} 步。";
            if (missingSortIds.Count > 0)
            {
                message += $"\n\n缺失步骤：{string.Join(", ", missingSortIds)}";
            }

            EditorUtility.DisplayDialog("完成", message, "确定");
        }

        private void SaveDecorateCostExcel()
        {
            if (dirtyRowIndexes.Count == 0)
            {
                EditorUtility.DisplayDialog("提示", "当前没有需要保存的修改。", "确定");
                return;
            }

            string excelPath = GetDocsConfigFilePath(DECORATE_COST_EXCEL_NAME);
            if (!File.Exists(excelPath))
            {
                EditorUtility.DisplayDialog("错误", $"未找到文件：{excelPath}", "确定");
                return;
            }

            try
            {
                using (ExcelPackage package = new ExcelPackage(new FileInfo(excelPath)))
                {
                    ExcelWorksheet worksheet = package.Workbook.Worksheets[DECORATE_COST_SHEET_NAME];
                    if (worksheet == null)
                    {
                        EditorUtility.DisplayDialog("错误", $"未找到 Sheet：{DECORATE_COST_SHEET_NAME}", "确定");
                        return;
                    }

                    foreach (int rowIndex in dirtyRowIndexes.OrderBy(index => index))
                    {
                        if (!rowIndexMap.TryGetValue(rowIndex, out DecorateCostExcelRow row))
                        {
                            continue;
                        }

                        worksheet.Cells[row.RowIndex, COL_COST_COUNT].Value = row.CostCount;
                        worksheet.Cells[row.RowIndex, COL_POS].Value = string.IsNullOrEmpty(row.Pos) ? null : row.Pos;
                    }

                    package.Save();
                }

                int savedCount = dirtyRowIndexes.Count;
                dirtyRowIndexes.Clear();
                AssetDatabase.Refresh();
                EditorUtility.DisplayDialog("成功", $"已保存 {savedCount} 行修改到 {DECORATE_COST_EXCEL_NAME}。", "确定");
            }
            catch (Exception e)
            {
                EditorUtility.DisplayDialog("错误", $"保存失败：{e.Message}\n{e.StackTrace}", "确定");
            }
        }

        private void ShowAreaInputDialog()
        {
            if (availableAreaIds == null || availableAreaIds.Count == 0)
            {
                return;
            }

            DecorateCostAreaInputWindow.ShowWindow(areaIdInput, TrySelectArea);
        }

        private bool TrySelectArea(int areaId)
        {
            return TrySelectArea(areaId, true);
        }

        private bool TrySelectArea(int areaId, bool showDialog)
        {
            if (areaId == 1)
            {
                if (showDialog)
                {
                    EditorUtility.DisplayDialog("限制", "AreaId 1 为旧版特殊场景，不能在此工具中编辑。", "确定");
                }
                return false;
            }

            int expectedStepCount = GetExpectedStepCount(areaId);
            if (expectedStepCount <= 0)
            {
                if (showDialog)
                {
                    EditorUtility.DisplayDialog("错误", "请输入有效的 AreaId。AreaId=2-5 为 20 步，AreaId>=6 为 25 步。", "确定");
                }
                return false;
            }

            bool hasArea = allRows.Any(row => row.AreaId == areaId);
            if (!hasArea)
            {
                if (showDialog)
                {
                    EditorUtility.DisplayDialog("未找到", $"DecorateCost 中不存在 AreaId={areaId} 的配置。", "确定");
                }
                return false;
            }

            selectedAreaId = areaId;
            areaIdInput = areaId;
            currentAreaExpectedStepCount = expectedStepCount;
            currentAreaStepRows = allRows
                .Where(row => row.AreaId == areaId && row.SortId != 0)
                .OrderBy(row => row.SortId)
                .ToList();

            if (showDialog)
            {
                string message = $"已加载 AreaId={areaId}\n期望步数：{currentAreaExpectedStepCount}\n可编辑步骤：{currentAreaStepRows.Count}";
                List<int> missingSortIds = GetMissingSortIds();
                if (missingSortIds.Count > 0)
                {
                    message += $"\n\n⚠ 缺失步骤：{string.Join(", ", missingSortIds)}";
                }

                EditorUtility.DisplayDialog("完成", message, "确定");
            }

            Repaint();
            return true;
        }

        private List<int> GetMissingSortIds()
        {
            if (currentAreaExpectedStepCount <= 0)
            {
                return new List<int>();
            }

            HashSet<int> existingIds = new HashSet<int>(currentAreaStepRows.Select(row => row.SortId));
            List<int> missingIds = new List<int>();
            for (int sortId = 1; sortId <= currentAreaExpectedStepCount; sortId++)
            {
                if (!existingIds.Contains(sortId))
                {
                    missingIds.Add(sortId);
                }
            }

            return missingIds;
        }

        private int GetDefaultAreaId()
        {
            return availableAreaIds.FirstOrDefault();
        }

        private int GetExpectedStepCount(int areaId)
        {
            if (areaId >= 2 && areaId <= 5)
            {
                return 20;
            }

            if (areaId >= 6)
            {
                return 25;
            }

            return 0;
        }

        private void MarkRowDirty(DecorateCostExcelRow row)
        {
            dirtyRowIndexes.Add(row.RowIndex);
        }

        private static string GetBatchDisplayName(int batchValue)
        {
            if (batchValue <= 0)
            {
                return "空";
            }

            if (batchValue < BATCH_NAMES.Length)
            {
                return BATCH_NAMES[batchValue];
            }

            return $"第{batchValue}批";
        }

        private static int ParseBatchValue(string value)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                return 0;
            }

            string trimmedValue = value.Trim();
            if (int.TryParse(trimmedValue, out int numericValue))
            {
                return Mathf.Max(0, numericValue);
            }

            for (int index = 1; index < BATCH_NAMES.Length; index++)
            {
                if (string.Equals(BATCH_NAMES[index], trimmedValue, StringComparison.OrdinalIgnoreCase))
                {
                    return index;
                }
            }

            string normalizedValue = trimmedValue.Replace("-", string.Empty).Replace(" ", string.Empty).ToLowerInvariant();
            for (int index = 1; index < BATCH_NAMES.Length; index++)
            {
                string normalizedBatchName = BATCH_NAMES[index].Replace("-", string.Empty).Replace(" ", string.Empty).ToLowerInvariant();
                if (normalizedBatchName == normalizedValue)
                {
                    return index;
                }
            }

            switch (normalizedValue)
            {
                case "fourth": return 4;
                case "fifth": return 5;
                case "sixth": return 6;
                case "seventh": return 7;
                case "eighth": return 8;
                case "ninth": return 9;
                case "tenth": return 10;
                case "eleventh": return 11;
                case "twelfth": return 12;
                case "thirteenth": return 13;
                case "fourteenth": return 14;
                case "fifteenth": return 15;
                case "sixteenth": return 16;
                case "seventeenth": return 17;
                case "eighteenth": return 18;
                case "nineteenth": return 19;
                case "twentieth": return 20;
                case "twentyfirst": return 21;
                case "twentysecond": return 22;
                case "twentythird": return 23;
                case "twentyfourth": return 24;
                case "twentyfifth": return 25;
                case "twentysixth": return 26;
                case "twentyseventh": return 27;
                case "twentyeighth": return 28;
                case "twentyninth": return 29;
                case "thirtieth": return 30;
                case "thirtyfirst": return 31;
                case "thirtysecond": return 32;
                case "thirtythird": return 33;
                case "thirtyfourth": return 34;
                case "thirtyfifth": return 35;
                case "thirtysixth": return 36;
                case "thirtyseventh": return 37;
                case "thirtyeighth": return 38;
                case "thirtyninth": return 39;
                case "fortieth": return 40;
                case "fortyfirst": return 41;
                default: return 0;
            }
        }

        private static string FormatBatchValue(int batchValue)
        {
            if (batchValue <= 0)
            {
                return string.Empty;
            }

            if (batchValue < BATCH_NAMES.Length)
            {
                return BATCH_NAMES[batchValue];
            }

            return batchValue.ToString();
        }

        private sealed class DecorateCostExcelRow
        {
            private readonly string[] fields;

            public DecorateCostExcelRow(int rowIndex, string[] fields)
            {
                RowIndex = rowIndex;
                this.fields = fields ?? new string[TOTAL_COL_COUNT];
            }

            public int RowIndex { get; }

            public int AreaId => ParseInt(fields[COL_AREA_ID - 1]);

            public int SortId => ParseInt(fields[COL_SORT_ID - 1]);

            public string Title => fields[4];

            public int CostCount
            {
                get => ParseInt(fields[COL_COST_COUNT - 1]);
                set => fields[COL_COST_COUNT - 1] = value.ToString();
            }

            public string Pos
            {
                get => fields[COL_POS - 1] ?? string.Empty;
                set => fields[COL_POS - 1] = value ?? string.Empty;
            }

            public int BatchValue
            {
                get => ParseBatchValue(Pos);
                set => Pos = FormatBatchValue(value);
            }

            private static int ParseInt(string value)
            {
                return int.TryParse(value, out int result) ? result : 0;
            }
        }
    }

    /// <summary>
    /// AreaId 输入窗口
    /// </summary>
    public class DecorateCostAreaInputWindow : EditorWindow
    {
        private Func<int, bool> onConfirm;
        private string areaIdText = string.Empty;

        public static void ShowWindow(int defaultAreaId, Func<int, bool> confirmCallback)
        {
            DecorateCostAreaInputWindow window = CreateInstance<DecorateCostAreaInputWindow>();
            window.titleContent = new GUIContent("输入 AreaId");
            window.minSize = new Vector2(320, 120);
            window.maxSize = new Vector2(320, 120);
            window.areaIdText = defaultAreaId > 0 ? defaultAreaId.ToString() : string.Empty;
            window.onConfirm = confirmCallback;
            window.ShowUtility();
        }

        private void OnGUI()
        {
            EditorGUILayout.Space(10);
            EditorGUILayout.LabelField("请输入要编辑的 AreaId", EditorStyles.boldLabel);
            EditorGUILayout.HelpBox("AreaId=1 不允许编辑；AreaId=2-5 为 20 步；AreaId>=6 为 25 步。", MessageType.Info);

            GUI.SetNextControlName("AreaIdField");
            areaIdText = EditorGUILayout.TextField("AreaId", areaIdText);

            EditorGUILayout.Space(10);
            EditorGUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();

            if (GUILayout.Button("确定", GUILayout.Width(90), GUILayout.Height(24)))
            {
                Confirm();
            }

            if (GUILayout.Button("取消", GUILayout.Width(90), GUILayout.Height(24)))
            {
                Close();
            }

            EditorGUILayout.EndHorizontal();

            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Return)
            {
                Confirm();
                Event.current.Use();
            }
        }

        private void OnFocus()
        {
            EditorGUI.FocusTextInControl("AreaIdField");
        }

        private void Confirm()
        {
            if (!int.TryParse(areaIdText, out int areaId))
            {
                EditorUtility.DisplayDialog("错误", "请输入有效的整数 AreaId。", "确定");
                return;
            }

            if (onConfirm == null || onConfirm.Invoke(areaId))
            {
                Close();
            }
        }
    }

    /// <summary>
    /// DecorateCost 独立的批量设置资源消耗弹窗。
    /// </summary>
    public class DecorateCostPlannerBatchCostWindow : EditorWindow
    {
        private int groupCount = 5;
        private int stepCount = 25;
        private TextField costInputField;
        private Action<int[]> onConfirm;

        public static void ShowWindow(int stepCount, Action<int[]> confirmCallback)
        {
            DecorateCostPlannerBatchCostWindow window = CreateInstance<DecorateCostPlannerBatchCostWindow>();
            window.titleContent = new GUIContent("批量设置资源消耗");
            window.minSize = new Vector2(420, 260);
            window.stepCount = Mathf.Max(1, stepCount);
            window.groupCount = Mathf.CeilToInt(window.stepCount / 5f);
            window.onConfirm = confirmCallback;
            window.ShowUtility();
        }

        private void CreateGUI()
        {
            VisualElement root = rootVisualElement;
            root.Clear();
            root.style.paddingTop = 10;
            root.style.paddingBottom = 10;
            root.style.paddingLeft = 10;
            root.style.paddingRight = 10;

            Label title = new Label($"粘贴{groupCount}组资源消耗数值\n支持 Tab、换行、空格、逗号分隔（当前共{stepCount}步）");
            title.style.fontSize = 14;
            title.style.marginBottom = 10;
            title.style.unityTextAlign = TextAnchor.MiddleCenter;
            root.Add(title);

            Label hint = new Label("示例：2200\t5525\t8795\t12065\t15390");
            hint.style.marginBottom = 6;
            root.Add(hint);

            costInputField = new TextField("资源消耗")
            {
                multiline = true,
                value = string.Empty
            };
            costInputField.style.height = 110;
            costInputField.style.whiteSpace = WhiteSpace.Normal;
            costInputField.style.flexGrow = 1;
            root.Add(costInputField);

            VisualElement buttonRow = new VisualElement();
            buttonRow.style.flexDirection = FlexDirection.Row;
            buttonRow.style.marginTop = 15;

            UnityEngine.UIElements.Button confirmBtn = new UnityEngine.UIElements.Button(OnConfirmClicked) { text = "确定" };
            confirmBtn.style.flexGrow = 1;
            confirmBtn.style.marginRight = 5;
            buttonRow.Add(confirmBtn);

            UnityEngine.UIElements.Button cancelBtn = new UnityEngine.UIElements.Button(Close) { text = "取消" };
            cancelBtn.style.flexGrow = 1;
            buttonRow.Add(cancelBtn);

            root.Add(buttonRow);
        }

        private void OnConfirmClicked()
        {
            if (!TryParseIntValues(costInputField?.value, out List<int> costs, out string errorMessage))
            {
                EditorUtility.DisplayDialog("错误", errorMessage, "确定");
                return;
            }

            if (costs.Count != groupCount)
            {
                EditorUtility.DisplayDialog("错误", $"需要粘贴 {groupCount} 个资源消耗值，当前解析到 {costs.Count} 个。", "确定");
                return;
            }

            onConfirm?.Invoke(costs.ToArray());
            Close();
        }

        private static bool TryParseIntValues(string input, out List<int> values, out string errorMessage)
        {
            values = new List<int>();
            errorMessage = null;

            if (string.IsNullOrWhiteSpace(input))
            {
                errorMessage = "请先粘贴资源消耗数据。";
                return false;
            }

            string[] tokens = Regex.Split(input.Trim(), @"[\s,，;；]+")
                .Where(token => !string.IsNullOrWhiteSpace(token))
                .ToArray();

            foreach (string token in tokens)
            {
                if (!int.TryParse(token, out int value))
                {
                    errorMessage = $"存在无法解析的整数：{token}";
                    return false;
                }

                values.Add(value);
            }

            return true;
        }
    }

    /// <summary>
    /// DecorateCost 独立的批量设置步骤批次弹窗。
    /// </summary>
    public class DecorateCostPlannerBatchSkipWindow : EditorWindow
    {
        private int stepCount = 25;
        private TextField batchInputField;
        private Action<int[]> onConfirm;

        public static void ShowWindow(int stepCount, Action<int[]> confirmCallback)
        {
            DecorateCostPlannerBatchSkipWindow window = CreateInstance<DecorateCostPlannerBatchSkipWindow>();
            window.titleContent = new GUIContent("批量设置批次");
            window.minSize = new Vector2(420, 520);
            window.stepCount = Mathf.Max(1, stepCount);
            window.onConfirm = confirmCallback;
            window.ShowUtility();
        }

        private void CreateGUI()
        {
            VisualElement root = rootVisualElement;
            root.Clear();
            root.style.paddingTop = 10;
            root.style.paddingBottom = 10;
            root.style.paddingLeft = 10;
            root.style.paddingRight = 10;

            Label title = new Label($"粘贴{stepCount}个数字设置批次\n支持换行、Tab、空格、逗号分隔；0=空 1=first 2=second 3=third...");
            title.style.fontSize = 14;
            title.style.marginBottom = 10;
            title.style.unityTextAlign = TextAnchor.MiddleCenter;
            root.Add(title);

            Label hint = new Label("示例：每行一个批次编号，或直接粘贴一列 Excel 数据");
            hint.style.marginBottom = 6;
            root.Add(hint);

            batchInputField = new TextField("步骤批次")
            {
                multiline = true,
                value = string.Empty
            };
            batchInputField.style.height = 340;
            batchInputField.style.whiteSpace = WhiteSpace.Normal;
            batchInputField.style.flexGrow = 1;
            root.Add(batchInputField);

            VisualElement buttonRow = new VisualElement();
            buttonRow.style.flexDirection = FlexDirection.Row;
            buttonRow.style.marginTop = 10;

            UnityEngine.UIElements.Button confirmBtn = new UnityEngine.UIElements.Button(OnConfirmClicked) { text = "确定" };
            confirmBtn.style.flexGrow = 1;
            confirmBtn.style.marginRight = 5;
            buttonRow.Add(confirmBtn);

            UnityEngine.UIElements.Button cancelBtn = new UnityEngine.UIElements.Button(Close) { text = "取消" };
            cancelBtn.style.flexGrow = 1;
            buttonRow.Add(cancelBtn);

            root.Add(buttonRow);
        }

        private void OnConfirmClicked()
        {
            if (!TryParseIntValues(batchInputField?.value, out List<int> batches, out string errorMessage))
            {
                EditorUtility.DisplayDialog("错误", errorMessage, "确定");
                return;
            }

            if (batches.Count != stepCount)
            {
                EditorUtility.DisplayDialog("错误", $"需要粘贴 {stepCount} 个批次值，当前解析到 {batches.Count} 个。", "确定");
                return;
            }

            onConfirm?.Invoke(batches.ToArray());
            Close();
        }

        private static bool TryParseIntValues(string input, out List<int> values, out string errorMessage)
        {
            values = new List<int>();
            errorMessage = null;

            if (string.IsNullOrWhiteSpace(input))
            {
                errorMessage = "请先粘贴批次数据。";
                return false;
            }

            string[] tokens = Regex.Split(input.Trim(), @"[\s,，;；]+")
                .Where(token => !string.IsNullOrWhiteSpace(token))
                .ToArray();

            foreach (string token in tokens)
            {
                if (!int.TryParse(token, out int value))
                {
                    errorMessage = $"存在无法解析的整数：{token}";
                    return false;
                }

                values.Add(value);
            }

            return true;
        }
    }
}
