using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
using OfficeOpenXml;
using ArtResource;
using DesignTools.Common;
using Debug = UnityEngine.Debug;

namespace DesignTools.Scene
{
    /// <summary>
    /// 场景进度奖励配置Editor工具
    /// 读取Docs/config/IndoorProgress.xlsx和Item.xlsx
    /// </summary>
    public class IndoorProgressEditor : EditorWindow
    {
        private const string ART_SO_PATH = "Assets/Art_SubModule/Art_SO";
        private const string INDOOR_PROGRESS_EXCEL_NAME = "IndoorProgress.xlsx";
        private const string ITEM_EXCEL_NAME = "Item.xlsx";
        private const string INDOOR_PROGRESS_SHEET_NAME = "IndoorProgress";
        private const string ITEM_SHEET_NAME = "Item";
        private const string DOCS_PATH_PREF_KEY = "IndoorProgressEditor_DocsPath";
        private const string DESIGN_SUBMODULE_PATH = "Assets/Design_SubModule";
        
        // IType类型定义（从ItemConfigEditor复制）
        private static readonly Dictionary<int, string> ITEM_TYPES = new Dictionary<int, string>
        {
            { 1, "能量" },
            { 2, "星星" },
            { 3, "钻石" },
            { 97, "Playroom宠物道具" },
            { 98, "卡牌" },
            { 99, "背包道具" },
            { 100, "棋子" },
            { 101, "卡包" },
            { 102, "限时事件" },
            { 103, "小猪存钱罐" },
            { 104, "万能卡" },
            { 105, "头像框" },
            { 106, "活动代币" },
            { 107, "竞赛游戏代币" },
            { 108, "Pet Playroom拜访道具" },
            { 109, "表情" },
            { 110, "头像" },
            { 111, "Playroom装饰" },
            { 112, "Playroom服装" },
            { 113, "Playroom装饰套装" },
            { 114, "Playroom服装套装" },
            { 115, "Playroom道具宝箱" },
            { 116, "活动通行证代币道具" }
        };
        
        // 特殊Item的映射关系
        private static readonly Dictionary<int, string> MY_ITEM_DICT = new Dictionary<int, string>()
        {
            [100001] = "Energy",
            [100002] = "Star",
            [100003] = "Diamond",
            [100004] = "Cardpack1",
            [100005] = "Cardpack2",
            [100006] = "Cardpack3",
            [100007] = "Cardpack4",
            [100008] = "Cardpack5",
            [100011] = "LimitEvent4",
            [100012] = "LimitEvent2",
            [100013] = "LimitEvent3",
            [100014] = "LimitEvent1",
            [100015] = "LimitEvent5",
            [100016] = "LimitEvent6",
            [100017] = "LimitEvent7",
            [100018] = "LimitEvent9",
            [100019] = "LimitEvent10",
            [100020] = "LimitEvent8",
            [100022] = "PurplePig",
            [101149] = "LimitEvent2",
            [101150] = "LimitEvent3",
            [101151] = "LimitEvent4",
            [1021] = "705",
            [1006] = "702",
            [1007] = "703",
            [100035] = "Battery",
            [101445] = "BagItemBox1",
            [101446] = "BagItemBox2",
            [101447] = "BagItemBox3",
        };

        private string docsRootPath = "";
        private List<IndoorProgressData> allProgressDataList = new List<IndoorProgressData>();
        private List<IndoorProgressData> filteredProgressDataList = new List<IndoorProgressData>();
        private Dictionary<int, ItemData> itemDict = new Dictionary<int, ItemData>(); // Id -> ItemData
        private List<ArtTableSO> allArtTables = new List<ArtTableSO>();

        private Vector2 scrollPosition;
        private bool isDataLoaded = false;
        private int selectedScene = -1;
        private string sceneInputText = "";
        
        // 道具奖励临时编辑状态（按数据ID存储）
        private Dictionary<int, int> tempItemRewardTypeIndex = new Dictionary<int, int>();
        private Dictionary<int, int> tempItemRewardInputId = new Dictionary<int, int>();
        
        // 区域奖励临时编辑状态（按数据ID存储）
        private Dictionary<int, int> tempAreaRewardTypeIndex = new Dictionary<int, int>();
        private Dictionary<int, int> tempAreaRewardItemId = new Dictionary<int, int>();
        private Dictionary<int, int> tempAreaRewardNum = new Dictionary<int, int>();
        
        // 所有IType列表（动态生成）
        private List<int> allItemTypes = new List<int>();

        [MenuItem("策划工具/场景/场景进度奖励")]
        public static void ShowWindow()
        {
            var window = GetWindow<IndoorProgressEditor>("场景进度奖励配置");
            window.minSize = new Vector2(1400, 700);
            window.Show();
        }

        private void OnEnable()
        {
            // 读取上次保存的路径
            if (EditorPrefs.HasKey(DOCS_PATH_PREF_KEY))
            {
                docsRootPath = EditorPrefs.GetString(DOCS_PATH_PREF_KEY);
            }
        }

        private void OnGUI()
        {
            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
            EditorGUILayout.LabelField("场景进度奖励配置工具", EditorStyles.boldLabel);
            GUILayout.FlexibleSpace();
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space(5);

            // Docs路径选择
            EditorGUILayout.BeginVertical("box");
            EditorGUILayout.LabelField("Docs项目根目录", EditorStyles.boldLabel);
            
            EditorGUILayout.BeginHorizontal();
            docsRootPath = EditorGUILayout.TextField("路径", docsRootPath);
            if (GUILayout.Button("选择文件夹", GUILayout.Width(100)))
            {
                string selectedPath = EditorUtility.OpenFolderPanel("选择Docs项目根目录", "", "");
                if (!string.IsNullOrEmpty(selectedPath))
                {
                    docsRootPath = selectedPath;
                    EditorPrefs.SetString(DOCS_PATH_PREF_KEY, docsRootPath);
                }
            }
            EditorGUILayout.EndHorizontal();

            if (GUILayout.Button("加载配置数据", GUILayout.Height(30)))
            {
                LoadData();
            }

            EditorGUILayout.EndVertical();

            EditorGUILayout.Space(5);

            // 数据编辑区域
            if (isDataLoaded)
            {
                DrawSceneFilterAndDataEditor();
            }
            else
            {
                EditorGUILayout.HelpBox("请先选择Docs根目录并加载配置数据", MessageType.Info);
            }
        }

