using System.Data;
using Valg.EVA.Skanning.Contracts.CommonEnums;
using Valg.EVA.Skanning.Diagnostics;
using Valg.EVA.Skanning.Entity.SqlConnection;
using Valg.EVA.Skanning.Entity.WriteModel;
using Valg.EVA.Skanning.Repositories.Counting;
using Valg.EVA.Skanning.ServicesModel.Internal;

namespace Valg.EVA.Skanning.Commands.DeleteBoxCountingAndRegisterForScanAgain
{
    public class DeleteBoxCountingAndReregisterForScanningCommandHandler : IHandleCommandsWithReturnValue<DeleteBoxCountingAndReregisterForScanningCommand, DeleteBoxCountingAndReregisterForScanningCommandResult>
    {
        private readonly ICountingRepository countingRepository;
        private readonly ICountingWriteableRepository countingWriteableRepository;
        private readonly TransactionScopeFactory transactionScopeFactory;
        private readonly CountingUniqueIdCreator countingUniqueIdCreator;

        public DeleteBoxCountingAndReregisterForScanningCommandHandler(ICountingRepository countingRepository,
            ICountingWriteableRepository countingWriteableRepository,
            TransactionScopeFactory transactionScopeFactory,
            CountingUniqueIdCreator countingUniqueIdCreator)
        {
            this.countingRepository = countingRepository;
            this.countingWriteableRepository = countingWriteableRepository;
            this.transactionScopeFactory = transactionScopeFactory;
            this.countingUniqueIdCreator = countingUniqueIdCreator;
        }

        public void HandleCommand(DeleteBoxCountingAndReregisterForScanningCommand command)
        {
            CommandResult = new DeleteBoxCountingAndReregisterForScanningCommandResult();

            using (var scope = transactionScopeFactory.GetTransactionScope())
            {
                var counting = countingRepository.GetActiveCounting(
                    countingUniqueIdCreator.Create(command.BarcodeLong, command.BarcodeShort),
                    command.CountingEmlAreaContextId,
                    command.CountingId);

                if (counting != null && counting.Id == command.CountingId)
                {
                    try
                    {
                        countingWriteableRepository.MarkBoxCountingAsDeleted(
                            command.CountingId,
                            command.BarcodeLong,
                            command.BarcodeShort,
                            command.BoxCountingConcurrencyToken);

                        InsertNewBoxCounting(command);

                        scope.Complete();
                    }
                    catch (DBConcurrencyException ex)
                    {
                        EvaSkanningEventSource.Log.ConcurrencyError(GetType().ToString(), ex.ToString());
                        CommandResult.DeleteAndReregisterFailed = true;
                    }
                }
                else
                {
                    CommandResult.CountingIsNotActive = true;
                    CommandResult.DeleteAndReregisterFailed = true;
                }
            }
        }

        private void InsertNewBoxCounting(DeleteBoxCountingAndReregisterForScanningCommand command)
        {
            var boxCountingInsert = new BoxCountingInsert
            {
                State = command.ScanAgainImmediatly ? BoxCountingState.Scanning : BoxCountingState.ReadyForScan,
                BarcodeLong = command.BarcodeLong,
                BarcodeShort = command.BarcodeShort,
                CountingId = command.CountingId
            };

            countingWriteableRepository.InsertBoxCounting(boxCountingInsert);
        }

        public DeleteBoxCountingAndReregisterForScanningCommandResult CommandResult { get; private set; }
    }
}
