using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using OfficeOpenXml;
using ArtResource;

namespace DesignTools.Scene
{
    /// <summary>
    /// 场景标题和预览图配置工具
    /// 读取 Docs/config/SceneData.xlsx 的 SceneData Sheet
    /// 关联 ArtTableSO "SceneDataPic" 提供预览图选择
    /// </summary>
    public class SceneDataEditor : BaseDesignToolEditor
    {
        #region 常量

        private const string SCENE_EXCEL_NAME = "SceneData.xlsx";
        private const string SCENE_SHEET_NAME = "SceneData";
        private const string RESOURCES_PATH_PREFIX = "Assets/Art_SubModule/GameMain/UI/UISprites/Area/";
        private const string SCENE_DATA_PIC_TABLE_NAME = "SceneDataPic";

        #endregion

        #region 数据

        private List<SceneRowData> sceneDataList = new List<SceneRowData>();
        private ArtTableSO sceneDataPicSO;
        private Dictionary<string, Sprite> spriteCache = new Dictionary<string, Sprite>();
        private Dictionary<string, Texture2D> textureCache = new Dictionary<string, Texture2D>();

        #endregion

        #region 打开窗口

        [MenuItem("策划工具/场景/场景标题和预览图配置")]
        public static void ShowWindow()
        {
            var window = GetWindow<SceneDataEditor>("场景标题和预览图配置");
            window.minSize = window.GetMinWindowSize();
            window.Show();
        }

        #endregion

        #region BaseDesignToolEditor 实现

        protected override string GetDocsPathPrefKey() => "SceneDataEditor_DocsPath";
        protected override string GetWindowTitle() => "场景标题和预览图配置";
        protected override Vector2 GetMinWindowSize() => new Vector2(1300, 600);

        protected override void LoadConfigData()
        {
            spriteCache.Clear();
            textureCache.Clear();
            LoadSceneDataPicSO();
            LoadSceneDataExcel();
        }

        protected override void DrawDataEditor()
        {
            if (sceneDataPicSO == null)
            {
                EditorGUILayout.HelpBox(
                    $"未找到 ArtTableSO \"{SCENE_DATA_PIC_TABLE_NAME}\"，预览图选择功能不可用。\n请先在美术资源工具中创建名为 \"{SCENE_DATA_PIC_TABLE_NAME}\" 的资源表。",
                    MessageType.Warning);
            }

            EditorGUILayout.BeginVertical("box");

            // 标题 + 新增按钮
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField($"场景数据列表（共 {sceneDataList.Count} 条）", EditorStyles.boldLabel);
            GUILayout.FlexibleSpace();
            GUI.backgroundColor = Color.cyan;
            if (GUILayout.Button("+ 新增行", GUILayout.Height(25), GUILayout.Width(100)))
            {
                AddNewRow();
            }
            GUI.backgroundColor = Color.white;
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space(5);

            // 表头
            DrawTableHeader();

            // 数据行
            scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);

            SceneRowData toDelete = null;
            foreach (var data in sceneDataList)
            {
                DrawDataRow(data, ref toDelete);
            }

            if (toDelete != null)
            {
                sceneDataList.Remove(toDelete);
            }

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

