using System;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Dacryptero.Notifications;

namespace Dacryptero.Web.Events.Receive
{
    public class EditInterviewSend : ReceiveBase
    {
        public string Id { get; private set; } = "";

        public bool Delete { get; private set; }

        public DateTime? Time { get; private set; }

        public string? Location { get; private set; }

        public string? Interviewer { get; private set; }

        public override async Task Execute(ExecuteArgs args)
        {
            var id = Id.ToObjectId();
            if (id is null)
            {
                await args.Connection.Send(new Send.EditDenied(Id, null,
                    Send.EditTarget.Interview, Send.EditDeniedReason.IdNotFound,
                    "invalid id"
                )).ConfigureAwait(false);
                return;
            }
            var result = await args.Data.GetInterviewAsync(id, CancellationToken.None)
                .ConfigureAwait(false);
            if (result is null)
            {
                await args.Connection.Send(new Send.EditDenied(Id, null,
                    Send.EditTarget.Interview, Send.EditDeniedReason.IdNotFound,
                    "id does not exists"
                )).ConfigureAwait(false);
                return;
            }
            var interview = result.Value.Value;
            if (Time is not null)
            {
                interview.Time = Time.Value;
                await args.Connection.Send(new Send.EditAccept(Id, "time", Send.EditTarget.Interview))
                    .ConfigureAwait(false);
            }
            if (Location is not null)
            {
                result.Value.Source.ReplaceIndex(Data.IndexSource.Interviews, id, interview.Location, Location, true, args);
                interview.Location = Location;
                await args.Connection.Send(new Send.EditAccept(Id, "location", Send.EditTarget.Interview))
                    .ConfigureAwait(false);
            }
            if (Interviewer is not null)
            {
                result.Value.Source.ReplaceIndex(Data.IndexSource.Interviews, id, interview.Interviewer, Interviewer, true, args);
                interview.Interviewer = Interviewer;
                await args.Connection.Send(new Send.EditAccept(Id, "interviewer", Send.EditTarget.Interview))
                    .ConfigureAwait(false);
            }
            interview.Deleted = Delete;
            await result.Value.Source.UpdateInterviewAsync(result.Value.Value, CancellationToken.None)
                .ConfigureAwait(false);
            if (Delete)
            {
                interview.PerformIndex(result.Value.Source, true, args);

                args.SendGlobalNotification(new Notification
                {
                    Image = "/img/svgrepo/essential-set-2/garbage-51844.svg",
                    Title = "Interview deleted",
                    Description = $"{interview.Location} with {interview.Interviewer} deleted",
                    Close = System.DateTime.UtcNow.AddSeconds(15),
                });
            }
            await args.Connection.Send(new Send.EditAccept(Id, null, Send.EditTarget.Attribute))
                .ConfigureAwait(false);
        }

        public override void ReadJsonContent(JsonElement json)
        {
            Id = json.GetProperty("id").GetString() ?? "";
            Delete = json.TryGetProperty("delete", out JsonElement node) ?
                node.GetBoolean() : false;
            Time = json.TryGetProperty("time", out node) && node.ValueKind == JsonValueKind.String ?
                node.GetDateTime() : null;
            Location = json.TryGetProperty("location", out node) ?
                node.GetString() : null;
            Interviewer = json.TryGetProperty("interviewer", out node) ?
                node.GetString() : null;
        }
    }
}