public async Task DeleteTimelineTask(ClickUpTask clickUpTask)
        {
            var timelineTaskToDelete = Converters.ConvertToTimelineTask(clickUpTask);

            var existingTimelineTask = _dbContext.TimelineTasks.SingleOrDefault(t => t.ClickUpTaskId.Equals(timelineTaskToDelete.ClickUpTaskId));

            if (existingTimelineTask != null)
            {
                _dbContext.TimelineTasks.Remove(existingTimelineTask);
                await _dbContext.SaveChangesAsync();
            }
        }
        /// <summary>
        /// TODO: this needs changing for the beta!! it needs to gracefully handle errors / missing data, with logging
        /// TODO: also it should probably live somewhere else too
        /// </summary>
        /// <param name="clickUpTask"></param>
        /// <returns></returns>
        public static TimelineTask ConvertToTimelineTask(ClickUpTask clickUpTask)
        {
            var acid = GetACIDFromClickUpTask(clickUpTask);

            var stepId          = 0;
            var stepDescription = "Not found";
            var stepField       = clickUpTask.CustomFields.FirstOrDefault(field => field.FieldId.Equals(Constants.ClickUp.Fields.StepId, StringComparison.InvariantCultureIgnoreCase));

            if (stepField != null && stepField.Value.ValueKind != System.Text.Json.JsonValueKind.Undefined)
            {
                var index = stepField.Value.ToObject <int>();
                stepId = int.Parse(stepField.ClickUpTypeConfig.Options[index].Name);

                stepDescription = clickUpTask.CustomFields.FirstOrDefault(field => field.FieldId.Equals(Constants.ClickUp.Fields.StepDescription, StringComparison.InvariantCultureIgnoreCase)).ClickUpTypeConfig.Options[index].Name;
            }

            var stageId          = 0;
            var stageDescription = "Not found";
            var stageField       = clickUpTask.CustomFields.FirstOrDefault(field => field.FieldId.Equals(Constants.ClickUp.Fields.StageId, StringComparison.InvariantCultureIgnoreCase));

            if (stageField != null && stageField.Value.ValueKind != System.Text.Json.JsonValueKind.Undefined)
            {
                var index = stageField.Value.ToObject <int>();
                stageId = int.Parse(stageField.ClickUpTypeConfig.Options[index].Name);

                stageDescription = clickUpTask.CustomFields.FirstOrDefault(field => field.FieldId.Equals(Constants.ClickUp.Fields.StageDescription, StringComparison.InvariantCultureIgnoreCase)).ClickUpTypeConfig.Options[index].Name;
            }

            DateTime?actualDate = null;
            var      actualDateStringJsonElement = clickUpTask.CustomFields.FirstOrDefault(field => field.FieldId.Equals(Constants.ClickUp.Fields.ActualDate, StringComparison.InvariantCultureIgnoreCase))?.Value;

            if (actualDateStringJsonElement.HasValue)
            {
                var actualDateString = actualDateStringJsonElement.Value.ToStringObject();
                if (!string.IsNullOrEmpty(actualDateString))
                {
                    actualDate = (double.Parse(actualDateString)).ToDateTime();
                }
            }

            var dueDate = string.IsNullOrEmpty(clickUpTask.DueDateSecondsSinceUnixEpochAsString) ? null : double.Parse(clickUpTask.DueDateSecondsSinceUnixEpochAsString).ToDateTime();

            return(new TimelineTask(acid, stepId, stepDescription, stageId, stageDescription, clickUpTask.Space.Id, clickUpTask.Folder.Id, clickUpTask.ListId.Id, clickUpTask.ClickUpTaskId, dueDate, actualDate));
        }
        public async Task <int> SaveOrUpdateTimelineTask(ClickUpTask clickUpTask)
        {
            var timelineTaskToSaveOrUpdate = Converters.ConvertToTimelineTask(clickUpTask);

            var existingTimelineTask = _dbContext.TimelineTasks.SingleOrDefault(t => t.ClickUpTaskId.Equals(timelineTaskToSaveOrUpdate.ClickUpTaskId));

            if (existingTimelineTask != null)                                               //it's an update
            {
                if (!TimelineTasksDiffer(existingTimelineTask, timelineTaskToSaveOrUpdate)) //task matches the task in the database, so don't bother updating it.
                {
                    return(0);
                }

                existingTimelineTask.ACID = timelineTaskToSaveOrUpdate.ACID;

                existingTimelineTask.StepId           = timelineTaskToSaveOrUpdate.StepId;
                existingTimelineTask.StepDescription  = timelineTaskToSaveOrUpdate.StepDescription;
                existingTimelineTask.StageId          = timelineTaskToSaveOrUpdate.StageId;
                existingTimelineTask.StageDescription = timelineTaskToSaveOrUpdate.StageDescription;

                existingTimelineTask.ClickUpSpaceId  = timelineTaskToSaveOrUpdate.ClickUpSpaceId;
                existingTimelineTask.ClickUpFolderId = timelineTaskToSaveOrUpdate.ClickUpFolderId;
                existingTimelineTask.ClickUpTaskId   = timelineTaskToSaveOrUpdate.ClickUpTaskId;

                existingTimelineTask.ActualDate = timelineTaskToSaveOrUpdate.ActualDate;
                existingTimelineTask.DueDate    = timelineTaskToSaveOrUpdate.DueDate;

                _dbContext.TimelineTasks.Update(existingTimelineTask);
            }
            else             //save new task
            {
                _dbContext.Add(timelineTaskToSaveOrUpdate);
            }

            return(await _dbContext.SaveChangesAsync());
        }
 public static int GetACIDFromClickUpTask(ClickUpTask clickUpTask)
 {
     return(int.Parse(clickUpTask.CustomFields.First(field => field.FieldId.Equals(Constants.ClickUp.Fields.ACID, StringComparison.InvariantCultureIgnoreCase)).Value.ToObject <string>()));           //TODO: ACID is a string in clickup. needs to be a number.
 }