using System;
using System.Diagnostics;
using System.IO;
using UnityEditor;
using UnityEngine;
using Debug = UnityEngine.Debug;

namespace DesignTools
{
    /// <summary>
    /// 策划工具编辑器基类
    /// 提供通用的Docs路径管理、Git操作、UI框架等功能
    /// </summary>
    public abstract class BaseDesignToolEditor : EditorWindow
    {
        #region 常量定义
        
        /// <summary>
        /// Design_SubModule相对路径
        /// </summary>
        protected const string DESIGN_SUBMODULE_PATH = "Assets/Design_SubModule";
        
        #endregion
        
        #region 字段定义
        
        /// <summary>
        /// Docs项目根目录路径
        /// </summary>
        protected string docsRootPath = "";
        
        /// <summary>
        /// 数据是否已加载
        /// </summary>
        protected bool isDataLoaded = false;
        
        /// <summary>
        /// 滚动位置
        /// </summary>
        protected Vector2 scrollPosition;
        
        #endregion
        
        #region 抽象方法和虚方法
        
        /// <summary>
        /// 获取EditorPrefs保存路径的Key
        /// 子类需要返回唯一的Key，例如: "ItemConfigEditor_DocsPath"
        /// </summary>
        protected abstract string GetDocsPathPrefKey();
        
        /// <summary>
        /// 获取工具窗口标题
        /// </summary>
        protected abstract string GetWindowTitle();
        
        /// <summary>
        /// 加载具体的配置数据
        /// 在Git检查和更新完成后调用
        /// </summary>
        protected abstract void LoadConfigData();
        
        /// <summary>
        /// 绘制数据编辑器UI
        /// 在数据加载完成后调用
        /// </summary>
        protected abstract void DrawDataEditor();
        
        /// <summary>
        /// 获取工具窗口的最小尺寸
        /// 默认为 (1000, 600)
        /// </summary>
        protected virtual Vector2 GetMinWindowSize()
        {
            return new Vector2(1000, 600);
        }
        
        /// <summary>
        /// 是否需要检查Design_SubModule分支
        /// 默认为true，子类可以覆盖
        /// </summary>
        protected virtual bool NeedCheckDesignSubModuleBranch()
        {
            return true;
        }
        
        /// <summary>
        /// 获取Docs配置路径相对于Docs根目录的路径
        /// 默认为 "config"，子类可以覆盖
        /// </summary>
        protected virtual string GetDocsConfigPath()
        {
            return "config";
        }
        
        /// <summary>
        /// 是否显示底部操作按钮（保存、重新加载等）
        /// 默认为true
        /// </summary>
        protected virtual bool ShowBottomButtons()
        {
            return true;
        }
        
        /// <summary>
        /// 保存数据到Excel
        /// 子类可以覆盖此方法实现具体的保存逻辑
        /// </summary>
        protected virtual void SaveDataToExcel()
        {
            EditorUtility.DisplayDialog("提示", "此工具未实现保存功能", "确定");
        }
        
        #endregion
        
        #region Unity生命周期
        
        protected virtual void OnEnable()
        {
            // 读取上次保存的路径
            string prefKey = GetDocsPathPrefKey();
            if (EditorPrefs.HasKey(prefKey))
            {
                docsRootPath = EditorPrefs.GetString(prefKey);
            }
        }
        
        protected virtual void OnGUI()
        {
            // 绘制工具栏
            DrawToolbar();
            
            EditorGUILayout.Space(5);
            
            // 绘制Docs路径选择区域
            DrawDocsPathSelector();
            
            EditorGUILayout.Space(5);
            
            // 绘制数据编辑区域或提示信息
            if (isDataLoaded)
            {
                DrawDataEditor();
                
                // 绘制底部操作按钮
                if (ShowBottomButtons())
                {
                    DrawBottomButtons();
                }
            }
            else
            {
                EditorGUILayout.HelpBox("请先选择Docs根目录并加载配置数据", MessageType.Info);
            }
        }
        
        #endregion
        
        #region UI绘制方法
        
        /// <summary>
        /// 绘制工具栏
        /// </summary>
        protected virtual void DrawToolbar()
        {
            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
            EditorGUILayout.LabelField(GetWindowTitle(), EditorStyles.boldLabel);
            GUILayout.FlexibleSpace();
            EditorGUILayout.EndHorizontal();
        }
        
        /// <summary>
        /// 绘制Docs路径选择区域
        /// </summary>
        protected virtual void DrawDocsPathSelector()
        {
            EditorGUILayout.BeginVertical("box");
            EditorGUILayout.LabelField("Docs项目根目录", EditorStyles.boldLabel);
            
            EditorGUILayout.BeginHorizontal();
            docsRootPath = EditorGUILayout.TextField("路径", docsRootPath);
            if (GUILayout.Button("选择文件夹", GUILayout.Width(100)))
            {
                SelectDocsPath();
            }
            EditorGUILayout.EndHorizontal();
            
            if (GUILayout.Button("加载配置数据", GUILayout.Height(30)))
            {
                LoadData();
            }
            
            EditorGUILayout.EndVertical();
        }
        
