#if UNITY_IOS
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using System.Linq;
using System.IO;
using UnityEditor.iOS.Xcode;
using UnityEditor.iOS.Xcode.Extensions;


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

		public void OnPreprocessBuild(BuildReport report)
		{
			if (!Configuration.Instance.EnableIOSPostBuild)
			{
				return;
			}
			var comboSDKPath = Configuration.Instance.IOSComboSDK;
			if (comboSDKPath != null)
			{
				var result = XCFrameworkUtility.CompareXCFrameworks();
				if (!string.IsNullOrWhiteSpace(result))
				{
					throw new BuildFailedException("[ComboSDK]: " + result);
				}
			}
		}
	}

	public class ComboSDKIOSPostBuild : IPostprocessBuildWithReport
	{
		public int callbackOrder { get { return 0; } }

		private static readonly string ComboSDKDirectory = "ComboSDK";

		public void OnPostprocessBuild(UnityEditor.Build.Reporting.BuildReport report)
		{
			if (!Configuration.Instance.EnableIOSPostBuild)
			{
				Debug.Log("[ComboSDK] PostBuild iOS is disabled, skipped");
				return;
			}

			if (report.summary.platform == BuildTarget.iOS)
			{
				string projectPath = BuildTargetHelper.GetPBXProjectPath(report);
				Debug.Log($"[ComboSDK] PostBuild iOS init xcodeproj: {projectPath}");
				PBXProject pbxProject = new PBXProject();
				pbxProject.ReadFromFile(projectPath);

				string unityMainTargetGuid = pbxProject.GetUnityMainTargetGuid();
				string unityFrameworkTargetGuid = pbxProject.GetUnityFrameworkTargetGuid();

				//  UnityFramework for Unity-iPhone->Build Phases->Link Binary With Libraries 
				AddUnityFramework(pbxProject, unityMainTargetGuid);

				// Add AuthenticationServices
				pbxProject.AddFrameworkToProject(unityFrameworkTargetGuid, "AuthenticationServices.framework", true);

				// Build Setting
				ConfigBuildSetting(pbxProject, unityMainTargetGuid, unityFrameworkTargetGuid);

				// Add Combo SDK for iOS XCFrameworks and ComboSDK.json
				AssembleIOSSdk(report, pbxProject, unityMainTargetGuid, unityFrameworkTargetGuid);

				// Update Info.plist
				UpdatePListFile(report);

				AddAssociatedDomain(report, pbxProject, unityMainTargetGuid);

				pbxProject.WriteToFile(projectPath);

				Debug.Log($"[ComboSDK] PostBuild iOS init xcodeproj finish!");
			}
		}

		private void AddUnityFramework(PBXProject pbxProject, string mainTargetGuid)
		{
			//  UnityFramework for Tuanjie-iPhone->Build Phases->Link Binary With Libraries 
			string frameworkName = BuildTargetHelper.GetFrameworkName();
			string frameworkPath = Path.GetFullPath(frameworkName);
			Debug.Log($"[ComboSDK] Add UnityFramework: {frameworkPath}");
			var pathGuid = pbxProject.AddFile(frameworkPath, $"Frameworks/{frameworkName}", PBXSourceTree.Source);
			pbxProject.AddFileToBuild(mainTargetGuid, pathGuid);
		}

		private void ConfigBuildSetting(PBXProject pbxProject, string mainTargetGuid, string unityFrameworkTargetGuid)
		{
			SetBuildProperty(pbxProject, mainTargetGuid, unityFrameworkTargetGuid);
			SetOtherCFlags(pbxProject, mainTargetGuid, unityFrameworkTargetGuid);
		}
		private void SetBuildProperty(PBXProject pbxProject, string mainTargetGuid, string frameworkTargetGuid)
		{
			// ENABLE_BITCODE
			pbxProject.SetBuildProperty(mainTargetGuid, "ENABLE_BITCODE", "NO");
			pbxProject.SetBuildProperty(frameworkTargetGuid, "ENABLE_BITCODE", "NO");
			// ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES
			pbxProject.SetBuildProperty(mainTargetGuid, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "YES");
			// LD_RUNPATH_SEARCH_PATHS : /usr/lib/swift
			var runpathSearchPaths = pbxProject.GetBuildPropertyForAnyConfig(mainTargetGuid, "LD_RUNPATH_SEARCH_PATHS");
			if (runpathSearchPaths.Contains("/usr/lib/swift"))
			{
				runpathSearchPaths = runpathSearchPaths.Replace("/usr/lib/swift", "");
				runpathSearchPaths = runpathSearchPaths.Replace("  ", " ");
				if (runpathSearchPaths.EndsWith(" "))
					runpathSearchPaths = runpathSearchPaths.Substring(0, runpathSearchPaths.Length - 1);
			}
			runpathSearchPaths = $"/usr/lib/swift {runpathSearchPaths}";
			pbxProject.SetBuildProperty(mainTargetGuid, "LD_RUNPATH_SEARCH_PATHS", runpathSearchPaths);
		}

		// Fix Xcode 16 Build Error: unsupported option '-mno-thumb' for target 'arm64-apple-iosxxx'
		// Reference: https://discussions.unity.com/t/xcode-16-1-build-failing-unsupported-option-mno-thumb-for-target-arm64-apple-ios11-0/1563505/1
		private void SetOtherCFlags(PBXProject pbxProject, string mainTargetGuid, string unityFrameworkTargetGuid)
		{
			var otherCFlags = pbxProject.GetBuildPropertyForAnyConfig(mainTargetGuid, "OTHER_CFLAGS");

			if (!string.IsNullOrEmpty(otherCFlags) && otherCFlags.Contains("-mno-thumb"))
			{
				var newOtherCFlags = otherCFlags.Replace("-mno-thumb", "").Trim();
				pbxProject.SetBuildProperty(mainTargetGuid, "OTHER_CFLAGS", newOtherCFlags);
			}
		}

		private void AssembleIOSSdk(BuildReport report, PBXProject pbxProject, string mainTargetGuid, string unityFrameworkTargetGuid)
		{
			var enablePostBuild = Configuration.Instance.EnableIOSPostBuild;
			if (enablePostBuild)
			{
				var comboSDKPath = Configuration.Instance.IOSComboSDK;
				var unityMainFrameworksBuildPhase = pbxProject.GetFrameworksBuildPhaseByTarget(mainTargetGuid);
				var unityFrameworkBuildPhase = pbxProject.GetFrameworksBuildPhaseByTarget(unityFrameworkTargetGuid);

				if (comboSDKPath != null)
				{
					CopyAndAddComboSDKJson(report, pbxProject, mainTargetGuid, comboSDKPath);
					AddFrameworks(comboSDKPath, report, pbxProject, mainTargetGuid, unityMainFrameworksBuildPhase, unityFrameworkTargetGuid, unityFrameworkBuildPhase);
					AddBundleRes(report, pbxProject, mainTargetGuid, comboSDKPath);
				}

				SetBuildPropertyForFramework(pbxProject, mainTargetGuid, unityFrameworkTargetGuid);
			}
			else
			{
				Debug.Log($"[ComboSDK] PostBuild iOS EnableIOSPostBuild = {enablePostBuild}");
			}
		}

		//添加 ComboSDK 依赖的 bundle 资源
		private void AddBundleRes(BuildReport report, PBXProject pbxProject, string mainTargetGuid, string comboSDKPath)
		{
			List<string> relativeBundlePaths = new List<string>
			{
				"ComboSDKTopOn/baidumobadsdk.bundle",
			};

			foreach (var relativePath in relativeBundlePaths)
			{
				string directoryName = Path.GetDirectoryName(relativePath).Split(Path.DirectorySeparatorChar)[0];
				var needFrameworks = XCFrameworkUtility.GetNeedFrameworks();
				if (!needFrameworks.Contains(directoryName))
				{
					continue;
				}
				string fullBundlePath = Path.Combine(comboSDKPath, relativePath);
				string destJsonFilePath = Path.Combine(report.summary.outputPath, ComboSDKDirectory, Path.GetFileName(fullBundlePath));
				Debug.Log($"Processing bundle: {fullBundlePath} to {destJsonFilePath}");

				// Check if the source bundle directory exists
				if (Directory.Exists(fullBundlePath))
				{
					try
					{
						// Ensure the destination directory exists
						if (!Directory.Exists(destJsonFilePath))
						{
							Directory.CreateDirectory(destJsonFilePath);
						}

						// Copy the directory
						CopyDirectory(fullBundlePath, destJsonFilePath);
						Debug.Log($"Successfully copied {fullBundlePath} to {destJsonFilePath}");

						string projPathOfFile = $"{ComboSDKDirectory}/{Path.GetFileName(fullBundlePath)}";
						var guid = pbxProject.AddFile(projPathOfFile, projPathOfFile, PBXSourceTree.Source);
						pbxProject.AddFileToBuild(mainTargetGuid, guid);
					}
					catch (Exception ex)
					{
						Debug.Log($"Failed to copy {fullBundlePath} to {destJsonFilePath}: {ex.Message}");
					}
				}
				else
				{
					Debug.Log($"The directory {fullBundlePath} does not exist. Skipping the operation.");
				}
			}
		}

		// Recursive directory copy
		private void CopyDirectory(string sourceDir, string destDir)
		{
			// Create the destination directory if it doesn't exist
			Directory.CreateDirectory(destDir);

			// Copy all files
			foreach (string filePath in Directory.GetFiles(sourceDir))
			{
				string destFilePath = Path.Combine(destDir, Path.GetFileName(filePath));
				File.Copy(filePath, destFilePath, true);
			}

			// Copy all subdirectories
			foreach (string directoryPath in Directory.GetDirectories(sourceDir))
			{
				string destSubDir = Path.Combine(destDir, Path.GetFileName(directoryPath));
				CopyDirectory(directoryPath, destSubDir);
			}
		}


		private void AddFrameworks(string szFrameworkPath, BuildReport report, PBXProject pbxProject,
			string mainTargetGuid, string mainFrameworksBuildPhase, string frameworkTargetGuid, string frameworkBuildPhase)
		{
			// 扫描一级目录
			var levelOneDirectories = Directory.GetDirectories(szFrameworkPath);
			var frameworks = new Dictionary<string, List<string>>();

			foreach (var levelOneDirectory in levelOneDirectories)
			{
				var levelOneDirectoryName = Path.GetFileName(levelOneDirectory);
				var needFrameworks = XCFrameworkUtility.GetNeedFrameworks();
				if (!needFrameworks.Contains(levelOneDirectoryName))
				{
					continue;
				}
				// 筛选一级目录 .xcframework 和 .framework 目录
				if (levelOneDirectoryName.EndsWith(".xcframework") || levelOneDirectoryName.EndsWith(".framework"))
				{
					if (!frameworks.ContainsKey(szFrameworkPath))
					{
						frameworks[szFrameworkPath] = new List<string>();
					}
					frameworks[szFrameworkPath].Add(levelOneDirectoryName);
				}
				else
				{
					// 扫描第二级目录
					var levelTwoDirectories = Directory.GetDirectories(levelOneDirectory);

					// 通过名称筛选出 .xcframework 和 .framework 目录
					var frameworkDirectories = levelTwoDirectories.Where(directory =>
						directory.EndsWith(".xcframework") || directory.EndsWith(".framework")).ToArray();

					if (frameworkDirectories.Length > 0)
					{
						frameworks[levelOneDirectory] = frameworkDirectories.Select(Path.GetFileName).ToList();
					}
				}
			}

			foreach (var pair in frameworks)
			{
				foreach (var frameworkName in pair.Value)
				{
					string destPath = Path.Combine(report.summary.outputPath, ComboSDKDirectory, frameworkName);
					DirectoryCopy(Path.Combine(pair.Key, frameworkName), destPath);

					string projPathOfFile = $"{ComboSDKDirectory}/{frameworkName}";

					string fileGuid = pbxProject.AddFile(projPathOfFile, projPathOfFile, PBXSourceTree.Source);
					if (fileGuid != null)
					{
						pbxProject.AddFileToEmbedFrameworks(mainTargetGuid, fileGuid);
						pbxProject.AddFileToBuildSection(mainTargetGuid, mainFrameworksBuildPhase, fileGuid);
						pbxProject.AddFileToBuildSection(frameworkTargetGuid, frameworkBuildPhase, fileGuid);
					}
					else
					{
						Debug.Log($"{frameworkName} file not found!");
					}
				}
			}
		}

		// Framework search path
		private void SetBuildPropertyForFramework(PBXProject pbxProject, string mainTargetGuid, string unityFrameworkTargetGuid)
		{
			pbxProject.AddBuildProperty(mainTargetGuid, "FRAMEWORK_SEARCH_PATHS", $"$(PROJECT_DIR)/{ComboSDKDirectory}");
			pbxProject.AddBuildProperty(unityFrameworkTargetGuid, "FRAMEWORK_SEARCH_PATHS", $"$(PROJECT_DIR)/{ComboSDKDirectory}");
		}

		private void CopyAndAddComboSDKJson(BuildReport report, PBXProject pbxProject, string mainTargetGuid, string comboSDKPath)
		{
			string destFolder = Path.Combine(report.summary.outputPath, ComboSDKDirectory);

			if (!Directory.Exists(destFolder))
			{
				Directory.CreateDirectory(destFolder);
			}

			Debug.Log($"ComboSDKJson = {destFolder}");

			foreach (string jsonFile in Directory.GetFiles(comboSDKPath, "*.json"))
			{
				string destJsonFilePath = Path.Combine(destFolder, Path.GetFileName(jsonFile));
				CopyFile(jsonFile, destJsonFilePath);
				string projPathOfFile = $"{ComboSDKDirectory}/{Path.GetFileName(jsonFile)}";
				var guid = pbxProject.AddFile(projPathOfFile, projPathOfFile, PBXSourceTree.Source);
				pbxProject.AddFileToBuild(mainTargetGuid, guid);
			}
		}

		private void UpdatePListFile(BuildReport report)
		{
			var plistPath = $"{report.summary.outputPath}/Info.plist";
			var plist = new PlistDocument();
			plist.ReadFromFile(plistPath);
			var domains = XCFrameworkUtility.GetAllDomains();
			var parameters = XCFrameworkUtility.GetAllParameters();
			// Check if LSApplicationQueriesSchemes key exists, if not create one
			if (!plist.root.values.ContainsKey("LSApplicationQueriesSchemes"))
			{
				plist.root.CreateArray("LSApplicationQueriesSchemes");
			}
			PlistElementArray queriesSchemes = plist.root.values["LSApplicationQueriesSchemes"].AsArray();

			foreach (var domain in domains)
			{
				switch (domain)
				{
					case XCFrameworkUtility.TOPON:
					case XCFrameworkUtility.DOUYIN:
					case XCFrameworkUtility.TRACKINGIO:
						plist.root.SetString("NSUserTrackingUsageDescription", "此标识符将用于向您提供个性化广告。");
						break;
					case XCFrameworkUtility.BDA:
						AddUrlScheme(plist, "", PlayerSettings.applicationIdentifier);
						break;
					case XCFrameworkUtility.WEIBO:
						var weiboScheme = "wb" + parameters.weibo_app_key;
						AddUrlScheme(plist, "weibo", weiboScheme);
						AddQueryScheme(queriesSchemes, new string[] { "sinaweibo", "weibosdk", "weibosdk2.5", "weibosdk3.3" });
						break;
					case XCFrameworkUtility.WEIXIN:
						AddUrlScheme(plist, "weixin", parameters.weixin_app_id);
						AddQueryScheme(queriesSchemes, new string[] { "weixinULAPI", "weixinURLParamsAPI" });
						break;
					case XCFrameworkUtility.DOUYIN_OPEN:
						AddUrlScheme(plist, "douyin", parameters.douyin_open_app_id);
						AddQueryScheme(queriesSchemes, new string[] { "douyinliteopensdk", "douyinsharesdk", "snssdk1128", "douyinopensdk" });
						AddPhotoLibraryUsageDescription(plist, "此应用需要访问您的相册用于分享图片或视频。");
						break;
					case XCFrameworkUtility.AGORA:
						var agoraScheme = "xhs" + parameters.agora_ios_app_key;
						AddUrlScheme(plist, "xiaohongshu", agoraScheme);
						AddQueryScheme(queriesSchemes, new string[] { "xhsdiscover" });
						AddPhotoLibraryUsageDescription(plist, "此应用需要访问您的相册用于分享图片或视频。");
						break;
					case XCFrameworkUtility.QQ:
						var qqScheme = "tencent" + parameters.qq_app_id;
						AddUrlScheme(plist, "qq", qqScheme);
						AddQueryScheme(queriesSchemes, new string[] { "mqq", "mqqapi", "tim", "mqqopensdknopasteboard", "mqqopensdknopasteboardios16", "mqqopensdkapiV2", "mqzone", "mqqOpensdkSSoLogin", "mqqOpensdkSSoLogin" });
						break;
				}
			}
			// Sign up for weixin scheme to jump to weixin
			AddQueryScheme(queriesSchemes, new string[] { "weixin" });

			// Hidden status bar
			plist.root.SetBoolean("UIStatusBarHidden", true);
			plist.root.SetBoolean("UIViewControllerBasedStatusBarAppearance", false);

			// Add NSCameraUsageDescription
			AddCameraUsageDescription(plist, "此应用需要访问您的相机用于拍摄照片或视频。");

			// Add NSPhotoLibraryUsageDescription
			AddPhotoLibraryUsageDescription(plist, "此应用需要访问您的相册。");

			// Add AddMicrophoneUsageDescription
			AddMicrophoneUsageDescription(plist, "此应用需要访问您的麦克风用于录制音频。");

			plist.WriteToFile(plistPath);
		}

		private void AddPhotoLibraryUsageDescription(PlistDocument plist, string description)
		{
			const string photoLibraryUsageKey = "NSPhotoLibraryUsageDescription";
			// Check if the key exists, if not create one
			if (!plist.root.values.ContainsKey(photoLibraryUsageKey))
			{
				plist.root.SetString(photoLibraryUsageKey, description);
			}
		}

		private void AddCameraUsageDescription(PlistDocument plist, string description)
		{
			const string cameraUsageKey = "NSCameraUsageDescription";
			// Check if the key exists, if not create one
			if (!plist.root.values.ContainsKey(cameraUsageKey))
			{
				plist.root.SetString(cameraUsageKey, description);
			}
		}

		private void AddMicrophoneUsageDescription(PlistDocument plist, string description)
		{
			const string microphoneUsageKey = "NSMicrophoneUsageDescription";
			// Check if the key exists, if not create one
			if (!plist.root.values.ContainsKey(microphoneUsageKey))
			{
				plist.root.SetString(microphoneUsageKey, description);
			}
		}

		private void AddQueryScheme(PlistElementArray queriesSchemes, string[] schemes)
		{
			foreach (var scheme in schemes)
			{
				if (!queriesSchemes.values.Any(element => element.AsString() == scheme))
				{
					queriesSchemes.AddString(scheme);
				}
			}
		}

		private static void AddUrlScheme(PlistDocument plist, string name, string scheme)
		{
			// 获取根字典元素
			var rootDict = plist.root;

			// 查找现有的URL类型，如果不存在则创建新的数组
			PlistElementArray urlTypes;
			if (rootDict.values.ContainsKey("CFBundleURLTypes"))
			{
				urlTypes = rootDict.values["CFBundleURLTypes"].AsArray();
			}
			else
			{
				urlTypes = plist.root.CreateArray("CFBundleURLTypes");
			}

			// 创建一个新的字典来存储URL Scheme信息
			PlistElementDict urlTypeDict = urlTypes.AddDict();

			// 设置这个新的URL Scheme的角色
			urlTypeDict.SetString("CFBundleTypeRole", "Editor");

			// 为这个新的URL Scheme指定一个唯一的标识名
			if (!string.IsNullOrEmpty(name))
			{
				urlTypeDict.SetString("CFBundleURLName", name);
			}

			// 创建一个数组来保存具体的URL Scheme字符串
			PlistElementArray urlSchemes = urlTypeDict.CreateArray("CFBundleURLSchemes");

			// 添加URL Scheme到数组中
			urlSchemes.AddString(scheme);
		}

		private void AddAssociatedDomain(BuildReport report, PBXProject pbxProject, string mainTargetGuid)
		{
			// 检查是否有需要处理的特殊 domain
			var domains = XCFrameworkUtility.GetAllDomains();
			if (domains.Any(domain => domain == XCFrameworkUtility.WEIBO || domain == XCFrameworkUtility.WEIXIN || domain == XCFrameworkUtility.AGORA))
			{
				string entitlementsPath = BuildTargetHelper.GetEntitlementsPath(report);
				PlistDocument entitlements = new PlistDocument();

				// 尝试读取现有的entitlements文件，如果不存在则创建新的
				if (File.Exists(entitlementsPath))
				{
					entitlements.ReadFromString(File.ReadAllText(entitlementsPath));
				}
				else
				{
					entitlements.root.CreateArray("com.apple.developer.associated-domains");
				}

				PlistElementArray associatedDomains = entitlements.root["com.apple.developer.associated-domains"].AsArray();

				var universalLink = XCFrameworkUtility.GetAllParameters().game_universal_link;
				if (Uri.TryCreate(universalLink, UriKind.Absolute, out Uri linkUri))
				{
					string domain = linkUri.Host; // 提取域名，例如从https://xxxxx/app/中提取xxxxx
					string applinksEntry = $"applinks:{domain}";

					if (!associatedDomains.values.Any(element => element.AsString() == applinksEntry))
					{
						associatedDomains.AddString(applinksEntry);
					}
				}
				else
				{
					Debug.LogError($"无效的universal link URL: {universalLink}");
					return; // 无效的URL，不继续执行
				}

				// 写回entitlements文件
				File.WriteAllText(entitlementsPath, entitlements.WriteToString());

				// 将entitlements添加到Xcode项目中
				string relativeEntitlementsPath = BuildTargetHelper.GetRelativeEntitlementsPath();
				pbxProject.AddFile(relativeEntitlementsPath, relativeEntitlementsPath, PBXSourceTree.Source);
				pbxProject.AddCapability(mainTargetGuid, PBXCapabilityType.AssociatedDomains, relativeEntitlementsPath);
			}
		}

		private static bool CopyFile(string sourcePath, string targetPath)
		{
			try
			{
				File.Copy(sourcePath, targetPath, true);
				UnityEngine.Debug.Log("Copy \"" + sourcePath + "\" to \"" + targetPath + "\" succeed");
				return true;
			}
			catch (Exception e)
			{
				UnityEngine.Debug.LogError("Copy failed：" + e.Message);
			}
			return false;
		}

		private static void DirectoryCopy(
			string sourceDirName,
			string destDirName,
			bool copySubDirs = true
		)
		{
			DirectoryInfo dir = new DirectoryInfo(sourceDirName);
			DirectoryInfo[] dirs = dir.GetDirectories();

			// If the source directory does not exist, throw an exception.
			if (!dir.Exists)
			{
				throw new DirectoryNotFoundException(
					"Source directory does not exist or could not be found: " + sourceDirName
				);
			}

			// If the destination directory does not exist, create it.
			if (!Directory.Exists(destDirName))
			{
				Directory.CreateDirectory(destDirName);
			}

			// Get the file contents of the directory to copy.
			FileInfo[] files = dir.GetFiles();

			foreach (FileInfo file in files)
			{
				// Create the path to the new copy of the file.
				string temppath = Path.Combine(destDirName, file.Name);

				// Copy the file.
				file.CopyTo(temppath, true);
			}

			// If copySubDirs is true, copy the subdirectories.
			if (copySubDirs)
			{
				foreach (DirectoryInfo subdir in dirs)
				{
					// Create the subdirectory.
					string temppath = Path.Combine(destDirName, subdir.Name);

					// Copy the subdirectories.
					DirectoryCopy(subdir.FullName, temppath, copySubDirs);
				}
			}
		}
	}

	public static class BuildTargetHelper
	{
		public static string GetMainTargetName()
		{
#if TUANJIE_1
			return "Tuanjie-iPhone";
#else
			return "Unity-iPhone";
#endif
		}

		public static string GetFrameworkName()
		{
#if TUANJIE_1
			return "TuanjieFramework.framework";
#else
			return "UnityFramework.framework";
#endif
		}

		public static string GetPBXProjectPath(BuildReport report)
		{
			return Path.Combine(report.summary.outputPath, $"{GetMainTargetName()}.xcodeproj/project.pbxproj");
		}

		public static string GetEntitlementsPath(BuildReport report)
		{
			return Path.Combine(report.summary.outputPath, $"{GetMainTargetName()}/{GetMainTargetName()}.entitlements");
		}

		public static string GetRelativeEntitlementsPath()
		{
			return $"{GetMainTargetName()}/{GetMainTargetName()}.entitlements";
		}
	}

	public static class XCFrameworkUtility
	{
		public const string APP_STORE_CONNECT = "app_store_connect";
		public const string SEAYOO_ACCOUNT = "seayoo_account";
		public const string SENTRY = "sentry";
		public const string SING_IN_WITH_APPLE = "sign_in_with_apple";
		public const string TOPON = "topon";
		public const string TRACKINGIO = "trackingio";
		public const string UPUSH = "upush";
		public const string BDA = "bda";
		public const string AGORA = "agora";
		public const string WEIXIN = "weixin";
		public const string DOUYIN_OPEN = "douyin_open";
		public const string WEIBO = "weibo";
		public const string SOLAR_ENGINE = "solar_engine";
		public const string GUEST = "guest";
		public const string DOUYIN = "douyin";
		public const string QQ = "qq";
		public static Dictionary<string, string> domainsXCFrameworksDic = new Dictionary<string, string>
		{
			{ APP_STORE_CONNECT, "ComboSDKAppStoreConnect.xcframework" },
			{ SEAYOO_ACCOUNT, "ComboSDKSeayooAccount.xcframework" },
			{ SENTRY, "ComboSDKSentry" },
			{ SING_IN_WITH_APPLE, "ComboSDKSignInWithApple.xcframework" },
			{ TOPON, "ComboSDKTopOn" },
			{ TRACKINGIO, "ComboSDKTrackingIO.xcframework" },
			{ UPUSH, "ComboSDKUPush.xcframework" },
			{ BDA, "ComboSDKBDASignal" },
			{ AGORA, "ComboSDKAgora.xcframework" },
			{ WEIXIN, "ComboSDKWeixin.xcframework" },
			{ DOUYIN_OPEN, "ComboSDKDouyinOpen.xcframework" },
			{ WEIBO, "ComboSDKWeibo.xcframework" },
			{ SOLAR_ENGINE, "ComboSDKSolarEngine.xcframework" },
			{ GUEST, "ComboSDKGuest.xcframework" },
			{ DOUYIN, "ComboSDKDouyin" },
			{ QQ, "ComboSDKQQ.xcframework" },
		};
		private class ComboSDKJsonData
		{
			public string distro;
			public string[] domains;
			public Parameters parameters;
		}

		[Serializable]
		public class Parameters
		{
			public string weibo_app_key;
			public string weixin_app_id;
			public string douyin_open_app_id;
			public string agora_ios_app_key;
			public string game_universal_link;
			public string qq_app_id;
		}

		public static string CompareXCFrameworks()
		{
			var needFrameworks = GetNeedFrameworks();
			var allFrameworks = GetAllFrameworks();
			var missingFrameworks = needFrameworks.Except(allFrameworks).ToList();
			if (missingFrameworks.Count != 0)
			{
				return "The following XCFramework components are missing: \n" + string.Join("\n", missingFrameworks);
			}
			return "";
		}

		public static string[] GetAllDomains()
		{
			string jsonContent = System.IO.File.ReadAllText(Path.Combine(Configuration.Instance.IOSComboSDK, "ComboSDK.json"));
			ComboSDKJsonData comboSDKJsonData = JsonUtility.FromJson<ComboSDKJsonData>(jsonContent);
			Debug.Log($"json = {jsonContent}");
			return comboSDKJsonData.domains;
		}

		public static Parameters GetAllParameters()
		{
			string jsonContent = System.IO.File.ReadAllText(Path.Combine(Configuration.Instance.IOSComboSDK, "ComboSDK.json"));
			ComboSDKJsonData comboSDKJsonData = JsonUtility.FromJson<ComboSDKJsonData>(jsonContent);
			return comboSDKJsonData.parameters;
		}

		//private static

		public static List<string> GetNeedFrameworks()
		{
			if (string.IsNullOrWhiteSpace(Configuration.Instance.IOSComboSDK))
			{
				return new List<string>();
			}
			var needFrameworks = new List<string> { "ComboSDK.xcframework" };
			string jsonContent = System.IO.File.ReadAllText(Path.Combine(Configuration.Instance.IOSComboSDK, "ComboSDK.json"));
			ComboSDKJsonData comboSDKJsonData = JsonUtility.FromJson<ComboSDKJsonData>(jsonContent);
			foreach (var domain in comboSDKJsonData.domains)
			{
				string needFramework;
				if (domainsXCFrameworksDic.TryGetValue(domain, out needFramework))
				{
					needFrameworks.Add(needFramework);
				}
			}
			return needFrameworks;
		}

		private static List<string> GetAllFrameworks()
		{
			if (string.IsNullOrWhiteSpace(Configuration.Instance.IOSComboSDK))
			{
				return new List<string>();
			}
			var levelOneDirectories = Directory.GetDirectories(Configuration.Instance.IOSComboSDK);
			var frameworks = new List<string>();
			foreach (var levelOneDirectory in levelOneDirectories)
			{
				var levelOneDirectoryName = Path.GetFileName(levelOneDirectory);
				frameworks.Add(levelOneDirectoryName);
			}
			return frameworks;
		}
	}
}
#endif