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

namespace DesignTools.Friends
{
    /// <summary>
    /// 好友邀请奖励配置工具
    /// 读取 Docs/config/Invite.xlsx 的 Reward Sheet，仅支持编辑固定 4 档邀请奖励
    /// </summary>
    public class InviteRewardEditor : BaseDesignToolEditor
    {
        private const string INVITE_EXCEL_NAME = "Invite.xlsx";
        private const string REWARD_SHEET_NAME = "Reward";

        private const int COL_ID = 1;
        private const int COL_NEED = 2;
        private const int COL_ITEMS = 3;
        private const int FIXED_STAGE_COUNT = 4;

        private readonly List<InviteRewardData> rewardDataList = new List<InviteRewardData>();

        [MenuItem("策划工具/好友/邀请奖励")]
        public static void ShowWindow()
        {
            var window = GetWindow<InviteRewardEditor>("邀请奖励配置");
            window.minSize = window.GetMinWindowSize();
            window.Show();
        }

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

        protected override string GetWindowTitle()
        {
            return "邀请奖励配置工具";
        }

        protected override Vector2 GetMinWindowSize()
        {
            return new Vector2(820, 520);
        }

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

        protected override void DrawDataEditor()
        {
            DrawTips();
            EditorGUILayout.Space(6);
            DrawRewardTable();
        }

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

        private void DrawTips()
        {
            EditorGUILayout.BeginVertical("box");
            EditorGUILayout.HelpBox("如果要添加阶段数量请联系开发组", MessageType.Warning);

            if (rewardDataList.Count != FIXED_STAGE_COUNT)
            {
                EditorGUILayout.HelpBox(
                    $"当前 Reward Sheet 读取到 {rewardDataList.Count} 行有效数据，工具仅支持固定 {FIXED_STAGE_COUNT} 行配置。",
                    MessageType.Error);
            }

            bool hasParseError = false;
            for (int i = 0; i < rewardDataList.Count; i++)
            {
                if (!rewardDataList[i].IsItemsValid)
                {
                    hasParseError = true;
                    break;
                }
            }

            if (hasParseError)
            {
                EditorGUILayout.HelpBox("存在无法解析的奖励数据，请先检查 Excel 中 Items 列格式，必须为 [{\"Id\":100001,\"Num\":50}] 这种结构。", MessageType.Error);
            }

            EditorGUILayout.EndVertical();
        }

        private void DrawRewardTable()
        {
            EditorGUILayout.BeginVertical("box");

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("阶段", EditorStyles.boldLabel, GUILayout.Width(80));
            EditorGUILayout.LabelField("需要邀请人数", EditorStyles.boldLabel, GUILayout.Width(180));
            EditorGUILayout.LabelField("奖励数量", EditorStyles.boldLabel, GUILayout.Width(180));
            GUILayout.FlexibleSpace();
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space(4);

            scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);

            for (int i = 0; i < rewardDataList.Count; i++)
            {
                InviteRewardData data = rewardDataList[i];

                EditorGUILayout.BeginVertical("box");
                EditorGUILayout.BeginHorizontal();

                EditorGUILayout.LabelField($"第 {i + 1} 档", GUILayout.Width(80));
                data.Need = EditorGUILayout.IntField(data.Need, GUILayout.Width(180));
                data.RewardNum = EditorGUILayout.IntField(data.RewardNum, GUILayout.Width(180));
                GUILayout.FlexibleSpace();

                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                GUILayout.Space(84);
                EditorGUILayout.LabelField($"配置Id: {data.Id}", EditorStyles.miniLabel, GUILayout.Width(120));
                EditorGUILayout.LabelField($"奖励ItemId: {data.RewardItemId}", EditorStyles.miniLabel, GUILayout.Width(160));
                if (!data.IsItemsValid)
                {
                    EditorGUILayout.LabelField("Items 格式异常", EditorStyles.miniBoldLabel, GUILayout.Width(100));
                }
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.EndVertical();
            }

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

