using Exam.Infrastructure.Extensions;
using Exam.Infrastructure.Validation.Validation;
using FluentValidation;
using Hotline.Exams.ExamManages;
using Hotline.Exams.TestPapers;
using Hotline.Repository.SqlSugar.Exam.Core.Constants;
using Hotline.Repository.SqlSugar.Exam.Interfaces.ExamManages;
using Hotline.Repository.SqlSugar.Exam.Validate;
using Hotline.Share.Enums.Exams;
using ExamErrorMessage = Hotline.Exams.Validate.ExamErrorMessage;

namespace Exam.Application
{
    public class ExamManageValidator:BaseValidator<ExamManage>
    {
        private readonly IExamManageRepository _examManageRepository;

        public ExamManageValidator(IExamManageRepository examManageRepository)
        {
            RuleSet(ValidatorTypeConstants.Create, () =>
            {
                BaseValidateRule();

                ValidateRuleWithAdd();
            });

            RuleSet(ValidatorTypeConstants.Modify, () =>
            {
                BaseValidateRule();

                ValidateRuleWithModify();
            });

            RuleSet(ValidatorTypeConstants.Remove, () =>
            {
                ValidateRuleWithRemove();
            });

            this._examManageRepository = examManageRepository;
        }

        protected override void BaseValidateRule()
        {
            base.BaseValidateRule();

            RuleFor(m => m.Name).NotEmpty().WithMessage(x=>string.Format(ExamErrorMessage.IsRequired,x.GetType().GetDescription(nameof(ExamManage.Name))));
            RuleFor(m => m.Code).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.Code))));
            RuleFor(m => m.CutoffScore).NotNull().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.CutoffScore))));
            RuleFor(m => m.ExamType).NotNull().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.ExamType))));
            RuleFor(m => m.Method).NotNull().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.Method))));
            //RuleFor(m => m.TestPaperId).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, typeof(ExamTestPaper).GetDescription()));
            RuleFor(m => m.Count).NotNull().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.Count))));
            RuleFor(m => m.TimeSpan).NotNull().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.TimeSpan))));
            RuleFor(m => m.StartTime).NotNull().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.StartTime))));
            RuleFor(m => m.EndTime).NotNull().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.EndTime))));
            RuleFor(m => m.EndTime).Must((e, v) => e.ExamType == EExamType.Simulate || e.StartTime < v).WithMessage(x => string.Format(ExamErrorMessage.Greater, x.GetType().GetDescription(nameof(ExamManage.EndTime)), x.GetType().GetDescription(nameof(ExamManage.StartTime))));
            RuleFor(m => m.TotalScore).NotNull().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.TotalScore))));
            RuleFor(m => m.CutoffScore).Must((e, v)=> e.TotalScore >= v).WithMessage(x => string.Format(ExamErrorMessage.Greater, x.GetType().GetDescription(nameof(ExamManage.CutoffScore)), x.GetType().GetDescription(nameof(ExamManage.TotalScore))));
        }

        protected override void ValidateRuleWithAdd()
        {
            base.ValidateRuleWithAdd();
            RuleFor(m => m.CreationTime).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.CreationTime))));

            RuleFor(m => m.Name).Must(v => !_examManageRepository.Queryable().Any(x => x.Name == v)).WithMessage(x => string.Format(ExamErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(ExamManage.Name))));
            RuleFor(m => m.Code).Must(v => !_examManageRepository.Queryable().Any(x => x.Code == v)).WithMessage(x => string.Format(ExamErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(ExamManage.Code))));
        }

        protected override void ValidateRuleWithModify()
        {
            base.ValidateRuleWithModify();
            RuleFor(m => m.LastModificationTime).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.LastModificationTime))));

            RuleFor(m => m.Name).Must((e,v) => !_examManageRepository.Queryable().Any(x => x.Name == v && x.Id!=e.Id)).WithMessage(x => string.Format(ExamErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(ExamManage.Name))));
            RuleFor(m => m.Code).Must((e,v) => !_examManageRepository.Queryable().Any(x => x.Code == v && x.Id != e.Id)).WithMessage(x => string.Format(ExamErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(ExamManage.Code))));

        }

        private void ValidateRuleWithRemove()
        {
            RuleFor(x => x.Id).Must(v => !_examManageRepository.Queryable().Where(x => x.Id == v && x.ExamStatus != EExamStatus.NoStart).Any()).WithMessage(Hotline.Repository.SqlSugar.Exam.Core.Constants.ExamErrorMessage.DeleteUnableExam);
        }

    }
}