        /// <summary>
        /// 加载配置数据
        /// </summary>
        private void LoadData()
        {
            if (string.IsNullOrEmpty(docsRootPath))
            {
                EditorUtility.DisplayDialog("错误", "请先选择Docs根目录", "确定");
                return;
            }

            try
            {
                // 检查并更新Docs仓库
                if (!CheckAndUpdateDocsRepository())
                {
                    return;
                }

                // 检查并切换Design_SubModule到main分支
                if (!CheckAndSwitchDesignSubModuleBranch())
                {
                    return;
                }

                // 加载所有Art_SO资源
                LoadAllArtTableSO();

                // 加载Item数据
                LoadItemData();

                // 加载IndoorProgress数据
                LoadIndoorProgressData();

                isDataLoaded = true;
                selectedScene = -1;
                sceneInputText = "";
                filteredProgressDataList.Clear();

                EditorUtility.DisplayDialog("成功", "配置数据加载完成！", "确定");
            }
            catch (Exception e)
            {
                EditorUtility.DisplayDialog("错误", $"加载数据失败: {e.Message}\n{e.StackTrace}", "确定");
                isDataLoaded = false;
            }
        }

        /// <summary>
        /// 执行Git命令
        /// </summary>
        private string ExecuteGitCommand(string workingDirectory, string arguments, out bool success)
        {
            try
            {
                var processInfo = new ProcessStartInfo
                {
                    FileName = "git",
                    Arguments = arguments,
                    WorkingDirectory = workingDirectory,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true
                };

                using (var process = Process.Start(processInfo))
                {
                    string output = process.StandardOutput.ReadToEnd();
                    string error = process.StandardError.ReadToEnd();
                    process.WaitForExit();

                    success = process.ExitCode == 0;
                    return success ? output : error;
                }
            }
            catch (Exception e)
            {
                success = false;
                return $"执行Git命令失败: {e.Message}";
            }
        }

        /// <summary>
        /// 检查并更新Docs仓库
        /// </summary>
        private bool CheckAndUpdateDocsRepository()
        {
            string gitPath = Path.Combine(docsRootPath, ".git");
            if (!Directory.Exists(gitPath))
            {
                EditorUtility.DisplayDialog("错误", 
                    $"所选目录不是Git仓库：{docsRootPath}\n请确保选择的是Docs项目的根目录。", 
                    "确定");
                return false;
            }

            string fetchResult = ExecuteGitCommand(docsRootPath, "fetch", out bool fetchSuccess);
            
            if (!fetchSuccess)
            {
                bool continueAnyway = EditorUtility.DisplayDialog("警告", 
                    $"Git fetch失败：{fetchResult}\n\n是否继续？", 
                    "继续", "取消");
                return continueAnyway;
            }

            string statusResult = ExecuteGitCommand(docsRootPath, "status", out bool statusSuccess);
            
            if (!statusSuccess)
            {
                EditorUtility.DisplayDialog("错误", 
                    $"Git status检查失败：{statusResult}", 
                    "确定");
                return false;
            }

            if (statusResult.Contains("Changes not staged") || statusResult.Contains("Changes to be committed"))
            {
                bool proceed = EditorUtility.DisplayDialog("提示", 
                    "Docs仓库有未提交的修改。\n\n建议先提交或暂存这些修改。\n\n是否继续？", 
                    "继续", "取消");
                
                if (!proceed)
                {
                    return false;
                }
            }

            if (statusResult.Contains("Your branch is behind"))
            {
                bool doPull = EditorUtility.DisplayDialog("提示", 
                    "Docs仓库有远程更新。\n\n是否执行git pull拉取最新代码？\n（建议执行以获取最新配置）", 
                    "执行Pull", "跳过");
                
                if (doPull)
                {
                    string pullResult = ExecuteGitCommand(docsRootPath, "pull", out bool pullSuccess);
                    
                    if (!pullSuccess)
                    {
                        if (pullResult.Contains("CONFLICT") || pullResult.Contains("conflict"))
                        {
                            EditorUtility.DisplayDialog("错误", 
                                $"Git pull遇到冲突：\n{pullResult}\n\n请先在SourceTree或其他Git工具中解决冲突。", 
                                "确定");
                        }
                        else
                        {
                            EditorUtility.DisplayDialog("错误", 
                                $"Git pull失败：{pullResult}", 
                                "确定");
                        }
                        return false;
                    }

                    EditorUtility.DisplayDialog("成功", "已拉取最新代码！", "确定");
                }
            }
            else
            {
                Debug.Log("Docs仓库已是最新");
            }

            return true;
        }

        /// <summary>
        /// 检查并切换Design_SubModule到main分支
        /// </summary>
        private bool CheckAndSwitchDesignSubModuleBranch()
        {
            string designSubModulePath = Path.Combine(Application.dataPath.Replace("/Assets", ""), DESIGN_SUBMODULE_PATH);
            designSubModulePath = designSubModulePath.Replace("\\", "/");

            if (!Directory.Exists(designSubModulePath))
            {
                EditorUtility.DisplayDialog("错误", 
                    $"Design_SubModule目录不存在：{designSubModulePath}", 
                    "确定");
                return false;
            }

            string branchResult = ExecuteGitCommand(designSubModulePath, "rev-parse --abbrev-ref HEAD", out bool branchSuccess);
            
            if (!branchSuccess)
            {
                EditorUtility.DisplayDialog("错误", 
                    $"无法获取Design_SubModule当前分支：{branchResult}", 
                    "确定");
                return false;
            }

            string currentBranch = branchResult.Trim();
            
            if (currentBranch != "main")
            {
                bool doCheckout = EditorUtility.DisplayDialog("提示", 
                    $"Design_SubModule当前在 '{currentBranch}' 分支。\n\n是否切换到main分支？", 
                    "切换到main", "取消");
                
                if (doCheckout)
                {
                    string checkoutResult = ExecuteGitCommand(designSubModulePath, "checkout main", out bool checkoutSuccess);
                    
                    if (!checkoutSuccess)
                    {
                        EditorUtility.DisplayDialog("错误", 
                            $"切换到main分支失败：{checkoutResult}", 
                            "确定");
                        return false;
                    }

                    EditorUtility.DisplayDialog("成功", "已切换到main分支！", "确定");
                }
                else
                {
                    return false;
                }
            }
            else
            {
                Debug.Log("Design_SubModule已在main分支");
            }

            return true;
        }

        /// <summary>
        /// 加载所有Art_SO资源
        /// </summary>
        private void LoadAllArtTableSO()
        {
            allArtTables.Clear();

            string[] guids = AssetDatabase.FindAssets("t:ArtTableSO", new[] { ART_SO_PATH });
            foreach (string guid in guids)
            {
                string path = AssetDatabase.GUIDToAssetPath(guid);
                ArtTableSO artTable = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
                if (artTable != null)
                {
                    allArtTables.Add(artTable);
                }
            }

            Debug.Log($"加载了 {allArtTables.Count} 个ArtTableSO资源");
        }

