using System.Net;
using InABox.API;
using InABox.Core;
using InABox.Database;
using Microsoft.Exchange.WebServices.Data;

namespace InABox.Rpc
{
    public class RpcSaveHandler : RpcCommandHandler<IRpcServer, RpcSaveCommand, RpcSaveParameters, RpcSaveResult>
    {
        public RpcSaveHandler(IRpcServer sender) : base(sender)
        {
        }

        protected override RpcSaveResult Execute(IRpcSession session, RpcSaveParameters parameters, Logger logger)
        {
            var user = CredentialsCache.ValidateAndRefresh(session.ID)
                ?? throw new RpcException("User not found in Credentials Cache!", RpcError.UNAUTHENTICATED);

            var response = new RpcSaveResult() { Type = parameters.Type };
            var entities = parameters.Items;

            var originals = new Dictionary<string, object>[entities.Length];

            for(int i = 0; i < entities.Length; ++i)
            {
                originals[i] = BaseObjectExtensions.GetOriginaValues(entities[i]);
            }

            var store = DbFactory.FindStore(parameters.Type, user.ID, user.UserID, session.Platform, session.Version ?? "", logger);

            store.Save(entities, parameters.AuditNote);
            
            InABox.API.CredentialsCache.Refresh(parameters.Type == typeof(InABox.Core.User));
            
            var deltas = new Dictionary<string, object?>[entities.Length];
            for (int i = 0; i < entities.Length; ++i)
            {
                var preSaveChanges = originals[i];
                var item = entities[i];
                var currentChanges = item.GetOriginaValues();

                var delta = new Dictionary<string, object?>();

                foreach (var (key, value) in currentChanges)
                {
                    if (preSaveChanges.TryGetValue(key, out var oldValue))
                    {
                        if (!Equals(value, oldValue))
                            delta[key] = CoreUtils.GetPropertyValue(item, key);
                    }
                    else
                        delta[key] = CoreUtils.GetPropertyValue(item, key);
                }

                deltas[i] = delta;
            }

            response.Deltas = deltas;

            return response;
        }

    }
}