        private void LoadInviteRewardExcel()
        {
            rewardDataList.Clear();

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

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

                int rowCount = worksheet.Dimension?.Rows ?? 0;
                for (int row = 3; row <= rowCount; row++)
                {
                    string idText = worksheet.Cells[row, COL_ID].Text.Trim();
                    if (string.IsNullOrEmpty(idText))
                    {
                        continue;
                    }

                    if (!int.TryParse(idText, out int id))
                    {
                        Debug.LogWarning($"Invite.xlsx/{REWARD_SHEET_NAME} 第 {row} 行 Id 不是有效整数，已跳过");
                        continue;
                    }

                    InviteRewardData data = new InviteRewardData
                    {
                        Id = id,
                        Need = ParseInt(worksheet.Cells[row, COL_NEED].Text.Trim()),
                        ItemsRawText = worksheet.Cells[row, COL_ITEMS].Text.Trim(),
                        RowIndex = row
                    };

                    data.IsItemsValid = TryParseItems(data.ItemsRawText, out int rewardItemId, out int rewardNum);
                    data.RewardItemId = rewardItemId;
                    data.RewardNum = rewardNum;

                    rewardDataList.Add(data);
                }
            }

            if (rewardDataList.Count == 0)
            {
                throw new Exception("未读取到任何邀请奖励数据");
            }
        }

        private void SaveToExcel()
        {
            if (!ValidateRewardData(out string errorMessage))
            {
                EditorUtility.DisplayDialog("校验失败", errorMessage, "确定");
                return;
            }

            try
            {
                string excelPath = GetDocsConfigFilePath(INVITE_EXCEL_NAME);

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

                    foreach (InviteRewardData data in rewardDataList)
                    {
                        int row = data.RowIndex;
                        worksheet.Cells[row, COL_ID].Value = data.Id;
                        worksheet.Cells[row, COL_NEED].Value = data.Need;
                        worksheet.Cells[row, COL_ITEMS].Value = BuildItemsJson(data.RewardItemId, data.RewardNum);
                    }

                    package.Save();
                }

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

        private bool ValidateRewardData(out string errorMessage)
        {
            if (rewardDataList.Count != FIXED_STAGE_COUNT)
            {
                errorMessage = $"当前 Reward Sheet 不是固定的 {FIXED_STAGE_COUNT} 行配置，不能通过该工具保存。\n\n如果要添加阶段数量请联系开发组";
                return false;
            }

            int previousNeed = int.MinValue;
            for (int i = 0; i < rewardDataList.Count; i++)
            {
                InviteRewardData data = rewardDataList[i];

                if (!data.IsItemsValid || data.RewardItemId <= 0)
                {
                    errorMessage = $"第 {i + 1} 档奖励数据格式异常，无法保存。";
                    return false;
                }

                if (data.Need < 0)
                {
                    errorMessage = $"第 {i + 1} 档的需要邀请人数不能小于 0。";
                    return false;
                }

                if (data.RewardNum < 0)
                {
                    errorMessage = $"第 {i + 1} 档的奖励数量必须是整数，且不能小于 0。";
                    return false;
                }

                if (data.Need <= previousNeed)
                {
                    errorMessage = "需要邀请人数必须按从小到大的顺序填写。";
                    return false;
                }

                previousNeed = data.Need;
            }

            errorMessage = string.Empty;
            return true;
        }

        private bool TryParseItems(string itemsText, out int itemId, out int rewardNum)
        {
            itemId = 0;
            rewardNum = 0;

            if (string.IsNullOrWhiteSpace(itemsText))
            {
                return false;
            }

            Match idMatch = Regex.Match(itemsText, @"""Id""\s*:\s*(\d+)");
            Match numMatch = Regex.Match(itemsText, @"""Num""\s*:\s*(-?\d+)");

            if (!idMatch.Success || !numMatch.Success)
            {
                return false;
            }

            return int.TryParse(idMatch.Groups[1].Value, out itemId) &&
                   int.TryParse(numMatch.Groups[1].Value, out rewardNum);
        }

        private string BuildItemsJson(int itemId, int rewardNum)
        {
            return $"[{{\"Id\":{itemId},\"Num\":{rewardNum}}}]";
        }

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

    [Serializable]
    public class InviteRewardData
    {
        public int Id;
        public int Need;
        public int RewardItemId;
        public int RewardNum;
        public bool IsItemsValid;
        public int RowIndex;
        public string ItemsRawText;
    }
}
