using UnityEngine;
using UnityEditor;
using System.IO;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using System.Collections.Generic;
using System;
using UnityEditor.PackageManager.Requests;
using UnityEditor.PackageManager;
using System.Linq;

namespace Combo
{
    public class ComboSDKWindowsPostBuild
    {
        public class PrePostBuild : IPreprocessBuildWithReport
        {
            public int callbackOrder { get { return 0; } }

            public void OnPreprocessBuild(BuildReport report)
            {
                if (report.summary.platform != BuildTarget.StandaloneWindows && report.summary.platform != BuildTarget.StandaloneWindows64)
                {
                    return;
                }
                var domains = Utils.GetAllDomains();

                foreach (KeyValuePair<string, string> kvp in Utils.thirdNameDic)
                {
                    if (!Array.Exists(domains, element => element == kvp.Value))
                    {
                        Utils.AddOrRemovePrefix(Utils.GetPath(kvp.Key, false), true);
                    }
                }
            }
        }

        private static void RenameFile()
        {
            var domains = Utils.GetAllDomains();

            foreach (KeyValuePair<string, string> kvp in Utils.thirdNameDic)
            {
                if (!Array.Exists(domains, element => element == kvp.Value))
                {
                    Utils.AddOrRemovePrefix(Utils.GetPath(kvp.Key, true), false);
                }
            }
        }

        [UnityEditor.Callbacks.PostProcessBuild(1)]
        public static void OnPostProcessBuild(BuildTarget target, string executablePath)
        {
            var targetGroup = BuildPipeline.GetBuildTargetGroup(target);
            if (targetGroup != BuildTargetGroup.Standalone)
            {
                return;
            }
            Debug.Log("[ComboSDK] Adding windows support.");
            var buildOutputDir = Path.GetDirectoryName(executablePath);
            var executableName = Path.GetFileName(executablePath);
            AddCrashHandler(target, buildOutputDir, executableName);
            RenameFile();
        }

        private static void AddCrashHandler(BuildTarget target, string buildOutputDir, string executableName)
        {
            string crashpadPath;
            if (target == BuildTarget.StandaloneWindows64)
            {
                crashpadPath = Path.Combine("Windows", "Sentry", "crashpad_handler.exe");
            }
            else
            {
                throw new ArgumentException($"Unsupported build target: {target}");
            }

            crashpadPath = Path.GetFullPath(Path.Combine("Packages", "com.seayoo.sdk", "Sentry", "Plugins", crashpadPath));
            var targetPath = Path.Combine(buildOutputDir, Path.GetFileName(crashpadPath));
            Debug.Log($"Copying the native crash handler '{Path.GetFileName(crashpadPath)}' to {targetPath}");
            File.Copy(crashpadPath, targetPath, true);
        }
    }

    public class Utils
    {
        private class ComboSDKJsonData
        {
            public string distro;
            public string[] domains;
            public string parameters;
        }

        public static string[] GetAllDomains()
        {
            try
            {
                string jsonContent;
                if(string.IsNullOrEmpty(Configuration.Instance.WindowsComboSDKJsonPath))
                {
                    jsonContent = File.ReadAllText(Path.Combine(Application.dataPath, "Resources/ComboSDK.json"));
                }
                else
                {
                    jsonContent = File.ReadAllText(Configuration.Instance.WindowsComboSDKJsonPath);
                }
                ComboSDKJsonData comboSDKJsonData = JsonUtility.FromJson<ComboSDKJsonData>(jsonContent);
                return comboSDKJsonData.domains;
            } 
            catch (Exception error)
            {
                throw new BuildFailedException("[ComboSDK]: " + error);
            }
        }

        public static string GetPath(string name, bool isRemove)
        {
            if (isRemove)
            {
                name = name + "~";
                return GetPath(name);
            }
            else
            {
                return GetPath(name);
            }
        }

        private static string GetPath(string name)
        {
            var path = Path.GetFullPath(Path.Combine(Application.dataPath, "../Packages/com.seayoo.sdk/Combo/Plugins/Windows/Plugins/", name));
            if (Directory.Exists(path))
            {
                return path;
            }
            return Path.GetFullPath(Path.Combine(GetCurrentPackageRoot("com.seayoo.sdk"), "Combo/Plugins/Windows/Plugins/", name));
        }

        private static string GetCurrentPackageRoot(string packageName)
        {
            if (string.IsNullOrEmpty(packageName))
            {
                Debug.LogError("Parameter packageName cannot be null or empty.");
                return null;
            }
            ListRequest listRequest = Client.List();
            while (!listRequest.IsCompleted) { }

            if (listRequest.Status == StatusCode.Success)
            {
                var packageInfo = listRequest.Result.FirstOrDefault(p => p.name == packageName);
                if (packageInfo != null)
                {
                    return packageInfo.resolvedPath;
                }
                else
                {
                    Debug.LogError($"The specified package '{packageName}' could not be found.");
                }
            }
            else
            {
                Debug.LogError("Failed to retrieve the package list.");
            }
            return null;
        }

        public static Dictionary<string, string> thirdNameDic = new Dictionary<string, string>
        {
            {"TapSDK", "taptap"},
            {"Lenovo", "lenovo_pc"}
        };

        public static void AddOrRemovePrefix(string folderPath, bool addPrefix)
        {
            if (Directory.Exists(folderPath))
            {
                string parentDirectory = Path.GetDirectoryName(folderPath);
                string currentFolderName = Path.GetFileName(folderPath);
                string newFolderName;

                if (addPrefix)
                {
                    if (!currentFolderName.EndsWith("~"))
                    {
                        newFolderName = currentFolderName + "~";
                    }
                    else
                    {
                        Debug.Log($"Folder already has the prefix '~': {folderPath}");
                        return;
                    }
                }
                else
                {
                    if (currentFolderName.EndsWith("~"))
                    {
                        newFolderName = currentFolderName.Substring(0, currentFolderName.Length - 1);
                    }
                    else
                    {
                        Debug.Log($"Folder does not have the prefix '~': {folderPath}");
                        return;
                    }
                }

                string newPath = Path.Combine(parentDirectory, newFolderName);
                Directory.Move(folderPath, newPath);

                // 删除与文件夹相关的 .meta 文件
                string metaFilePath = folderPath + ".meta";
                if (File.Exists(metaFilePath))
                {
                    File.Delete(metaFilePath);
                    Debug.Log($"Deleted .meta file: {metaFilePath}");
                }
                else
                {
                    Debug.Log($"No .meta file found for: {folderPath}");
                }

                Debug.Log($"Folder renamed successfully: {folderPath} -> {newPath}");
            }
            else
            {
                Debug.Log($"Folder does not exist: {folderPath}");
            }
        }
    }
}