using System.Linq;
using Valg.EVA.Skanning.Contracts.CommonEnums;
using Valg.EVA.Skanning.Entity.ReadModel;
using Valg.EVA.Skanning.Repositories.BallotPaper;

namespace Valg.EVA.Skanning.Commands.SaveBallotPaperVerifications
{
    public class RejectionAndResetFieldsHelper
    {
        public static void SetRejectionAndResetFieldsAccordingly(SaveBallotPaperVerificationsCommand command, CopiedUnlessSpecifiedValues optional, IBallotPaperRepository ballotPaperRepository)
        {
            var originalBallotPaperValues = ballotPaperRepository.GetOriginalBallotPaperValues(command.BallotPaperId);

            if (command.IsRejectedForAnyReason)
            {
                RejectionReasonType? rejectionReason = command.RejectionReasonVerification.NewValue;
                optional.RejectionReasonTypeIsSpecified = true;
                optional.RejectionReasonType = rejectionReason;

                ResetIgnoreCandidates(optional, originalBallotPaperValues);
            }
            else
            {
                if (command.IsExplicitlyNotRejected)
                {
                    SetRejectionReasonToNull(optional);
                }
                else
                {
                    ResetRejectionIfCurrentVerificationsCancelsTheRejection(command, optional, ballotPaperRepository);
                }

                UpdateIgnoreCandidates(command, optional);
            }
        }

        private static void ResetRejectionIfCurrentVerificationsCancelsTheRejection(SaveBallotPaperVerificationsCommand command, CopiedUnlessSpecifiedValues optional,
            IBallotPaperRepository ballotPaperRepository)
        {
            var currentBallotPaperValues = ballotPaperRepository.GetCurrentBallotPaperValues(command.BallotPaperId);
            var previousRejection = currentBallotPaperValues.RejectionReasonType;

            if (previousRejection.HasValue)
            {
                var previousReasonWasStampAndStampIsNowSetValid = previousRejection.Value == RejectionReasonType.NoOfficialStamp && command.StampVerification != null &&
                                                                  command.StampVerification.StampIsValid;
                var previousReasonWasAnyOfBallotNumberRejectionsAndBallotNumberVerificationIsNowSetToValid = RejectionReasonsCollections.BallotNumberRejectionReasons.Contains(previousRejection.Value) && command.BallotNumberVerification != null;

                if (previousReasonWasStampAndStampIsNowSetValid
                    || previousReasonWasAnyOfBallotNumberRejectionsAndBallotNumberVerificationIsNowSetToValid)
                {
                    SetRejectionReasonToNull(optional);
                }
            }
        }

        private static void SetRejectionReasonToNull(CopiedUnlessSpecifiedValues optional)
        {
            optional.RejectionReasonTypeIsSpecified = true;
            optional.RejectionReasonType = null;
        }

        private static void ResetIgnoreCandidates(CopiedUnlessSpecifiedValues optional, BallotPaperValues originalBallotPaperValues)
        {
            optional.IgnoreCandidatesIsSpecified = true;
            optional.IgnoreCandidates = originalBallotPaperValues.IgnoreCandidates;
        }

        private static void UpdateIgnoreCandidates(SaveBallotPaperVerificationsCommand command, CopiedUnlessSpecifiedValues optional)
        {
            if (command.BallotNumberVerification != null)
            {
                optional.IgnoreCandidates = command.BallotNumberVerification.IgnoreCandidates;
                optional.IgnoreCandidatesIsSpecified = true;
            }
        }
    }
}
