using Quadarax.Foundation.Core.Business.Processor.Enums;
using Quadarax.Foundation.Core.Business.Processor.Queue;
using Quadarax.Foundation.Core.Logging;
using Quadarax.Foundation.Core.Object;
using Quadarax.Foundation.Core.Value.Extensions;

namespace Quadarax.Foundation.Core.Business.Processor.Task
{
    internal class TaskItem : ITaskItem
    {
        #region *** Properties ***

        /// <summary>
        /// <inheritdoc cref="ITaskItem.Id"/>
        /// </summary>
        public long Id { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.QueueType"/>
        /// </summary>
        public ProcessQueueTypeEnum QueueType { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.Created"/>
        /// </summary>
        public DateTime Created { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.Changed"/>
        /// </summary>
        public DateTime? Changed { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.AffinityToken"/>
        /// </summary>
        public IAffinityToken AffinityToken { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.Reference"/>
        /// </summary>
        public string Reference { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.Status"/>
        /// </summary>
        public ProcessStatusEnum Status { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.ProviderClass"/>
        /// </summary>
        public string ProviderClass { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.Priority"/>
        /// </summary>
        public byte Priority { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.ProcessingValidFrom"/>
        /// </summary>
        public DateTime ProcessingValidFrom { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.ProcessingValidTo"/>
        /// </summary>
        public DateTime? ProcessingValidTo { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.AttemptsLeft"/>
        /// </summary>
        public int AttemptsLeft { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.AttemptTimeout"/>
        /// </summary>
        public TimeSpan? AttemptTimeout { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.StatStarted"/>
        /// </summary>
        public DateTime StatStarted { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.StatFinished"/>
        /// </summary>
        public DateTime StatFinished { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.StatLastAttemptDuration"/>
        /// </summary>
        public TimeSpan StatLastAttemptDuration { get; }
        /// <summary>
        /// <inheritdoc cref="ITaskItem.StatusLog"/>
        /// </summary>
        public ITaskStatusLogItem[] StatusLog => _statusLog.ToArray();

        public TypedArgument[] Arguments => _arguments.ToArray(); 
        #endregion

        #region *** Private Fields ***
        private readonly List<ITaskStatusLogItem> _statusLog = new();
        private readonly List<TypedArgument> _arguments = new();
        private ILog _log;
        private ProcessQueue _parent; 
        #endregion

        #region *** Constructors ***
        private TaskItem(ProcessQueue parent, long id, ProcessStatusEnum initialStatus, string reference, string source, TypedArgument[] initialArguments, byte priority, int attepts, TimeSpan? attemptTimeout, DateTime validFrom, DateTime? validTo, ITaskStatusLogItem[]? initialStatusLog):
            this(parent, reference, source, initialArguments, priority, attepts, attemptTimeout, validFrom, validTo, initialStatusLog)
        {
            Id = id;
            Status = initialStatus;
        }
        public TaskItem(ProcessQueue parent, string reference, string providerClass, TypedArgument[] initialArguments, byte priority, int attepts, TimeSpan? attemptTimeout, DateTime validFrom, DateTime? validTo, ITaskStatusLogItem[]? initialStatusLog)
        {	   
            _parent = parent ?? throw new ArgumentNullException(nameof(parent)); 
            _log = new ConsoleLogger().GetLogger(GetType());      
            Priority = priority;
            Reference = reference;
            ProviderClass = providerClass;
            Arguments.Setup(initialArguments);
            AttemptTimeout = attemptTimeout;
            AttemptsLeft = attepts;
            ProcessingValidFrom = validFrom;
            ProcessingValidTo = validTo;
            Created = DateTime.Now;
            if (initialStatusLog != null)
                _statusLog.Setup(initialStatusLog);
            Status = ProcessStatusEnum.Pending; 
            Id = long.MinValue;
        }
        #endregion

        
        #region *** Public Operations ***
        public void Postpone(TimeSpan postponeInterval, string reason)
        {
            throw new NotImplementedException();
        }

        public void Stop(string reason, bool willPause = true, bool willFail = false)
        {
            throw new NotImplementedException();
        }

        public void Reset(string reason, TimeSpan postponeValid)
        {
            throw new NotImplementedException();
        }

        public void Delete(string reason, bool immediate = false)
        {
            throw new NotImplementedException();
        }
        #endregion
    }
}
