using Insight.Agent.Interfaces;
using Insight.Agent.Messages;
using Insight.Infrastructure;
using Insight.Infrastructure.Entities;
using MongoDB.Driver;

namespace Insight.Server.Network.Handlers.Agent
{
    public class OperationSystemHandler : IAgentMessageHandler<AgentSession>
    {
        private readonly IMongoDatabase _database;

        public OperationSystemHandler(IMongoDatabase database)
        {
            _database = database;
        }

        public async ValueTask HandleAsync<TMessage>(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage
        {
            if (message is OperationSystem os)
            {
                await OnOperationSystemAsync(sender, os, cancellationToken);
            }
        }

        private async ValueTask OnOperationSystemAsync(AgentSession session, OperationSystem operatingSystem, CancellationToken cancellationToken)
        {
            var agentEntity = await _database.Agent().Find(Builders<AgentEntity>.Filter.Eq(p => p.Id, session.Id)).FirstOrDefaultAsync(cancellationToken);
            if (agentEntity is null) return;

            var hostEntity = await _database.Host().Find(Builders<HostEntity>.Filter.Eq(p => p.Agent, agentEntity.Id)).FirstOrDefaultAsync(cancellationToken);
            if (hostEntity is null) return;

            var date = DateTime.Now;

            await _database.HostOs().UpdateOneAsync(p => p.Host == hostEntity.Id, Builders<HostOsEntity>.Update
                .SetOnInsert(p => p.Insert, date)
                .SetOnInsert(p => p.Host, hostEntity.Id)
                .Set(p => p.Update, date)
                .Set(p => p.Name, operatingSystem.Name)
                .Set(p => p.Version, operatingSystem.Version)
                .Set(p => p.Architecture, operatingSystem.Architecture.ToString())
                .Set(p => p.SerialNumber, operatingSystem.SerialNumber)
                .Set(p => p.Virtual, operatingSystem.Virtual)
                .Set(p => p.Installed, operatingSystem.InstallDate), new UpdateOptions
                {
                    IsUpsert = true
                }, cancellationToken);
        }
    }
}