        /// <summary>
        /// 加载Item数据
        /// </summary>
        private void LoadItemData()
        {
            itemDict.Clear();

            string itemExcelPath = Path.Combine(docsRootPath, "config", ITEM_EXCEL_NAME);
            if (!File.Exists(itemExcelPath))
            {
                throw new Exception($"未找到Item配置文件: {itemExcelPath}");
            }

            using (var package = new ExcelPackage(new FileInfo(itemExcelPath)))
            {
                var worksheet = package.Workbook.Worksheets[ITEM_SHEET_NAME];
                if (worksheet == null)
                {
                    throw new Exception($"Item.xlsx中未找到Sheet: {ITEM_SHEET_NAME}");
                }

                // 读取表头（第1行）
                int idCol = -1, nameCol = -1, iTypeCol = -1, resCol = -1;
                int columnCount = worksheet.Dimension.Columns;

                for (int col = 1; col <= columnCount; col++)
                {
                    string header = worksheet.Cells[1, col].Text;
                    if (header == "Id") idCol = col;
                    else if (header == "Name") nameCol = col;
                    else if (header == "IType") iTypeCol = col;
                    else if (header == "Res") resCol = col;
                }

                if (idCol < 0 || nameCol < 0 || iTypeCol < 0)
                {
                    throw new Exception("Item.xlsx表结构不正确，缺少必要列（Id/Name/IType）");
                }

                // 读取数据（从第3行开始）
                int rowCount = worksheet.Dimension.Rows;
                for (int row = 3; row <= rowCount; row++)
                {
                    string idText = worksheet.Cells[row, idCol].Text;
                    if (string.IsNullOrEmpty(idText)) continue;

                    if (!int.TryParse(idText, out int id)) continue;

                    string name = worksheet.Cells[row, nameCol].Text;
                    string iTypeText = worksheet.Cells[row, iTypeCol].Text;
                    string res = resCol > 0 ? worksheet.Cells[row, resCol].Text : "";

                    if (!int.TryParse(iTypeText, out int iType)) continue;

                    itemDict[id] = new ItemData
                    {
                        Id = id,
                        Name = name,
                        IType = iType,
                        Res = res
                    };
                }
            }

            Debug.Log($"加载了 {itemDict.Count} 个Item数据");
            
            // 生成所有IType列表
            allItemTypes = itemDict.Values.Select(x => x.IType).Distinct().OrderBy(x => x).ToList();
        }

        /// <summary>
        /// 加载IndoorProgress数据
        /// </summary>
        private void LoadIndoorProgressData()
        {
            allProgressDataList.Clear();

            string progressExcelPath = Path.Combine(docsRootPath, "config", INDOOR_PROGRESS_EXCEL_NAME);
            if (!File.Exists(progressExcelPath))
            {
                throw new Exception($"未找到IndoorProgress配置文件: {progressExcelPath}");
            }

            using (var package = new ExcelPackage(new FileInfo(progressExcelPath)))
            {
                var worksheet = package.Workbook.Worksheets[INDOOR_PROGRESS_SHEET_NAME];
                if (worksheet == null)
                {
                    throw new Exception($"IndoorProgress.xlsx中未找到Sheet: {INDOOR_PROGRESS_SHEET_NAME}");
                }

                // 读取表头（第1行）
                int idCol = -1, sceneCol = -1, lvCol = -1, itemCol = -1, emitCol = -1, 
                    rewardCol = -1, bigRewardCol = -1, areaRewardCol = -1, partCol = -1;
                int columnCount = worksheet.Dimension.Columns;

                for (int col = 1; col <= columnCount; col++)
                {
                    string header = worksheet.Cells[1, col].Text;
                    if (header == "Id") idCol = col;
                    else if (header == "Scene") sceneCol = col;
                    else if (header == "Lv") lvCol = col;
                    else if (header == "Item") itemCol = col;
                    else if (header == "Emit") emitCol = col;
                    else if (header == "Reward") rewardCol = col;
                    else if (header == "BigReward") bigRewardCol = col;
                    else if (header == "AreaReward") areaRewardCol = col;
                    else if (header == "Part") partCol = col;
                }

                if (idCol < 0 || sceneCol < 0 || lvCol < 0)
                {
                    throw new Exception("IndoorProgress.xlsx表结构不正确，缺少必要列（Id/Scene/Lv）");
                }

                // 读取数据（从第3行开始）
                int rowCount = worksheet.Dimension.Rows;
                for (int row = 3; row <= rowCount; row++)
                {
                    string idText = worksheet.Cells[row, idCol].Text;
                    if (string.IsNullOrEmpty(idText)) continue;

                    if (!int.TryParse(idText, out int id)) continue;

                    string sceneText = worksheet.Cells[row, sceneCol].Text;
                    string lvText = worksheet.Cells[row, lvCol].Text;
                    
                    if (!int.TryParse(sceneText, out int scene)) continue;
                    if (!int.TryParse(lvText, out int lv)) continue;

                    string item = itemCol > 0 ? worksheet.Cells[row, itemCol].Text : "";
                    string emit = emitCol > 0 ? worksheet.Cells[row, emitCol].Text : "";
                    string reward = rewardCol > 0 ? worksheet.Cells[row, rewardCol].Text : "";
                    string bigReward = bigRewardCol > 0 ? worksheet.Cells[row, bigRewardCol].Text : "";
                    string areaReward = areaRewardCol > 0 ? worksheet.Cells[row, areaRewardCol].Text : "";
                    string partText = partCol > 0 ? worksheet.Cells[row, partCol].Text : "";

                    int.TryParse(partText, out int part);

                    var progressData = new IndoorProgressData
                    {
                        Id = id,
                        Scene = scene,
                        Lv = lv,
                        Item = item,
                        Emit = emit,
                        Reward = reward,
                        BigReward = bigReward,
                        AreaReward = areaReward,
                        Part = part
                    };

                    allProgressDataList.Add(progressData);
                }
            }

            Debug.Log($"加载了 {allProgressDataList.Count} 条IndoorProgress数据");
        }

