﻿#region Header

// Copyright (c) 2026 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.

#endregion

using UnityEditor;
using UnityEngine;
using System.IO;
using UnityEngine.Networking;
using System.Threading.Tasks;

#if UNITY_EDITOR
namespace BlackBox
{
    // NOTE: download blackbox_helper.exe and blackbox_issue_reporter.exe if not exists
    public static class BlackBoxHelperInstaller
    {
        private const string SESSION_KEY_DISMISSED = "BlackBox.DownloadWindow.Dismissed";
        public static readonly string CRASH_HELPER_VERSION = "1.3.3";
        public static readonly string ISSUE_REPORTER_VERSION = "1.2.1";
        private static string CrashHelperDownloadURL = $"https://cdn.prod.blackbox.accelbyte.io/sdk/helper/{CRASH_HELPER_VERSION}/blackbox_helper.exe";
        private static string IssueReporterDownloadURL = $"https://cdn.prod.blackbox.accelbyte.io/sdk/reporter/{ISSUE_REPORTER_VERSION}/blackbox_issue_reporter.exe";
        private static readonly string CrashHelperPath = Path.Combine(Application.streamingAssetsPath, "BlackBox", "helper", "blackbox_helper.exe");
        private static readonly string IssueReporterPath = Path.Combine(Application.streamingAssetsPath, "BlackBox", "issue_reporter", "blackbox_issue_reporter.exe");

        public static void Run()
        {
            if (BothExeExist())
                return;

            if (SessionState.GetBool(SESSION_KEY_DISMISSED, false))
                return;

            EditorApplication.delayCall += BlackBoxHelperDownloadWindow.Open;
        }

        public static void StartDownloadFromUI()
        {
            EditorApplication.delayCall += () =>
            {
                _ = DownloadTask();
            };
        }

        public static void MarkDismissed()
        {
            SessionState.SetBool(SESSION_KEY_DISMISSED, true);
        }

        private static bool BothExeExist()
        {
            return File.Exists(CrashHelperPath) && File.Exists(IssueReporterPath);
        }

        private static async Task DownloadTask()
        {
            ResolveDownloadURLs();

            try
            {
                var downloaded = false;

                if (!File.Exists(CrashHelperPath))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(CrashHelperPath));
                    await DownloadFile(CrashHelperDownloadURL, CrashHelperPath, "BlackBox Helper");
                    downloaded = true;
                }

                if (!File.Exists(IssueReporterPath))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(IssueReporterPath));
                    await DownloadFile(IssueReporterDownloadURL, IssueReporterPath, "BlackBox Issue Reporter");
                    downloaded = true;
                }

                EditorUtility.ClearProgressBar();
                AssetDatabase.Refresh();

                if (downloaded)
                {
                    BlackBoxRestartWindow.Open();
                }
            }
            catch (System.Exception ex)
            {
                EditorUtility.ClearProgressBar();
                Logger.LogError($"Failed to download BlackBox exe: {ex}");
            }
        }

        private static void ResolveDownloadURLs()
        {
            var baseUrl = BlackBoxConfig.Instance.BaseUrl;

            string env;
            if (baseUrl.Contains("develop"))
                env = "develop";
            else if (baseUrl.Contains("staging"))
                env = "staging";
            else
                env = "prod";

            if (env == "prod") return;

            CrashHelperDownloadURL = CrashHelperDownloadURL.Replace("prod", env);
            IssueReporterDownloadURL = IssueReporterDownloadURL.Replace("prod", env);
        }

        private static async Task DownloadFile(string url, string path, string fileName)
        {
            Logger.Log($"Downloading... {fileName} from \"{url}\" saved to \"{path}\"");

            using var request = UnityWebRequest.Get(url);
            var operation = request.SendWebRequest();

            string progressTitle = fileName == "BlackBox Helper"
                ? $"Downloading {fileName} (1/2)"
                : $"Downloading {fileName} (2/2)";

            while (!operation.isDone)
            {
                EditorUtility.DisplayProgressBar(
                    progressTitle,
                    $"{request.downloadProgress * 100:F1}% ({FormatBytes(request.downloadedBytes)})",
                    request.downloadProgress
                );
                await Task.Yield();
            }

            if (request.result != UnityWebRequest.Result.Success)
            {
                throw new IOException(request.error);
            }

            File.WriteAllBytes(path, request.downloadHandler.data);
            Logger.Log($"Successfully download: {path}");
        }

        private static string FormatBytes(ulong bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB" };
            double len = bytes;
            var order = 0;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len /= 1024;
            }
            return $"{len:0.##} {sizes[order]}";
        }
    }
}
#endif