using System.Diagnostics;
using System.IO.Compression;
using System.Text;

namespace AmazTool
{
    internal class UpgradeApp
    {
        public static bool Upgrade(string fileName)
        {
            Utils.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}");

            if (!File.Exists(fileName))
            {
                Utils.WriteLine(Resx.Resource.UpgradeFileNotFound);
                return false;
            }

            Utils.Waiting(5);

            KillV2rayN();

            Utils.WriteLine(Resx.Resource.StartUnzipping);
            StringBuilder sb = new();
            try
            {
                var splitKey = "/";

                using var archive = ZipFile.OpenRead(fileName);
                foreach (var entry in archive.Entries)
                {
                    try
                    {
                        if (entry.Length == 0)
                        {
                            continue;
                        }

                        Utils.WriteLine(entry.FullName);

                        var lst = entry.FullName.Split(splitKey);
                        if (lst.Length == 1)
                        {
                            continue;
                        }

                        var fullName = string.Join(splitKey, lst[1..lst.Length]);
                        var entryOutputPath = Utils.GetPath(fullName);
                        Directory.CreateDirectory(Path.GetDirectoryName(entryOutputPath)!);
                        //In the bin folder, if the file already exists, it will be skipped
                        if (fullName.StartsWith("bin") && File.Exists(entryOutputPath))
                        {
                            continue;
                        }
                        entry.ExtractToFile(entryOutputPath, true);

                        Utils.WriteLine(entryOutputPath);
                    }
                    catch (Exception ex)
                    {
                        sb.Append(ex.Message);
                        sb.Append(ex.StackTrace);
                    }
                }
            }
            catch (Exception ex)
            {
                sb.Append(Resx.Resource.FailedUpgrade + ex.StackTrace);
            }

            if (sb.Length <= 0)
            {
                return true;
            }

            Utils.WriteLine(sb.ToString());
            Utils.WriteLine(Resx.Resource.FailedUpgrade);
            return false;
        }

        public static bool Init()
        {
            //Process temporary files generated by the last update
            var files = Directory.GetFiles(Utils.GetPath(""), "*.tmp");
            foreach (var file in files)
            {
                if (file.Contains(Utils.AmazTool))
                {
                    File.Delete(file);
                }
            }

            var destFileName = $"{Utils.GetExePath()}{Guid.NewGuid().ToString("N")[..8]}.tmp";
            File.Move(Utils.GetExePath(), destFileName);

            return true;
        }

        private static bool KillV2rayN()
        {
            Utils.WriteLine(Resx.Resource.TryTerminateProcess);
            try
            {
                var existing = Process.GetProcessesByName(Utils.V2rayN);
                foreach (var pp in existing)
                {
                    var path = pp.MainModule?.FileName ?? "";
                    if (path.StartsWith(Utils.GetPath(Utils.V2rayN)))
                    {
                        pp?.Kill();
                        pp?.WaitForExit(1000);
                    }
                }
            }
            catch (Exception ex)
            {
                // Access may be denied without admin right. The user may not be an administrator.
                Utils.WriteLine(Resx.Resource.FailedTerminateProcess + ex.StackTrace);
            }

            return true;
        }
    }
}