        /// <summary>
        /// 绘制场景筛选和数据编辑器
        /// </summary>
        private void DrawSceneFilterAndDataEditor()
        {
            EditorGUILayout.BeginVertical("box");
            
            // 场景筛选
            EditorGUILayout.LabelField("场景筛选", EditorStyles.boldLabel);
            EditorGUILayout.BeginHorizontal();
            
            sceneInputText = EditorGUILayout.TextField("输入场景ID", sceneInputText, GUILayout.Width(200));
            
            if (GUILayout.Button("确认加载场景", GUILayout.Width(120)))
            {
                if (int.TryParse(sceneInputText, out int sceneId))
                {
                    selectedScene = sceneId;
                    FilterProgressByScene();
                }
                else
                {
                    EditorUtility.DisplayDialog("错误", "请输入有效的场景ID（数字）", "确定");
                }
            }
            
            if (selectedScene > 0)
            {
                EditorGUILayout.LabelField($"当前场景: {selectedScene}", EditorStyles.boldLabel, GUILayout.Width(150));
            }
            
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();

            if (selectedScene > 0 && filteredProgressDataList.Count > 0)
            {
                EditorGUILayout.Space(10);
                
                // 新增场景按钮
                EditorGUILayout.BeginHorizontal();
                if (GUILayout.Button("+ 新增场景", GUILayout.Height(30), GUILayout.Width(150)))
                {
                    AddNewScene();
                }
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();
                
                EditorGUILayout.Space(5);
                
                // 数据列表
                scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
                
                EditorGUILayout.BeginVertical("box");
                DrawProgressDataList();
                EditorGUILayout.EndVertical();
                
                EditorGUILayout.EndScrollView();
                
                EditorGUILayout.Space(10);
                
                // 保存按钮
                EditorGUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("保存配置到Excel", GUILayout.Height(40), GUILayout.Width(200)))
                {
                    SaveData();
                }
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();
            }
            else if (selectedScene > 0)
            {
                EditorGUILayout.Space(10);
                EditorGUILayout.HelpBox($"场景 {selectedScene} 没有数据", MessageType.Warning);
                
                // 新增场景按钮
                EditorGUILayout.BeginHorizontal();
                if (GUILayout.Button("+ 新增场景", GUILayout.Height(30), GUILayout.Width(150)))
                {
                    AddNewScene();
                }
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();
            }
            else
            {
                EditorGUILayout.Space(10);
                EditorGUILayout.HelpBox("请输入场景ID并点击确认加载", MessageType.Info);
            }
        }

        /// <summary>
        /// 根据场景筛选数据
        /// </summary>
        private void FilterProgressByScene()
        {
            filteredProgressDataList = allProgressDataList
                .Where(x => x.Scene == selectedScene)
                .OrderBy(x => x.Lv)
                .ToList();
        }

        /// <summary>
        /// 绘制进度数据列表
        /// </summary>
        private void DrawProgressDataList()
        {
            // 表头
            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
            EditorGUILayout.LabelField("ID", EditorStyles.boldLabel, GUILayout.Width(40));
            EditorGUILayout.LabelField("Lv", EditorStyles.boldLabel, GUILayout.Width(40));
            EditorGUILayout.LabelField("道具奖励", EditorStyles.boldLabel, GUILayout.Width(450));
            EditorGUILayout.LabelField("区域奖励", EditorStyles.boldLabel, GUILayout.Width(450));
            EditorGUILayout.LabelField("零件", EditorStyles.boldLabel, GUILayout.Width(60));
            EditorGUILayout.LabelField("操作", EditorStyles.boldLabel, GUILayout.Width(60));
            EditorGUILayout.EndHorizontal();

            // 数据行
            for (int i = 0; i < filteredProgressDataList.Count; i++)
            {
                DrawProgressDataRow(filteredProgressDataList[i], i);
            }
        }

        /// <summary>
        /// 绘制单行进度数据
        /// </summary>
        private void DrawProgressDataRow(IndoorProgressData data, int index)
        {
            EditorGUILayout.BeginHorizontal("box");
            
            // ID（不可编辑）
            EditorGUILayout.LabelField(data.Id.ToString(), GUILayout.Width(40));
            
            // Lv（可编辑）
            EditorGUI.BeginChangeCheck();
            int newLv = EditorGUILayout.IntField(data.Lv, GUILayout.Width(40));
            if (EditorGUI.EndChangeCheck())
            {
                data.Lv = newLv;
            }
            
            // 道具奖励（Item/Emit/Reward一体）
            EditorGUILayout.BeginVertical(GUILayout.Width(450));
            DrawItemRewardEditor(data);
            EditorGUILayout.EndVertical();
            
            // 区域奖励（AreaReward/BigReward）
            EditorGUILayout.BeginVertical(GUILayout.Width(450));
            DrawAreaRewardEditor(data);
            EditorGUILayout.EndVertical();
            
            // 零件数量
            EditorGUI.BeginChangeCheck();
            int newPart = EditorGUILayout.IntField(data.Part, GUILayout.Width(60));
            if (EditorGUI.EndChangeCheck())
            {
                data.Part = newPart;
            }
            
            // 操作按钮
            if (GUILayout.Button("删除", GUILayout.Width(60)))
            {
                if (EditorUtility.DisplayDialog("确认删除", 
                    $"确定要删除ID {data.Id} (场景{data.Scene}-Lv{data.Lv}) 的数据吗？", 
                    "删除", "取消"))
                {
                    filteredProgressDataList.RemoveAt(index);
                    allProgressDataList.Remove(data);
                }
            }
            
            EditorGUILayout.EndHorizontal();
        }

