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

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

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

        private static List<Printer> GetPrinters()
        {
            using var searcher = new ManagementObjectSearcher
            {
                Scope = new ManagementScope(@"root\cimv2"),
                Query = new ObjectQuery("select drivername, name, portname, location, comment from win32_printer")
            };

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

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

            var printers = new List<Printer>();

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

                    var properties = @object.GetPropertyHashes();

                    printer.Driver = @object.GetValue<string>(properties, "drivername")?.Trim();
                    printer.Name = @object.GetValue<string>(properties, "name")?.Trim();
                    printer.Port = @object.GetValue<string>(properties, "portname")?.Trim();
                    printer.Location = @object.GetValue<string>(properties, "location")?.Trim();
                    printer.Comment = @object.GetValue<string>(properties, "comment")?.Trim();

                    printers.Add(printer);
                }
            }

            return printers;
        }
    }
}