        /// <summary>
        /// 绘制底部操作按钮
        /// </summary>
        protected virtual void DrawBottomButtons()
        {
            EditorGUILayout.Space(5);
            EditorGUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            
            if (GUILayout.Button("保存到Excel", GUILayout.Height(30), GUILayout.Width(150)))
            {
                SaveDataToExcel();
            }
            
            if (GUILayout.Button("重新加载", GUILayout.Height(30), GUILayout.Width(150)))
            {
                LoadData();
            }
            
            EditorGUILayout.EndHorizontal();
        }
        
        #endregion
        
        #region 路径选择和数据加载
        
        /// <summary>
        /// 选择Docs路径
        /// </summary>
        protected virtual void SelectDocsPath()
        {
            string selectedPath = EditorUtility.OpenFolderPanel("选择Docs项目根目录", "", "");
            if (!string.IsNullOrEmpty(selectedPath))
            {
                docsRootPath = selectedPath;
                EditorPrefs.SetString(GetDocsPathPrefKey(), docsRootPath);
            }
        }
        
        /// <summary>
        /// 加载数据（最终方法，不可覆盖）
        /// </summary>
        protected void LoadData()
        {
            try
            {
                // 1. 校验路径
                if (!ValidateDocsPath())
                {
                    return;
                }
                
                // 2. 检查Docs是否为Git仓库并更新
                if (!CheckAndUpdateDocsRepository())
                {
                    return;
                }
                
                // 3. 检查Design_SubModule分支（如果需要）
                if (NeedCheckDesignSubModuleBranch())
                {
                    if (!CheckAndSwitchDesignSubModuleBranch())
                    {
                        return;
                    }
                }
                
                // 4. 调用子类的具体加载逻辑
                LoadConfigData();
                
                // 5. 设置数据加载完成标志
                isDataLoaded = true;
                
                // 6. 显示成功提示
                EditorUtility.DisplayDialog("成功", "配置数据加载成功！", "确定");
            }
            catch (Exception e)
            {
                EditorUtility.DisplayDialog("错误", $"加载数据失败: {e.Message}\n{e.StackTrace}", "确定");
                isDataLoaded = false;
            }
        }
        
        /// <summary>
        /// 校验Docs路径
        /// </summary>
        protected virtual bool ValidateDocsPath()
        {
            if (string.IsNullOrEmpty(docsRootPath) || !Directory.Exists(docsRootPath))
            {
                EditorUtility.DisplayDialog("错误", "请选择有效的Docs根目录", "确定");
                return false;
            }
            return true;
        }
        
        #endregion
        
        #region Git操作方法
        