        /// <summary>
        /// 绘制道具奖励编辑器（Item/Emit/Reward）
        /// 使用输入框+查找按钮+弹窗选择的方式，支持所有类型
        /// </summary>
        private void DrawItemRewardEditor(IndoorProgressData data)
        {
            // 解析当前数据
            var itemReward = ParseItemReward(data.Item);
            
            EditorGUILayout.BeginVertical();
            EditorGUILayout.BeginHorizontal();
            
            // 选择IType
            var typeOptions = new List<string> { "无" };
            var typeValues = new List<int> { -1 };
            
            foreach (var kvp in ITEM_TYPES.OrderBy(x => x.Key))
            {
                typeOptions.Add($"{kvp.Value} ({kvp.Key})");
                typeValues.Add(kvp.Key);
            }
            
            // 初始化临时状态
            if (!tempItemRewardTypeIndex.ContainsKey(data.Id))
            {
                if (itemReward.HasValue)
                {
                    int itemType = GetItemType(itemReward.Value.Id);
                    tempItemRewardTypeIndex[data.Id] = typeValues.IndexOf(itemType);
                }
                else
                {
                    tempItemRewardTypeIndex[data.Id] = 0;
                }
            }
            else if (itemReward.HasValue)
            {
                int itemType = GetItemType(itemReward.Value.Id);
                int typeIndex = typeValues.IndexOf(itemType);
                if (typeIndex >= 0)
                {
                    tempItemRewardTypeIndex[data.Id] = typeIndex;
                }
            }
            
            // 初始化输入ID缓存
            if (!tempItemRewardInputId.ContainsKey(data.Id))
            {
                tempItemRewardInputId[data.Id] = itemReward.HasValue ? itemReward.Value.Id : 0;
            }
            
            int currentTypeIndex = tempItemRewardTypeIndex[data.Id];
            if (currentTypeIndex < 0) currentTypeIndex = 0;
            
            EditorGUI.BeginChangeCheck();
            int newTypeIndex = EditorGUILayout.Popup(currentTypeIndex, typeOptions.ToArray(), GUILayout.Width(120));
            bool typeChanged = EditorGUI.EndChangeCheck();
            
            if (typeChanged)
            {
                tempItemRewardTypeIndex[data.Id] = newTypeIndex;
            }
            
            if (newTypeIndex == 0)
            {
                // 选择"无"
                if (itemReward.HasValue)
                {
                    data.Item = "";
                    data.Emit = "";
                    data.Reward = "";
                    tempItemRewardInputId[data.Id] = 0;
                }
            }
            else
            {
                int selectedType = typeValues[newTypeIndex];
                
                // 如果类型改变，且当前有数据但类型不匹配，清空数据
                if (typeChanged && itemReward.HasValue && GetItemType(itemReward.Value.Id) != selectedType)
                {
                    data.Item = "";
                    data.Emit = "";
                    data.Reward = "";
                    itemReward = null;
                    tempItemRewardInputId[data.Id] = 0;
                }
                
                // 统一使用输入框+查找按钮方式
                int inputId = tempItemRewardInputId[data.Id];
                
                EditorGUILayout.LabelField("ID:", GUILayout.Width(25));
                int newInputId = EditorGUILayout.IntField(inputId, GUILayout.Width(70));
                if (newInputId != inputId)
                {
                    tempItemRewardInputId[data.Id] = newInputId;
                    if (itemDict.ContainsKey(newInputId))
                    {
                        int num = itemReward.HasValue ? itemReward.Value.Num : 1;
                        UpdateItemReward(data, newInputId, num);
                        // 同步类型选择
                        int newItemType = GetItemType(newInputId);
                        int newTypeIdx = typeValues.IndexOf(newItemType);
                        if (newTypeIdx >= 0) tempItemRewardTypeIndex[data.Id] = newTypeIdx;
                    }
                }
                
                // 查找按钮
                GUI.backgroundColor = new Color(0.75f, 0.9f, 1f);
                if (GUILayout.Button("查找", GUILayout.Width(45), GUILayout.Height(18)))
                {
                    int capturedDataId = data.Id;
                    int currentType = selectedType;
                    EditorApplication.delayCall += () => OpenItemPickerForReward(capturedDataId, currentType);
                    GUI.backgroundColor = Color.white;
                    GUIUtility.ExitGUI();
                }
                GUI.backgroundColor = Color.white;
                
                // 数量
                EditorGUILayout.LabelField("x", GUILayout.Width(10));
                int currentNum = itemReward.HasValue ? itemReward.Value.Num : 1;
                EditorGUI.BeginChangeCheck();
                currentNum = EditorGUILayout.IntField(currentNum, GUILayout.Width(40));
                if (EditorGUI.EndChangeCheck())
                {
                    int currentId = tempItemRewardInputId[data.Id];
                    if (currentId > 0 && itemDict.ContainsKey(currentId))
                    {
                        UpdateItemReward(data, currentId, currentNum);
                    }
                }
                
                // 显示预览图
                int previewId = tempItemRewardInputId[data.Id];
                if (previewId > 0 && itemDict.TryGetValue(previewId, out var previewItem))
                {
                    DrawItemPreview(previewItem);
                }
                else
                {
                    EditorGUILayout.LabelField("无", GUILayout.Width(50));
                }
            }
            
            EditorGUILayout.EndHorizontal();
            
            // 显示当前道具名称
            if (itemReward.HasValue && itemDict.TryGetValue(itemReward.Value.Id, out var currentItem))
            {
                EditorGUILayout.LabelField($"  当前: {currentItem.Name} ({currentItem.Id})", EditorStyles.miniLabel);
            }
            
            EditorGUILayout.EndVertical();
        }
        
        /// <summary>
        /// 打开Item选择弹窗（道具奖励用）
        /// </summary>
        private void OpenItemPickerForReward(int dataId, int currentType)
        {
            var data = allProgressDataList.FirstOrDefault(x => x.Id == dataId);
            if (data == null) data = filteredProgressDataList.FirstOrDefault(x => x.Id == dataId);
            if (data == null) return;
            
            var itemReward = ParseItemReward(data.Item);
            int selectedItemId = itemReward.HasValue ? itemReward.Value.Id : 0;
            
            DesignToolItemPickerWindow.ShowWindow(
                itemDict.Values
                    .Select(x => new DesignToolItemPickerItem { Id = x.Id, Name = x.Name, IType = x.IType })
                    .ToList(),
                allItemTypes,
                ITEM_TYPES,
                currentType,
                selectedItemId,
                position,
                pickedId =>
                {
                    if (itemDict.ContainsKey(pickedId))
                    {
                        int num = itemReward.HasValue ? itemReward.Value.Num : 1;
                        UpdateItemReward(data, pickedId, num);
                        tempItemRewardInputId[dataId] = pickedId;
                        // 同步类型
                        int pickedType = GetItemType(pickedId);
                        var typeValues2 = new List<int> { -1 };
                        foreach (var kvp in ITEM_TYPES.OrderBy(x => x.Key))
                            typeValues2.Add(kvp.Key);
                        int typeIdx = typeValues2.IndexOf(pickedType);
                        if (typeIdx >= 0) tempItemRewardTypeIndex[dataId] = typeIdx;
                        Repaint();
                    }
                });
        }

