using Quadarax.Foundation.Core.Business.Processor.Enums;
using Quadarax.Foundation.Core.Business.Processor.Exceptons;

namespace Quadarax.Foundation.Core.Business.Processor.Task;

public interface ITaskItem : ITaskIdentifier, ITimeTracked
{
	#region *** Properties ***
	/// <summary>
	/// Contains the affinity token which is used to identify owning/locking queue.
	/// </summary>
	IAffinityToken AffinityToken { get; }
	/// <summary>
	/// External reference of the task.
	/// </summary>
	public string Reference { get; }
	/// <summary>
	/// Status of the task.
	/// </summary>
    public ProcessStatusEnum Status { get; }
	/// <summary>
	/// Assembly qualified name of the provider class responsible to process task.
	/// </summary>
	public string ProviderClass { get; }
	/// <summary>
	/// Task priority value (0-maximal, 255-minimal / default 100).
	/// </summary>
	public byte Priority { get; }
	/// <summary>
	/// Time when task can be processed.
	/// </summary>
	public DateTime ProcessingValidFrom { get; }
    /// <summary>
    /// Time when task will be expired.
    /// </summary>
    public DateTime? ProcessingValidTo { get; }
	/// <summary>
	/// Decremental counter of attempts to try process task.
	/// </summary>
	public int AttemptsLeft { get; }
	/// <summary>
	/// Statistical timestamp when task begins to process.
	/// </summary>
	public DateTime StatStarted { get; }
	/// <summary>
	/// Statistical timestamp when task finished.
	/// </summary>
    public DateTime StatFinished { get; }
	/// <summary>
	/// Latest attempt duration
	/// </summary>
    public TimeSpan StatLastAttemptDuration { get; }
    #endregion

	#region *** Operations ***
	/// <summary>
	/// Re-Schedules inactive task to future and sets <see cref="Status"/> to <see cref="ProcessStatusEnum.Pending"/> (affects <see cref="ProcessingValidFrom"/> and <see cref="ProcessingValidTo"/>).
	/// <list type="bullet">
	///	<item><description>Allowed state: <see cref="ProcessStatusEnum.Pending"/>, <see cref="ProcessStatusEnum.Paused"/></description></item>
    ///	<item><description>Set state to: <see cref="ProcessStatusEnum.Pending"/></description></item>
    /// </list>
    /// <exception cref="InvalidTaskStateException">When task state is invalid for operation.</exception>
	/// </summary>
	/// <param name="postponeInterval">Interval to shift to future.</param>
	/// <param name="reason">Reason message to postpone.</param>
    void Postpone(TimeSpan postponeInterval, string reason);
	/// <summary>
	/// Stops running task and sets <see cref="Status"/> to <see cref="ProcessStatusEnum.Paused"/> or
	/// <see cref="ProcessStatusEnum.ProcessedSucc"/> or <see cref="ProcessStatusEnum.ProcessedFail"/> (target status is depends on input arguments)..
    /// <list type="bullet">
    ///	<item><description>Allowed state: <see cref="ProcessStatusEnum.Started"/></description></item>
    ///	<item><description>Set state to: <see cref="ProcessStatusEnum.Paused"/> or <see cref="ProcessStatusEnum.ProcessedSucc"/> or <see cref="ProcessStatusEnum.ProcessedFail"/></description></item>
    /// </list>
    /// <exception cref="InvalidTaskStateException">When task state is invalid for operation.</exception>
    /// </summary>
	/// <param name="reason">Reason message to stop.</param>
	/// <param name="willPause">If true, then <see cref="Status"/> will be set to <see cref="ProcessStatusEnum.Paused"/> otherwise to <see cref="ProcessStatusEnum.ProcessedSucc"/> or <see cref="ProcessStatusEnum.ProcessedFail"/>.</param>
	/// <param name="willFail">If true, then <see cref="Status"/> will be set to <see cref="ProcessStatusEnum.ProcessedFail"/> otherwise to <see cref="ProcessStatusEnum.ProcessedSucc"/>.</param>
    void Stop(string reason, bool willPause = true, bool willFail = false);

    /// <summary>
    /// Resets task to initial state and sets <see cref="Status"/> to <see cref="ProcessStatusEnum.Pending"/>.
    /// Uses current validity to re-calculate <see cref="ProcessingValidFrom"/> and <see cref="ProcessingValidTo"/> to now + <see cref="postponeValid"/>.
    /// </summary>
    /// <param name="reason">Reason to reset task.</param>
    /// <param name="postponeValid">Postpone current validity from now.</param>
    void Reset(string reason, TimeSpan postponeValid);
	#endregion
}