        /// <summary>
        /// 执行Git命令
        /// </summary>
        /// <param name="workingDirectory">工作目录</param>
        /// <param name="arguments">Git命令参数</param>
        /// <param name="success">是否执行成功</param>
        /// <returns>命令输出或错误信息</returns>
        protected string ExecuteGitCommand(string workingDirectory, string arguments, out bool success)
        {
            try
            {
                ProcessStartInfo startInfo = new ProcessStartInfo
                {
                    FileName = "git",
                    Arguments = arguments,
                    WorkingDirectory = workingDirectory,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true
                };

                using (Process process = Process.Start(startInfo))
                {
                    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>
        protected virtual bool CheckAndUpdateDocsRepository()
        {
            // 1. 检查是否为Git仓库
            string gitPath = Path.Combine(docsRootPath, ".git");
            if (!Directory.Exists(gitPath))
            {
                EditorUtility.DisplayDialog("错误", 
                    $"Docs目录不是Git仓库\n路径: {docsRootPath}\n\n请确保Docs项目已正确克隆", 
                    "确定");
                return false;
            }

            // 2. 执行Git Fetch
            EditorUtility.DisplayProgressBar("检查更新", "正在检查Docs仓库远程更新...", 0.3f);
            
            string fetchResult = ExecuteGitCommand(docsRootPath, "fetch", out bool fetchSuccess);
            
            if (!fetchSuccess)
            {
                EditorUtility.ClearProgressBar();
                EditorUtility.DisplayDialog("Git Fetch失败", 
                    $"无法检查远程更新:\n{fetchResult}\n\n请在SourceTree或GitHubDesktop中检查网络连接和仓库状态", 
                    "确定");
                return false;
            }

            // 3. 检查仓库状态
            EditorUtility.DisplayProgressBar("检查更新", "正在检查是否有新提交...", 0.6f);
            
            string statusResult = ExecuteGitCommand(docsRootPath, "status -uno", out bool statusSuccess);
            
            if (!statusSuccess)
            {
                EditorUtility.ClearProgressBar();
                EditorUtility.DisplayDialog("Git Status失败", 
                    $"无法获取仓库状态:\n{statusResult}\n\n请在SourceTree或GitHubDesktop中检查仓库状态", 
                    "确定");
                return false;
            }

            // 4. 检查是否有未提交的更改
            if (statusResult.Contains("Changes not staged") || statusResult.Contains("Changes to be committed"))
            {
                EditorUtility.ClearProgressBar();
                bool proceed = EditorUtility.DisplayDialog("警告：有未提交的更改", 
                    "Docs仓库中有未提交的更改，这可能导致拉取时产生冲突。\n\n建议先提交或暂存这些更改。\n\n是否继续加载配置？（不推荐）", 
                    "继续（不推荐）", "取消，前往处理");
                
                if (!proceed)
                {
                    Debug.Log("请在SourceTree或GitHubDesktop中处理未提交的更改");
                    return false;
                }
            }

            // 5. 如果远程有更新，则执行Pull
            if (statusResult.Contains("Your branch is behind"))
            {
                EditorUtility.DisplayProgressBar("更新中", "正在从远程拉取最新代码...", 0.8f);
                
                string pullResult = ExecuteGitCommand(docsRootPath, "pull", out bool pullSuccess);
                
                EditorUtility.ClearProgressBar();
                
                if (!pullSuccess)
                {
                    if (pullResult.Contains("CONFLICT") || pullResult.Contains("conflict"))
                    {
                        EditorUtility.DisplayDialog("拉取失败：存在冲突", 
                            $"拉取远程更新时发生冲突:\n{pullResult}\n\n请在SourceTree或GitHubDesktop中解决冲突后再操作", 
                            "确定");
                    }
                    else
                    {
                        EditorUtility.DisplayDialog("拉取失败", 
                            $"无法拉取远程更新:\n{pullResult}\n\n请在SourceTree或GitHubDesktop中检查并解决问题", 
                            "确定");
                    }
                    return false;
                }
                
                Debug.Log($"Docs仓库已更新到最新版本:\n{pullResult}");
                EditorUtility.DisplayDialog("更新成功", "Docs仓库已更新到最新版本", "确定");
            }
            else
            {
                EditorUtility.ClearProgressBar();
                Debug.Log("Docs仓库已是最新版本");
            }

            return true;
        }
        
        /// <summary>
        /// 检查并切换Design_SubModule到main分支
        /// </summary>
        protected virtual bool CheckAndSwitchDesignSubModuleBranch()
        {
            string designSubModulePath = Path.Combine(Application.dataPath, "..", DESIGN_SUBMODULE_PATH);
            designSubModulePath = Path.GetFullPath(designSubModulePath);

            if (!Directory.Exists(designSubModulePath))
            {
                EditorUtility.DisplayDialog("错误", 
                    $"Design_SubModule目录不存在:\n{designSubModulePath}\n\n请确保子模块已正确初始化", 
                    "确定");
                return false;
            }

            EditorUtility.DisplayProgressBar("检查分支", "正在检查Design_SubModule分支...", 0.5f);

            string branchResult = ExecuteGitCommand(designSubModulePath, "branch --show-current", out bool branchSuccess);
            
            if (!branchSuccess)
            {
                EditorUtility.ClearProgressBar();
                EditorUtility.DisplayDialog("Git Branch失败", 
                    $"无法获取当前分支:\n{branchResult}\n\n请在SourceTree或GitHubDesktop中检查Design_SubModule状态", 
                    "确定");
                return false;
            }

            string currentBranch = branchResult.Trim();
            
            if (currentBranch != "main")
            {
                EditorUtility.DisplayProgressBar("切换分支", "正在切换到main分支...", 0.8f);
                
                string checkoutResult = ExecuteGitCommand(designSubModulePath, "checkout main", out bool checkoutSuccess);
                
                EditorUtility.ClearProgressBar();
                
                if (!checkoutSuccess)
                {
                    EditorUtility.DisplayDialog("切换分支失败", 
                        $"无法切换到main分支:\n{checkoutResult}\n\n当前分支: {currentBranch}\n\n请在SourceTree或GitHubDesktop中手动切换到main分支", 
                        "确定");
                    return false;
                }
                
                Debug.Log($"Design_SubModule已从 {currentBranch} 切换到 main 分支");
            }
            else
            {
                EditorUtility.ClearProgressBar();
                Debug.Log("Design_SubModule已在main分支");
            }

            return true;
        }
        
        #endregion
        
        #region 工具方法
        
        /// <summary>
        /// 获取Docs配置文件的完整路径
        /// </summary>
        /// <param name="fileName">文件名（包含扩展名）</param>
        /// <returns>完整路径</returns>
        protected string GetDocsConfigFilePath(string fileName)
        {
            return Path.Combine(docsRootPath, GetDocsConfigPath(), fileName);
        }
        
        /// <summary>
        /// 获取Docs根目录下的完整路径
        /// </summary>
        /// <param name="relativePath">相对路径</param>
        /// <returns>完整路径</returns>
        protected string GetDocsFullPath(string relativePath)
        {
            return Path.Combine(docsRootPath, relativePath);
        }
        
        #endregion
    }
}