        /// <summary>
        /// 绘制区域奖励编辑器（AreaReward/BigReward）
        /// </summary>
        private void DrawAreaRewardEditor(IndoorProgressData data)
        {
            // 判断当前Lv是否可以配置AreaReward
            bool canConfigArea = CanConfigAreaReward(data.Scene, data.Lv);
            
            if (!canConfigArea)
            {
                // 不显示任何内容，保持空白
                return;
            }
            
            // 解析当前AreaReward
            var areaRewards = ParseAreaReward(data.AreaReward);
            
            EditorGUILayout.BeginVertical();
            
            // 显示现有奖励
            for (int i = 0; i < areaRewards.Count; i++)
            {
                EditorGUILayout.BeginHorizontal();
                
                var reward = areaRewards[i];
                
                // 显示Item信息和图片
                if (itemDict.TryGetValue(reward.Id, out var rewardItem))
                {
                    EditorGUILayout.LabelField($"{rewardItem.Name}", GUILayout.Width(100));
                    
                    // 显示预览图
                    DrawItemPreview(rewardItem);
                }
                else
                {
                    EditorGUILayout.LabelField($"ID:{reward.Id}", GUILayout.Width(100));
                    EditorGUILayout.LabelField("无图", GUILayout.Width(50));
                }
                
                // 数量
                EditorGUILayout.LabelField("x", GUILayout.Width(10));
                EditorGUI.BeginChangeCheck();
                int newNum = EditorGUILayout.IntField(reward.Num, GUILayout.Width(40));
                if (EditorGUI.EndChangeCheck())
                {
                    areaRewards[i] = new ItemReward { Id = reward.Id, Num = newNum };
                    UpdateAreaReward(data, areaRewards);
                }
                
                // 删除按钮
                if (GUILayout.Button("-", GUILayout.Width(30)))
                {
                    areaRewards.RemoveAt(i);
                    UpdateAreaReward(data, areaRewards);
                    break;
                }
                
                EditorGUILayout.EndHorizontal();
            }
            
            // 添加新奖励UI
            DrawAddAreaRewardUI(data, areaRewards);
            
            EditorGUILayout.EndVertical();
        }

        /// <summary>
        /// 判断是否可以配置AreaReward
        /// </summary>
        private bool CanConfigAreaReward(int scene, int lv)
        {
            if (scene == 1)
            {
                // 场景1: 20, 29, 36, 44
                return lv == 20 || lv == 29 || lv == 36 || lv == 44;
            }
            else if (scene >= 2 && scene <= 5)
            {
                // 场景2-5: 20
                return lv == 20;
            }
            else
            {
                // 其他场景: 25
                return lv == 25;
            }
        }

        /// <summary>
        /// 绘制添加区域奖励UI
        /// 使用输入框+查找按钮+弹窗选择的方式
        /// </summary>
        private void DrawAddAreaRewardUI(IndoorProgressData data, List<ItemReward> areaRewards)
        {
            EditorGUILayout.BeginHorizontal();
            
            // 使用临时变量存储当前选择
            if (!tempAreaRewardItemId.ContainsKey(data.Id))
            {
                tempAreaRewardItemId[data.Id] = 0;
            }
            if (!tempAreaRewardNum.ContainsKey(data.Id))
            {
                tempAreaRewardNum[data.Id] = 1;
            }
            
            // 输入ID
            EditorGUILayout.LabelField("ID:", GUILayout.Width(25));
            int inputId = tempAreaRewardItemId[data.Id];
            int newInputId = EditorGUILayout.IntField(inputId, GUILayout.Width(70));
            if (newInputId != inputId)
            {
                tempAreaRewardItemId[data.Id] = newInputId;
            }
            
            // 查找按钮
            GUI.backgroundColor = new Color(0.75f, 0.9f, 1f);
            if (GUILayout.Button("查找", GUILayout.Width(45), GUILayout.Height(18)))
            {
                int capturedDataId = data.Id;
                EditorApplication.delayCall += () => OpenItemPickerForAreaReward(capturedDataId);
                GUI.backgroundColor = Color.white;
                GUIUtility.ExitGUI();
            }
            GUI.backgroundColor = Color.white;
            
            // 显示道具名称
            int currentInputId = tempAreaRewardItemId[data.Id];
            if (currentInputId > 0 && itemDict.TryGetValue(currentInputId, out var inputItem))
            {
                EditorGUILayout.LabelField($"{inputItem.Name}", EditorStyles.miniLabel, GUILayout.Width(100));
            }
            else if (currentInputId > 0)
            {
                Color oldColor = GUI.color;
                GUI.color = new Color(1f, 0.35f, 0.35f);
                EditorGUILayout.LabelField("未找到", EditorStyles.miniLabel, GUILayout.Width(100));
                GUI.color = oldColor;
            }
            
            // 数量
            EditorGUILayout.LabelField("x", GUILayout.Width(10));
            int num = tempAreaRewardNum[data.Id];
            num = EditorGUILayout.IntField(num, GUILayout.Width(40));
            tempAreaRewardNum[data.Id] = num;
            
            // 添加按钮
            GUI.backgroundColor = Color.green;
            if (GUILayout.Button("+添加", GUILayout.Width(50)))
            {
                int addId = tempAreaRewardItemId[data.Id];
                if (addId > 0 && itemDict.ContainsKey(addId))
                {
                    areaRewards.Add(new ItemReward { Id = addId, Num = tempAreaRewardNum[data.Id] });
                    UpdateAreaReward(data, areaRewards);
                    // 重置
                    tempAreaRewardItemId[data.Id] = 0;
                    tempAreaRewardNum[data.Id] = 1;
                }
                else
                {
                    EditorUtility.DisplayDialog("错误", $"ID {addId} 不存在于Item表中", "确定");
                }
            }
            GUI.backgroundColor = Color.white;
            
            EditorGUILayout.EndHorizontal();
        }
        
        /// <summary>
        /// 打开Item选择弹窗（区域奖励用）
        /// </summary>
        private void OpenItemPickerForAreaReward(int dataId)
        {
            int currentItemId = tempAreaRewardItemId.ContainsKey(dataId) ? tempAreaRewardItemId[dataId] : 0;
            int currentType = currentItemId > 0 && itemDict.ContainsKey(currentItemId) ? itemDict[currentItemId].IType : -1;
            
            DesignToolItemPickerWindow.ShowWindow(
                itemDict.Values
                    .Select(x => new DesignToolItemPickerItem { Id = x.Id, Name = x.Name, IType = x.IType })
                    .ToList(),
                allItemTypes,
                ITEM_TYPES,
                currentType,
                currentItemId,
                position,
                pickedId =>
                {
                    tempAreaRewardItemId[dataId] = pickedId;
                    Repaint();
                });
        }