        protected override void SaveDataToExcel()
        {
            try
            {
                string excelPath = GetDocsConfigFilePath(SCENE_EXCEL_NAME);
                if (!File.Exists(excelPath))
                {
                    EditorUtility.DisplayDialog("错误", $"文件不存在: {excelPath}", "确定");
                    return;
                }

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

                    // 查找列索引
                    int idCol = -1, sceneIdCol = -1, areaIdCol = -1, titleCol = -1;
                    int iconCol = -1, iconGrayCol = -1, resPathCol = -1;
                    int colCount = ws.Dimension?.Columns ?? 0;

                    for (int c = 1; c <= colCount; c++)
                    {
                        string h = ws.Cells[1, c].Text;
                        switch (h)
                        {
                            case "Id": idCol = c; break;
                            case "SceneId": sceneIdCol = c; break;
                            case "AreaId": areaIdCol = c; break;
                            case "Title": titleCol = c; break;
                            case "Icon": iconCol = c; break;
                            case "IconGray": iconGrayCol = c; break;
                            case "ResourcesPath": resPathCol = c; break;
                        }
                    }

                    if (idCol < 0)
                    {
                        EditorUtility.DisplayDialog("错误", "表结构不正确，缺少 Id 列", "确定");
                        return;
                    }

                    // 清除现有数据行（从底部向上删除，保留前两行表头）
                    int existingRows = ws.Dimension?.Rows ?? 2;
                    for (int row = existingRows; row >= 3; row--)
                    {
                        ws.DeleteRow(row);
                    }

                    // 写入所有数据
                    for (int i = 0; i < sceneDataList.Count; i++)
                    {
                        int row = i + 3;
                        var data = sceneDataList[i];

                        ws.Cells[row, idCol].Value = data.Id;
                        if (sceneIdCol > 0) ws.Cells[row, sceneIdCol].Value = GetSceneId(data.Id);
                        if (areaIdCol > 0) ws.Cells[row, areaIdCol].Value = GetAreaId(data.Id);
                        if (titleCol > 0) ws.Cells[row, titleCol].Value = GetTitle(data.Id);
                        if (iconCol > 0) ws.Cells[row, iconCol].Value = data.Icon ?? "";
                        if (iconGrayCol > 0) ws.Cells[row, iconGrayCol].Value = data.IconGray ?? "";
                        if (resPathCol > 0) ws.Cells[row, resPathCol].Value = GetResourcesPath(data.Icon);
                    }

                    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}", "确定");
            }
        }

        #endregion

        #region 数据加载

        private void LoadSceneDataPicSO()
        {
            sceneDataPicSO = null;

            string[] guids = AssetDatabase.FindAssets("t:ArtTableSO");
            foreach (var guid in guids)
            {
                string path = AssetDatabase.GUIDToAssetPath(guid);
                var so = AssetDatabase.LoadAssetAtPath<ArtTableSO>(path);
                if (so != null && so.TableName == SCENE_DATA_PIC_TABLE_NAME)
                {
                    sceneDataPicSO = so;
                    break;
                }
            }

            if (sceneDataPicSO == null)
            {
                Debug.LogWarning($"未找到 ArtTableSO: {SCENE_DATA_PIC_TABLE_NAME}，预览图选择功能将不可用");
            }
        }

