using Stateless;

namespace Knoks.Sandbox
{
    public enum Status : short
    {
        PendingLoanRequestConfirmation = 1,
        PendingTranferMethod = 2,
        PendingUserVerification = 3,
        PendingOperatorVerification = 4,
        PendingPreDisclosure = 5,
        PendingBorowerPreDisclosure = 6,
        PendingAppraisal = 7,
        PendingUnderwriting = 8,
        PendingBucketFilling = 9,
        PendingAgreementCreation = 10,
        PendingAgreementSignup = 11,
        PendingMoneyTransfer = 12,
        ExecuteLoan = 13,
        RejectByOperator = 77,
        Expired = 88,
        CanceledByUser = 99,
    }

    public enum Action : short
    {
        UserFillLoanRequest = 1,
        UserConfirmLoanRequest = 2,
        UserAddPaymentMethod = 3,
        UserUploadDocument = 4,
        UserSubmitVerification = 5,
        UserProvidesAllAdditionalData = 6,
        UserSignOnTheAgeement = 7,
        UserCancelingLoanRequest = 8,

        OperatorVerify = 120,
        OperatorRejectDocument = 130,
        OperatorCanAskUser = 140,
        ExternalForMopreInfo = 150,
        OperatorAppraiseTheLoanRequest = 160,
        OperatorUndwritesTheLoanRequest = 170,
        BucketIsFillingByLender = 180,
        BucketIsFillingByOperator = 190,
        OperatorCreateAnAgreement = 200,
        OperatorTransferingTheMoney = 210,
        OperatorRejectLoanRequest = 220,
        LoanRequestExpiringBySystem = 300
    }

    public static class LoanRequestStateMachine
    {
        public static void Test()
        {
            var lr = new StateMachine<Status, Action>(Status.PendingLoanRequestConfirmation);

            lr.Configure(Status.PendingLoanRequestConfirmation)
                .Permit(Action.UserCancelingLoanRequest, Status.CanceledByUser)
                .Permit(Action.UserConfirmLoanRequest, Status.PendingTranferMethod);

            lr.Configure(Status.PendingTranferMethod)
                .Permit(Action.UserCancelingLoanRequest, Status.CanceledByUser)
                .Permit(Action.UserAddPaymentMethod, Status.PendingUserVerification);


            lr.Configure(Status.PendingUserVerification)
                .Permit(Action.UserCancelingLoanRequest, Status.CanceledByUser)
                .PermitReentry(Action.UserUploadDocument)
                .Permit(Action.UserSubmitVerification, Status.PendingOperatorVerification);

            lr.Configure(Status.PendingOperatorVerification)
                .Permit(Action.UserCancelingLoanRequest, Status.CanceledByUser)
                .Permit(Action.OperatorRejectLoanRequest, Status.RejectByOperator)
                .Permit(Action.OperatorRejectDocument, Status.PendingUserVerification)
                .Permit(Action.OperatorVerify, Status.PendingPreDisclosure);

            lr.Configure(Status.PendingPreDisclosure)
                .Permit(Action.UserCancelingLoanRequest, Status.CanceledByUser)
                .Permit(Action.OperatorRejectLoanRequest, Status.RejectByOperator)
                .Permit(Action.OperatorCanAskUser, Status.PendingBorowerPreDisclosure)
                .Permit(Action.ExternalForMopreInfo, Status.PendingAppraisal);

            lr.Configure(Status.PendingBorowerPreDisclosure)
                .Permit(Action.UserCancelingLoanRequest, Status.CanceledByUser)
                .Permit(Action.UserProvidesAllAdditionalData, Status.PendingUnderwriting);

            lr.Configure(Status.PendingAppraisal)
                .Permit(Action.UserCancelingLoanRequest, Status.CanceledByUser)
                .Permit(Action.OperatorRejectLoanRequest, Status.RejectByOperator)
                .Permit(Action.OperatorAppraiseTheLoanRequest, Status.PendingUnderwriting);

            lr.Configure(Status.PendingUnderwriting)
                .Permit(Action.UserCancelingLoanRequest, Status.CanceledByUser)
                .Permit(Action.OperatorRejectLoanRequest, Status.RejectByOperator)
                .Permit(Action.OperatorUndwritesTheLoanRequest, Status.PendingBucketFilling);

            lr.Configure(Status.PendingBucketFilling)
                .Permit(Action.UserCancelingLoanRequest, Status.CanceledByUser)
                .Permit(Action.OperatorRejectLoanRequest, Status.RejectByOperator)
                .Permit(Action.LoanRequestExpiringBySystem, Status.Expired)
                .Permit(Action.BucketIsFillingByLender, Status.PendingAgreementCreation)
                .Permit(Action.BucketIsFillingByOperator, Status.PendingAgreementCreation);

            lr.Configure(Status.PendingAgreementCreation)
                .Permit(Action.UserCancelingLoanRequest, Status.CanceledByUser)
                .Permit(Action.OperatorRejectLoanRequest, Status.RejectByOperator)
                .Permit(Action.OperatorCreateAnAgreement, Status.PendingAgreementSignup);

            lr.Configure(Status.PendingAgreementSignup)
                .Permit(Action.UserCancelingLoanRequest, Status.CanceledByUser)
                .Permit(Action.OperatorRejectLoanRequest, Status.RejectByOperator)
                .Permit(Action.OperatorCreateAnAgreement, Status.PendingMoneyTransfer);

            lr.Configure(Status.PendingMoneyTransfer)
                .Permit(Action.OperatorRejectLoanRequest, Status.RejectByOperator)
                .Permit(Action.OperatorTransferingTheMoney, Status.ExecuteLoan);
        }
    }
}