        /// <summary>
        /// 解析Item奖励
        /// </summary>
        private ItemReward? ParseItemReward(string itemJson)
        {
            if (string.IsNullOrEmpty(itemJson)) return null;
            
            try
            {
                // 格式: [{"Id":83,"Num":1}]
                itemJson = itemJson.Trim();
                if (!itemJson.StartsWith("[") || !itemJson.EndsWith("]"))
                    return null;
                
                itemJson = itemJson.Substring(1, itemJson.Length - 2); // 去掉[]
                
                // 简单解析
                var idMatch = System.Text.RegularExpressions.Regex.Match(itemJson, @"""Id"":(\d+)");
                var numMatch = System.Text.RegularExpressions.Regex.Match(itemJson, @"""Num"":(\d+)");
                
                if (idMatch.Success && numMatch.Success)
                {
                    return new ItemReward
                    {
                        Id = int.Parse(idMatch.Groups[1].Value),
                        Num = int.Parse(numMatch.Groups[1].Value)
                    };
                }
            }
            catch { }
            
            return null;
        }

        /// <summary>
        /// 解析区域奖励
        /// </summary>
        private List<ItemReward> ParseAreaReward(string areaRewardJson)
        {
            var result = new List<ItemReward>();
            
            if (string.IsNullOrEmpty(areaRewardJson)) return result;
            
            try
            {
                // 格式: [{"Id":100001,"Num":25}] 或 [{"Id":100001,"Num":50},{"Id":100021,"Num":1}]
                var matches = System.Text.RegularExpressions.Regex.Matches(areaRewardJson, @"\{""Id"":(\d+),""Num"":(\d+)\}");
                
                foreach (System.Text.RegularExpressions.Match match in matches)
                {
                    result.Add(new ItemReward
                    {
                        Id = int.Parse(match.Groups[1].Value),
                        Num = int.Parse(match.Groups[2].Value)
                    });
                }
            }
            catch { }
            
            return result;
        }

        /// <summary>
        /// 获取Item的类型
        /// </summary>
        private int GetItemType(int itemId)
        {
            if (itemDict.TryGetValue(itemId, out var item))
            {
                return item.IType;
            }
            return -1;
        }

        /// <summary>
        /// 更新Item奖励
        /// </summary>
        private void UpdateItemReward(IndoorProgressData data, int itemId, int num)
        {
            // Item格式: [{"Id":83,"Num":1}]
            data.Item = $"[{{\"Id\":{itemId},\"Num\":{num}}}]";
            
            // Emit格式: 83
            data.Emit = itemId.ToString();
            
            // Reward格式: 83=1
            data.Reward = $"{itemId}={num}";
        }

        /// <summary>
        /// 更新区域奖励
        /// </summary>
        private void UpdateAreaReward(IndoorProgressData data, List<ItemReward> areaRewards)
        {
            if (areaRewards.Count == 0)
            {
                data.AreaReward = "";
                data.BigReward = "";
                
                // 如果这是最后一个AreaReward位置，需要清空Lv=1的BigReward
                if (IsLastAreaRewardPosition(data.Scene, data.Lv))
                {
                    var lv1Data = allProgressDataList.FirstOrDefault(x => x.Scene == data.Scene && x.Lv == 1);
                    if (lv1Data != null)
                    {
                        lv1Data.BigReward = "";
                    }
                }
                return;
            }
            
            // AreaReward格式: [{"Id":100001,"Num":25}] 或 [{"Id":100001,"Num":50},{"Id":100021,"Num":1}]
            var areaRewardItems = areaRewards.Select(r => $"{{\"Id\":{r.Id},\"Num\":{r.Num}}}");
            data.AreaReward = $"[{string.Join(",", areaRewardItems)}]";
            
            // 当前行的BigReward清空（只有Lv=1才有BigReward）
            data.BigReward = "";
            
            // 如果这是最后一个AreaReward位置，更新Lv=1的BigReward
            if (IsLastAreaRewardPosition(data.Scene, data.Lv))
            {
                var lv1Data = allProgressDataList.FirstOrDefault(x => x.Scene == data.Scene && x.Lv == 1);
                if (lv1Data != null)
                {
                    // BigReward格式: Energy=25 或 Energy=50,PurplePig=1,101451=1
                    var bigRewardItems = new List<string>();
                    bool hasUnmappedItem = false;
                    
                    foreach (var reward in areaRewards)
                    {
                        if (MY_ITEM_DICT.TryGetValue(reward.Id, out string mappedName))
                        {
                            bigRewardItems.Add($"{mappedName}={reward.Num}");
                        }
                        else
                        {
                            bigRewardItems.Add($"{reward.Id}={reward.Num}");
                            hasUnmappedItem = true;
                        }
                    }
                    
                    lv1Data.BigReward = string.Join(",", bigRewardItems);
                    
                    // 如果有未映射的Item，显示警告
                    if (hasUnmappedItem)
                    {
                        Debug.LogWarning($"场景{data.Scene}的AreaReward包含未映射的ItemId，可能会出问题！");
                    }
                }
            }
        }
        
        /// <summary>
        /// 判断当前Lv是否为最后一个AreaReward位置
        /// </summary>
        private bool IsLastAreaRewardPosition(int scene, int lv)
        {
            if (scene == 1)
            {
                // 场景1的最后一个是44
                return lv == 44;
            }
            else if (scene >= 2 && scene <= 5)
            {
                // 场景2-5的最后一个是20
                return lv == 20;
            }
            else
            {
                // 其他场景的最后一个是25
                return lv == 25;
            }
        }

        /// <summary>
        /// 绘制Item预览
        /// </summary>
        private void DrawItemPreview(ItemData item)
        {
            if (string.IsNullOrEmpty(item.Res))
            {
                EditorGUILayout.LabelField("无图", GUILayout.Width(50));
                return;
            }
            
            // 解析Res格式: "TableName,ItemName"
            var parts = item.Res.Split(',');
            if (parts.Length != 2)
            {
                EditorGUILayout.LabelField("无图", GUILayout.Width(50));
                return;
            }
            
            string tableName = parts[0];
            string artItemName = parts[1];
            
            if (string.IsNullOrEmpty(tableName) || string.IsNullOrEmpty(artItemName))
            {
                EditorGUILayout.LabelField("无图", GUILayout.Width(50));
                return;
            }
            
            // 查找对应的ArtTableSO
            var artTable = allArtTables.FirstOrDefault(x => x.TableName == tableName);
            if (artTable == null)
            {
                EditorGUILayout.LabelField("无图", GUILayout.Width(50));
                return;
            }
            
            var artItem = artTable.Items.FirstOrDefault(x => x.Name == artItemName);
            if (artItem == null || artItem.Sprite == null)
            {
                EditorGUILayout.LabelField("无图", GUILayout.Width(50));
                return;
            }
            
            // 显示预览图
            Rect rect = GUILayoutUtility.GetRect(50, 50, GUILayout.Width(50), GUILayout.Height(50));
            GUI.DrawTexture(rect, artItem.Sprite.texture, ScaleMode.ScaleToFit);
        }

        /// <summary>
        /// 新增场景
        /// </summary>
        private void AddNewScene()
        {
            // 找到最大的Scene ID
            int maxScene = allProgressDataList.Count > 0 ? allProgressDataList.Max(x => x.Scene) : 0;
            int newScene = maxScene + 1;
            
            // 找到最大的ID
            int maxId = allProgressDataList.Count > 0 ? allProgressDataList.Max(x => x.Id) : 0;
            
            // 创建25个新记录
            for (int lv = 1; lv <= 25; lv++)
            {
                maxId++;
                
                var newData = new IndoorProgressData
                {
                    Id = maxId,
                    Scene = newScene,
                    Lv = lv,
                    Item = "",
                    Emit = "",
                    Reward = "",
                    BigReward = "",
                    AreaReward = "",
                    Part = 0
                };
                
                // 如果是Lv25，添加默认的AreaReward
                if (lv == 25)
                {
                    // 默认给25能量
                    newData.AreaReward = "[{\"Id\":100001,\"Num\":25}]";
                    newData.BigReward = "Energy=25";
                }
                
                allProgressDataList.Add(newData);
            }
            
            // 切换到新场景
            selectedScene = newScene;
            sceneInputText = newScene.ToString();
            FilterProgressByScene();
            
            EditorUtility.DisplayDialog("成功", $"已创建场景 {newScene}，包含25个步骤（Lv 1-25）", "确定");
        }

        /// <summary>
        /// 保存数据
        /// </summary>
        private void SaveData()
        {
            try
            {
                string progressExcelPath = Path.Combine(docsRootPath, "config", INDOOR_PROGRESS_EXCEL_NAME);
                if (!File.Exists(progressExcelPath))
                {
                    EditorUtility.DisplayDialog("错误", $"未找到IndoorProgress配置文件: {progressExcelPath}", "确定");
                    return;
                }

                using (var package = new ExcelPackage(new FileInfo(progressExcelPath)))
                {
                    var worksheet = package.Workbook.Worksheets[INDOOR_PROGRESS_SHEET_NAME];
                    if (worksheet == null)
                    {
                        EditorUtility.DisplayDialog("错误", $"IndoorProgress.xlsx中未找到Sheet: {INDOOR_PROGRESS_SHEET_NAME}", "确定");
                        return;
                    }

                    // 查找列索引
                    int idCol = -1, sceneCol = -1, lvCol = -1, itemCol = -1, emitCol = -1, 
                        rewardCol = -1, bigRewardCol = -1, areaRewardCol = -1, partCol = -1;
                    int columnCount = worksheet.Dimension.Columns;

                    for (int col = 1; col <= columnCount; col++)
                    {
                        string header = worksheet.Cells[1, col].Text;
                        if (header == "Id") idCol = col;
                        else if (header == "Scene") sceneCol = col;
                        else if (header == "Lv") lvCol = col;
                        else if (header == "Item") itemCol = col;
                        else if (header == "Emit") emitCol = col;
                        else if (header == "Reward") rewardCol = col;
                        else if (header == "BigReward") bigRewardCol = col;
                        else if (header == "AreaReward") areaRewardCol = col;
                        else if (header == "Part") partCol = col;
                    }

                    // 更新和删除数据（从第3行开始）
                    int rowCount = worksheet.Dimension.Rows;
                    var processedIds = new HashSet<int>();
                    
                    // 第一遍：更新现有行或标记删除
                    for (int row = rowCount; row >= 3; row--)
                    {
                        string idText = worksheet.Cells[row, idCol].Text;
                        if (string.IsNullOrEmpty(idText)) continue;

                        if (!int.TryParse(idText, out int id)) continue;

                        // 查找对应的数据
                        var progressData = allProgressDataList.Find(x => x.Id == id);
                        if (progressData != null)
                        {
                            // 更新数据
                            worksheet.Cells[row, sceneCol].Value = progressData.Scene;
                            worksheet.Cells[row, lvCol].Value = progressData.Lv;
                            worksheet.Cells[row, itemCol].Value = progressData.Item;
                            worksheet.Cells[row, emitCol].Value = progressData.Emit;
                            worksheet.Cells[row, rewardCol].Value = progressData.Reward;
                            worksheet.Cells[row, bigRewardCol].Value = progressData.BigReward;
                            worksheet.Cells[row, areaRewardCol].Value = progressData.AreaReward;
                            worksheet.Cells[row, partCol].Value = progressData.Part > 0 ? progressData.Part.ToString() : "";
                            
                            processedIds.Add(id);
                        }
                        else
                        {
                            // 删除行
                            worksheet.DeleteRow(row);
                        }
                    }
                    
                    // 第二遍：添加新行
                    int currentRow = worksheet.Dimension?.Rows ?? 2;
                    foreach (var progressData in allProgressDataList.OrderBy(x => x.Id))
                    {
                        if (!processedIds.Contains(progressData.Id))
                        {
                            // 这是新增的数据
                            currentRow++;
                            worksheet.Cells[currentRow, idCol].Value = progressData.Id;
                            worksheet.Cells[currentRow, sceneCol].Value = progressData.Scene;
                            worksheet.Cells[currentRow, lvCol].Value = progressData.Lv;
                            worksheet.Cells[currentRow, itemCol].Value = progressData.Item;
                            worksheet.Cells[currentRow, emitCol].Value = progressData.Emit;
                            worksheet.Cells[currentRow, rewardCol].Value = progressData.Reward;
                            worksheet.Cells[currentRow, bigRewardCol].Value = progressData.BigReward;
                            worksheet.Cells[currentRow, areaRewardCol].Value = progressData.AreaReward;
                            worksheet.Cells[currentRow, partCol].Value = progressData.Part > 0 ? progressData.Part.ToString() : "";
                        }
                    }

                    // 保存文件
                    package.Save();
                }

                // 提示成功并提醒推送
                EditorUtility.DisplayDialog("保存成功", 
                    "配置已保存到Excel文件！\n\n" +
                    "⚠️ 重要提醒：\n" +
                    "请及时在SourceTree或GitHubDesktop中：\n" +
                    "1. 提交(Commit)本次修改\n" +
                    "2. 推送(Push)到远程仓库\n\n" +
                    "避免与其他策划产生冲突！", 
                    "我知道了");
            }
            catch (Exception e)
            {
                EditorUtility.DisplayDialog("错误", $"保存数据失败: {e.Message}\n{e.StackTrace}", "确定");
            }
        }

        /// <summary>
        /// 场景进度数据类
        /// </summary>
        private class IndoorProgressData
        {
            public int Id;
            public int Scene;
            public int Lv;
            public string Item;
            public string Emit;
            public string Reward;
            public string BigReward;
            public string AreaReward;
            public int Part;
        }

        /// <summary>
        /// Item数据类
        /// </summary>
        private class ItemData
        {
            public int Id;
            public string Name;
            public int IType;
            public string Res;
        }

        /// <summary>
        /// Item奖励结构
        /// </summary>
        private struct ItemReward
        {
            public int Id;
            public int Num;
        }
    }
}