        private void LoadSceneDataExcel()
        {
            sceneDataList.Clear();

            string excelPath = GetDocsConfigFilePath(SCENE_EXCEL_NAME);
            if (!File.Exists(excelPath))
            {
                throw new Exception($"未找到文件: {excelPath}");
            }

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

                // 查找列
                int idCol = -1, iconCol = -1, iconGrayCol = -1;
                int colCount = ws.Dimension?.Columns ?? 0;

                for (int c = 1; c <= colCount; c++)
                {
                    string h = ws.Cells[1, c].Text;
                    if (h == "Id") idCol = c;
                    else if (h == "Icon") iconCol = c;
                    else if (h == "IconGray") iconGrayCol = c;
                }

                if (idCol < 0)
                {
                    throw new Exception("表结构不正确，缺少 Id 列");
                }

                int rowCount = ws.Dimension?.Rows ?? 0;
                for (int row = 3; row <= rowCount; row++)
                {
                    string idText = ws.Cells[row, idCol].Text;
                    if (string.IsNullOrEmpty(idText)) continue;
                    if (!int.TryParse(idText, out int id)) continue;

                    sceneDataList.Add(new SceneRowData
                    {
                        Id = id,
                        Icon = iconCol > 0 ? (ws.Cells[row, iconCol].Text ?? "") : "",
                        IconGray = iconGrayCol > 0 ? (ws.Cells[row, iconGrayCol].Text ?? "") : "",
                    });
                }
            }
        }

        #endregion

        #region UI 绘制

        private void DrawTableHeader()
        {
            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
            EditorGUILayout.LabelField("Id", EditorStyles.miniLabel, GUILayout.Width(35));
            EditorGUILayout.LabelField("SceneId", EditorStyles.miniLabel, GUILayout.Width(55));
            EditorGUILayout.LabelField("AreaId", EditorStyles.miniLabel, GUILayout.Width(45));
            EditorGUILayout.LabelField("Title", EditorStyles.miniLabel, GUILayout.Width(170));
            EditorGUILayout.LabelField("Icon", EditorStyles.miniLabel, GUILayout.Width(168));
            EditorGUILayout.LabelField("预览", EditorStyles.miniLabel, GUILayout.Width(55));
            EditorGUILayout.LabelField("IconGray", EditorStyles.miniLabel, GUILayout.Width(168));
            EditorGUILayout.LabelField("预览", EditorStyles.miniLabel, GUILayout.Width(55));
            EditorGUILayout.LabelField("ResourcesPath", EditorStyles.miniLabel);
            EditorGUILayout.LabelField("", GUILayout.Width(60));
            EditorGUILayout.EndHorizontal();
        }

        private void DrawDataRow(SceneRowData data, ref SceneRowData toDelete)
        {
            EditorGUILayout.BeginHorizontal();

            // Id（只读）
            EditorGUILayout.LabelField(data.Id.ToString(), GUILayout.Width(35));

            // SceneId（自动）
            EditorGUILayout.LabelField(GetSceneId(data.Id).ToString(), GUILayout.Width(55));

            // AreaId（自动）
            EditorGUILayout.LabelField(GetAreaId(data.Id).ToString(), GUILayout.Width(45));

            // Title（自动）
            EditorGUILayout.LabelField(GetTitle(data.Id), GUILayout.Width(170));

            // Icon + 选择按钮
            EditorGUILayout.BeginHorizontal(GUILayout.Width(168));
            data.Icon = EditorGUILayout.TextField(data.Icon, GUILayout.Width(120));
            GUI.enabled = sceneDataPicSO != null;
            if (GUILayout.Button("设置预览图", EditorStyles.miniButton, GUILayout.Width(60)))
            {
                var capturedData = data;
                SceneDataPicPickerWindow.Show(sceneDataPicSO, "选择 Icon 预览图", name =>
                {
                    capturedData.Icon = name;
                    // 清除缓存以便刷新
                    spriteCache.Remove(name);
                    textureCache.Remove(name);
                    Repaint();
                });
            }
            GUI.enabled = true;
            EditorGUILayout.EndHorizontal();

            // Icon 预览
            DrawSpritePreview(data.Icon, 50);

            // IconGray + 选择按钮
            EditorGUILayout.BeginHorizontal(GUILayout.Width(168));
            data.IconGray = EditorGUILayout.TextField(data.IconGray, GUILayout.Width(120));
            GUI.enabled = sceneDataPicSO != null;
            if (GUILayout.Button("设置预览图", EditorStyles.miniButton, GUILayout.Width(60)))
            {
                var capturedData = data;
                SceneDataPicPickerWindow.Show(sceneDataPicSO, "选择 IconGray 预览图", name =>
                {
                    capturedData.IconGray = name;
                    spriteCache.Remove(name);
                    textureCache.Remove(name);
                    Repaint();
                });
            }
            GUI.enabled = true;
            EditorGUILayout.EndHorizontal();

            // IconGray 预览
            DrawSpritePreview(data.IconGray, 50);

            // ResourcesPath（自动，只读）
            EditorGUILayout.LabelField(GetResourcesPath(data.Icon), EditorStyles.miniLabel);

            // 删除按钮
            GUI.backgroundColor = Color.red;
            if (GUILayout.Button("删除", GUILayout.Width(60)))
            {
                if (EditorUtility.DisplayDialog("确认删除",
                    $"确定要删除 Id={data.Id} 的行吗？", "删除", "取消"))
                {
                    toDelete = data;
                }
            }
            GUI.backgroundColor = Color.white;

            EditorGUILayout.EndHorizontal();
        }

        private void DrawSpritePreview(string spriteName, float size)
        {
            Rect previewRect = GUILayoutUtility.GetRect(size, size, GUILayout.Width(size), GUILayout.Height(size));

            if (string.IsNullOrEmpty(spriteName))
            {
                EditorGUI.DrawRect(previewRect, new Color(0.3f, 0.3f, 0.3f, 1f));
                return;
            }

            // 优先从 ArtTableSO 获取 Sprite
            Sprite sprite = GetCachedSprite(spriteName);
            if (sprite != null && sprite.texture != null)
            {
                EditorGUI.DrawRect(previewRect, new Color(0.5f, 0.5f, 0.5f, 1f));

                Rect texCoords = sprite.textureRect;
                Texture2D tex = sprite.texture;
                Rect normalizedCoords = new Rect(
                    texCoords.x / tex.width,
                    texCoords.y / tex.height,
                    texCoords.width / tex.width,
                    texCoords.height / tex.height
                );

                float aspect = texCoords.width / texCoords.height;
                Rect drawRect = previewRect;
                if (aspect > 1)
                {
                    float newHeight = previewRect.height / aspect;
                    drawRect.y += (previewRect.height - newHeight) * 0.5f;
                    drawRect.height = newHeight;
                }
                else
                {
                    float newWidth = previewRect.width * aspect;
                    drawRect.x += (previewRect.width - newWidth) * 0.5f;
                    drawRect.width = newWidth;
                }

                GUI.DrawTextureWithTexCoords(drawRect, tex, normalizedCoords);
                return;
            }

            // 回退：尝试直接从路径加载 Texture2D
            Texture2D fallbackTex = GetCachedTexture(spriteName);
            if (fallbackTex != null)
            {
                EditorGUI.DrawRect(previewRect, new Color(0.5f, 0.5f, 0.5f, 1f));
                GUI.DrawTexture(previewRect, fallbackTex, ScaleMode.ScaleToFit);
            }
            else
            {
                EditorGUI.DrawRect(previewRect, new Color(0.3f, 0.3f, 0.3f, 1f));
            }
        }

        #endregion

        #region 数据操作

        private void AddNewRow()
        {
            int newId = 1;
            if (sceneDataList.Count > 0)
            {
                newId = sceneDataList.Max(x => x.Id) + 1;
            }

            sceneDataList.Add(new SceneRowData
            {
                Id = newId,
                Icon = "",
                IconGray = "",
            });

            scrollPosition = new Vector2(0, float.MaxValue);
        }

        #endregion

        #region 自动计算

        private static int GetSceneId(int id) => ((id - 1) / 5) + 1;
        private static int GetAreaId(int id) => ((id - 1) % 5) + 1;
        private static string GetTitle(int id) => $"CS_ScenePanel_Scene{id}";

        private static string GetResourcesPath(string icon)
        {
            if (string.IsNullOrEmpty(icon)) return "";
            return $"{RESOURCES_PATH_PREFIX}{icon}.png";
        }

        #endregion

        #region Sprite 缓存

        private Sprite GetCachedSprite(string name)
        {
            if (string.IsNullOrEmpty(name)) return null;
            if (spriteCache.ContainsKey(name)) return spriteCache[name];

            Sprite result = null;
            if (sceneDataPicSO != null)
            {
                var item = sceneDataPicSO.Items.FirstOrDefault(x => x.Name == name);
                if (item != null) result = item.Sprite;
            }

            spriteCache[name] = result;
            return result;
        }

        private Texture2D GetCachedTexture(string name)
        {
            if (string.IsNullOrEmpty(name)) return null;
            if (textureCache.ContainsKey(name)) return textureCache[name];

            string path = GetResourcesPath(name);
            var tex = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
            textureCache[name] = tex;
            return tex;
        }

        #endregion

        #region 数据类

        private class SceneRowData
        {
            public int Id;
            public string Icon = "";
            public string IconGray = "";
        }

        #endregion
    }

    /// <summary>
    /// 场景预览图选择弹窗
    /// 展示 SceneDataPic ArtTableSO 中的所有图片，点击选择后回调
    /// </summary>
    public class SceneDataPicPickerWindow : EditorWindow
    {
        private ArtTableSO tableSO;
        private Action<string> onSelect;
        private string searchFilter = "";
        private Vector2 scrollPos;

        private const float CELL_WIDTH = 120;
        private const float CELL_HEIGHT = 130;
        private const float IMAGE_SIZE = 80;

        public static void Show(ArtTableSO tableSO, string title, Action<string> onSelect)
        {
            if (tableSO == null || tableSO.Items == null || tableSO.Items.Count == 0)
            {
                EditorUtility.DisplayDialog("错误", "SceneDataPic 资源表为空或不存在", "确定");
                return;
            }

            var window = CreateInstance<SceneDataPicPickerWindow>();
            window.titleContent = new GUIContent(title);
            window.tableSO = tableSO;
            window.onSelect = onSelect;
            window.minSize = new Vector2(650, 450);
            window.ShowUtility();
        }

        private void OnGUI()
        {
            if (tableSO == null)
            {
                EditorGUILayout.HelpBox("资源表未加载", MessageType.Error);
                return;
            }

            // 搜索栏
            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
            EditorGUILayout.LabelField("搜索:", GUILayout.Width(40));
            searchFilter = EditorGUILayout.TextField(searchFilter, EditorStyles.toolbarSearchField);
            if (GUILayout.Button("×", EditorStyles.miniButton, GUILayout.Width(20)))
            {
                searchFilter = "";
                GUI.FocusControl(null);
            }
            EditorGUILayout.EndHorizontal();

            // 过滤
            var items = tableSO.Items;
            if (!string.IsNullOrEmpty(searchFilter))
            {
                string filter = searchFilter.ToLower();
                items = items.Where(x => x.Name != null && x.Name.ToLower().Contains(filter)).ToList();
            }

            EditorGUILayout.LabelField($"共 {items.Count} 个资源（点击选择）", EditorStyles.miniLabel);

            // 网格展示
            scrollPos = EditorGUILayout.BeginScrollView(scrollPos);

            float windowWidth = position.width - 30;
            int columns = Mathf.Max(1, Mathf.FloorToInt(windowWidth / CELL_WIDTH));

            for (int i = 0; i < items.Count; i += columns)
            {
                EditorGUILayout.BeginHorizontal();
                for (int j = 0; j < columns && (i + j) < items.Count; j++)
                {
                    DrawItemCell(items[i + j]);
                }
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();
            }

            EditorGUILayout.EndScrollView();
        }

        private void DrawItemCell(ArtItemData item)
        {
            EditorGUILayout.BeginVertical("box", GUILayout.Width(CELL_WIDTH), GUILayout.Height(CELL_HEIGHT));

            // 图片预览
            Rect imageRect = GUILayoutUtility.GetRect(IMAGE_SIZE, IMAGE_SIZE,
                GUILayout.Width(IMAGE_SIZE), GUILayout.Height(IMAGE_SIZE));

            if (item.Sprite != null && item.Sprite.texture != null)
            {
                Sprite sprite = item.Sprite;
                Rect texCoords = sprite.textureRect;
                Texture2D tex = sprite.texture;
                Rect normalizedCoords = new Rect(
                    texCoords.x / tex.width,
                    texCoords.y / tex.height,
                    texCoords.width / tex.width,
                    texCoords.height / tex.height
                );

                EditorGUI.DrawRect(imageRect, new Color(0.4f, 0.4f, 0.4f, 1f));
                GUI.DrawTextureWithTexCoords(imageRect, tex, normalizedCoords);
            }
            else
            {
                EditorGUI.DrawRect(imageRect, new Color(0.3f, 0.3f, 0.3f, 1f));
                GUI.Label(imageRect, "无图片", EditorStyles.centeredGreyMiniLabel);
            }

            // 名称按钮（点击选择）
            string displayName = item.Name ?? "???";
            if (displayName.Length > 16)
            {
                displayName = displayName.Substring(0, 14) + "..";
            }
            if (GUILayout.Button(displayName, EditorStyles.miniButton))
            {
                onSelect?.Invoke(item.Name);
                Close();
            }

            EditorGUILayout.EndVertical();
        }
    }
}
