using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using OfficeOpenXml;
using UnityEditor;
using UnityEngine;
using Debug = UnityEngine.Debug;

namespace DesignTools.LimitedTimeEvent
{
    /// <summary>
    /// 小猫戏法限时事件常量配置工具
    /// 读取 Docs/config/LimitedTimeEvent.xlsx 的 Const Sheet，仅编辑指定 Key 的 Value。
    /// </summary>
    public class CatTrickConstEditor : BaseDesignToolEditor
    {
        private const string LIMITED_TIME_EVENT_EXCEL_NAME = "LimitedTimeEvent.xlsx";
        private const string CONST_SHEET_NAME = "Const";
        private const int HEADER_ROW = 1;
        private const int DATA_START_ROW = 3;

        private const string KEY_CONSUME_ENERGY = "CatTrick_ConsumeEnergy";
        private const string KEY_REWARD_DIAMOND = "CatTrick_RewardDiamond";
        private const string LABEL_CONSUME_ENERGY = "小猫戏法每次获得钻石需要消耗的体力";
        private const string LABEL_REWARD_DIAMOND = "每次领取的钻石数量";

        private readonly List<CatTrickConstItem> constItems = new List<CatTrickConstItem>();
        private int keyColumnIndex = -1;
        private int valueColumnIndex = -1;

        [MenuItem("策划工具/限时事件/小猫戏法")]
        public static void ShowWindow()
        {
            CatTrickConstEditor window = GetWindow<CatTrickConstEditor>("小猫戏法");
            window.minSize = window.GetMinWindowSize();
            window.Show();
        }

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

        protected override string GetWindowTitle()
        {
            return "小猫戏法配置工具";
        }

        protected override Vector2 GetMinWindowSize()
        {
            return new Vector2(760, 420);
        }

        protected override void LoadConfigData()
        {
            LoadConstSheet();
        }

        protected override void DrawDataEditor()
        {
            EditorGUILayout.BeginVertical("box");
            EditorGUILayout.HelpBox("仅会写回 LimitedTimeEvent.xlsx 的 Const Sheet，并且只修改 CatTrick_ConsumeEnergy 与 CatTrick_RewardDiamond 两个 Key 的 Value。", MessageType.Info);
            EditorGUILayout.EndVertical();

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

            foreach (CatTrickConstItem item in constItems)
            {
                DrawConstItem(item);
                EditorGUILayout.Space(4);
            }

            EditorGUILayout.EndScrollView();
        }

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

        private void LoadConstSheet()
        {
            constItems.Clear();
            keyColumnIndex = -1;
            valueColumnIndex = -1;

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

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

                if (worksheet.Dimension == null)
                {
                    throw new Exception($"{LIMITED_TIME_EVENT_EXCEL_NAME}/{CONST_SHEET_NAME} 没有可读取的数据");
                }

                keyColumnIndex = FindColumnIndex(worksheet, "Key");
                valueColumnIndex = FindColumnIndex(worksheet, "Value");

                if (keyColumnIndex < 0 || valueColumnIndex < 0)
                {
                    throw new Exception($"{LIMITED_TIME_EVENT_EXCEL_NAME}/{CONST_SHEET_NAME} 表结构不正确，缺少 Key 或 Value 列");
                }

                int rowCount = worksheet.Dimension.End.Row;
                for (int row = DATA_START_ROW; row <= rowCount; row++)
                {
                    string key = worksheet.Cells[row, keyColumnIndex].Text.Trim();
                    if (string.IsNullOrEmpty(key))
                    {
                        continue;
                    }

                    if (key != KEY_CONSUME_ENERGY && key != KEY_REWARD_DIAMOND)
                    {
                        continue;
                    }

                    string valueText = worksheet.Cells[row, valueColumnIndex].Text.Trim();
                    if (!int.TryParse(valueText, out int value))
                    {
                        throw new Exception($"{CONST_SHEET_NAME} Sheet 第 {row} 行 Key={key} 的 Value 不是有效整数：{valueText}");
                    }

                    constItems.Add(new CatTrickConstItem
                    {
                        Key = key,
                        Value = value,
                        RowIndex = row
                    });
                }
            }

            string[] missingKeys = new[] { KEY_CONSUME_ENERGY, KEY_REWARD_DIAMOND }
                .Where(targetKey => constItems.All(item => item.Key != targetKey))
                .ToArray();

            if (missingKeys.Length > 0)
            {
                throw new Exception($"{CONST_SHEET_NAME} Sheet 缺少以下 Key：{string.Join("、", missingKeys)}");
            }

            constItems.Sort((left, right) => string.CompareOrdinal(left.Key, right.Key));
            Debug.Log($"小猫戏法配置读取完成，共加载 {constItems.Count} 条数据");
        }

        private void DrawConstItem(CatTrickConstItem item)
        {
            EditorGUILayout.BeginVertical("box");

            EditorGUILayout.LabelField(GetDisplayName(item.Key), EditorStyles.boldLabel);
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Value", GUILayout.Width(60));
            item.Value = EditorGUILayout.IntField(item.Value, GUILayout.Width(180));
            GUILayout.FlexibleSpace();
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            GUILayout.Space(4);
            EditorGUILayout.LabelField($"Excel 行号：{item.RowIndex}", EditorStyles.miniLabel);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.EndVertical();
        }

        private void SaveConstSheet()
        {
            if (constItems.Count == 0)
            {
                EditorUtility.DisplayDialog("提示", "当前没有可保存的数据，请先加载配置。", "确定");
                return;
            }

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

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

                    foreach (CatTrickConstItem item in constItems)
                    {
                        worksheet.Cells[item.RowIndex, valueColumnIndex].Value = item.Value;
                    }

                    package.Save();
                }

                EditorUtility.DisplayDialog("成功", "小猫戏法配置已保存到 Excel！", "确定");
                Debug.Log("小猫戏法配置保存成功");
            }
            catch (Exception e)
            {
                EditorUtility.DisplayDialog("错误", $"保存失败: {e.Message}", "确定");
                Debug.LogError($"保存小猫戏法配置失败: {e}");
            }
        }

        private int FindColumnIndex(ExcelWorksheet worksheet, string columnName)
        {
            int columnCount = worksheet.Dimension?.End.Column ?? 0;
            for (int col = 1; col <= columnCount; col++)
            {
                if (string.Equals(worksheet.Cells[HEADER_ROW, col].Text.Trim(), columnName, StringComparison.OrdinalIgnoreCase))
                {
                    return col;
                }
            }

            return -1;
        }

        private string GetDisplayName(string key)
        {
            switch (key)
            {
                case KEY_CONSUME_ENERGY:
                    return LABEL_CONSUME_ENERGY;
                case KEY_REWARD_DIAMOND:
                    return LABEL_REWARD_DIAMOND;
                default:
                    return key;
            }
        }

        [Serializable]
        private class CatTrickConstItem
        {
            public string Key;
            public int Value;
            public int RowIndex;
        }
    }
}
