using Insight.Agent.Interfaces;
using Insight.Agent.Messages;
using System.Management;
using System.Runtime.Versioning;

namespace Insight.Agent.Network.Handlers
{
    [SupportedOSPlatform("windows")]
    public class VideocardHandler : IAgentMessageHandler<AgentSession>
    {
        public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
        {
            if (message is GetInventory)
            {
                var result = new VideocardList();
                result.AddRange(GetVideocards());

                await sender.SendAsync(result, cancellationToken);
            }
        }

        private static List<Videocard> GetVideocards()
        {
            using var searcher = new ManagementObjectSearcher
            {
                Scope = new ManagementScope(@"root\cimv2"),
                Query = new ObjectQuery("select deviceid, name, adapterram, driverdate, driverversion from win32_videocontroller")
            };

            if (searcher.TryGet(out var collection) is false)
            {
                searcher.Query = new ObjectQuery("select * from win32_videocontroller");

                if (searcher.TryGet(out collection) is false) throw new InvalidOperationException("WMI Collection NULL");
            }

            var videocards = new List<Videocard>();

            using (collection)
            {
                foreach (ManagementObject @object in collection.Cast<ManagementObject>())
                {
                    var videocard = new Videocard();

                    var properties = @object.GetPropertyHashes();

                    videocard.DeviceId = @object.GetValue<string>(properties, "deviceid")?.Trim();
                    videocard.Model = @object.GetValue<string>(properties, "name")?.Trim();

                    if (@object.TryGetValue<object>(properties, "driverdate", out var driverdate))
                    {
                        videocard.DriverDate = ManagementDateTimeConverter.ToDateTime(driverdate?.ToString());
                    }

                    videocard.DriverVersion = @object.GetValue<string>(properties, "driverversion")?.Trim();

                    videocards.Add(videocard);
                }
            }

            return videocards;
        }
    }
}