using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;

namespace VideoStudy.Shared.Services;

public interface IHardwareIdService
{
    string GetHardwareId();
}

public class HardwareIdService : IHardwareIdService
{
    public string GetHardwareId()
    {
        try
        {
            string rawId;
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                rawId = GetWindowsHardwareId();
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                rawId = GetMacOSHardwareId();
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                rawId = GetLinuxHardwareId();
            else
                rawId = "UNKNOWN_PLATFORM_" + Environment.MachineName;

            return ComputeSHA256(rawId);
        }
        catch
        {
            // Fallback for permissions issues
            return ComputeSHA256(Environment.MachineName + Environment.UserName);
        }
    }

    private string GetWindowsHardwareId()
    {
        // Simple fallback to MachineName + ProcessorCount to avoid System.Management dependency in Shared
        return Environment.MachineName + Environment.ProcessorCount;
    }

    private string GetMacOSHardwareId()
    {
        // Ideally use 'system_profiler SPHardwareDataType'
        return Environment.MachineName; 
    }

    private string GetLinuxHardwareId()
    {
        // Try reading machine-id
        try
        {
            if (File.Exists("/etc/machine-id"))
                return File.ReadAllText("/etc/machine-id").Trim();
            if (File.Exists("/var/lib/dbus/machine-id"))
                return File.ReadAllText("/var/lib/dbus/machine-id").Trim();
        }
        catch {}
        return Environment.MachineName;
    }

    private string ComputeSHA256(string rawData)
    {
        using var sha256 = SHA256.Create();
        var bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(rawData));
        return BitConverter.ToString(bytes).Replace("-", "").ToLower();
    }
}
