using qdr.fnd.core.pqueue.Enums;
using qdr.fnd.core.pqueue.Exceptions;
using Quadarax.Foundation.Core.Data;
using Quadarax.Foundation.Core.Logging;
using Quadarax.Foundation.Core.Object;
using Quadarax.Foundation.Core.Value.Generators;

namespace qdr.fnd.core.pqueue.Storages
{
    public abstract class BaseStorageProvider : DisposableObject, IPsQueueStorage
    {
        
        #region *** Properties ***
        protected ILog? Log => _log;
        #endregion

        #region *** Private Fields ***

        private ILog? _log;
        private IIdGenerator<string> _tranGenerator;

        #endregion

        #region *** Constructors ***
        protected BaseStorageProvider(ILogger? logger)
        {
            _log = logger?.GetLogger(GetType().Name);
            _tranGenerator = new TinyHash(10);
        }

        #endregion


        #region Implementation of IPsQueueStorage

        /// <inheritdoc />
        public string CreateItem(string owner, string ownerRef, string providerClass, int initialAttempts, DateTime? created)
        {
            if (string.IsNullOrWhiteSpace(owner))
                throw new ArgumentNullException(nameof(owner));
            if (string.IsNullOrWhiteSpace(ownerRef))
                throw new ArgumentNullException(nameof(ownerRef));
            if (string.IsNullOrWhiteSpace(providerClass))
                throw new ArgumentNullException(nameof(providerClass));
            if (created == null)
                created = DateTime.Now;

            var id = _tranGenerator.NewId();

            var newId = OnCreateItem(id, owner, ownerRef, providerClass, initialAttempts, created.Value, id);

            _log?.Log(LogSeverityEnum.Trace, $"Item [id={id}, owner={owner}, ownerRef{ownerRef}] created");
            return newId;
        }

        protected abstract string OnCreateItem(string id, string owner, string ownerRef, string providerClass, int initialAttempts, DateTime created, string s);

        /// <inheritdoc />
        public void DeleteItem(string itemId)
        {
            if (string.IsNullOrWhiteSpace(itemId))
                throw new ArgumentNullException(nameof(itemId));
            if (!ContainsItem(itemId))
                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);

            OnDeleteItem(itemId);
        }

        protected abstract void OnDeleteItem(string itemId);

        /// <inheritdoc />
        public void UpdateItemPriority(string itemId, int priority)
        {
            throw new NotImplementedException();
        }

        /// <inheritdoc />
        public void UpdateItemValidity(string itemId, DateTime validForm, DateTime? validTo)
        {
            throw new NotImplementedException();
        }

        /// <inheritdoc />
        public void UpdateItemStatus(string itemId, PsStatusEnum? status, bool isTransient)
        {
            throw new NotImplementedException();
        }

        /// <inheritdoc />
        public void UpdateItemAttempts(string itemId, int attemptsLeft)
        {
            throw new NotImplementedException();
        }

        /// <inheritdoc />
        public void UpdateItemStarted(string itemId, DateTime? started)
        {
            throw new NotImplementedException();
        }

        /// <inheritdoc />
        public void UpdateItemFinished(string itemId, DateTime? finished)
        {
            throw new NotImplementedException();
        }

        /// <inheritdoc />
        public void CreateItemAttribute(string itemId, string name, string? value, string valueTypeClass, bool isOutput)
        {
            throw new NotImplementedException();
        }

        /// <inheritdoc />
        public void UpdateItemAttribute(string itemId, string name, string value)
        {
            throw new NotImplementedException();
        }

        /// <inheritdoc />
        public void DeleteItemAttribute(string itemId, string name)
        {
            throw new NotImplementedException();
        }

        /// <inheritdoc />
        public void AppendLog(string transactionId, string itemId, string message, int code, ErrorLevelEnum messageType)
        {
            throw new NotImplementedException();
        }

        /// <inheritdoc />
        public void AppendStatusJournal(string itemId, PsStatusEnum status, bool isTransient, string message)
        {
            throw new NotImplementedException();
        }

        /// <inheritdoc />
        public IQueryable<IPsQueueItem> Query(string? owner, string? ownerRef, params Tuple<bool, PsStatusEnum>[] status)
        {
            throw new NotImplementedException();
        }

        /// <inheritdoc />
        public IPsQueueItem GetItem(string itemId)
        {
            throw new NotImplementedException();
        }

        /// <inheritdoc />
        public abstract bool ContainsItem(string itemId);

        #endregion
    }
}
