using AgileObjects.AgileMapper.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using MongoDB.Driver.Linq;
using System.Net;
using System.Text.RegularExpressions;
using static Tiobon.Core.Model.Consts;

namespace Tiobon.Core.Services;

/// <summary>
/// 考试记录 (服务)
/// </summary>
public class Ghre_ExamRecordServices : BaseServices<Ghre_ExamRecord, Ghre_ExamRecordDto, InsertGhre_ExamRecordInput, EditGhre_ExamRecordInput>, IGhre_ExamRecordServices
{
    private readonly IBaseRepository<Ghre_ExamRecord> _dal;
    //private readonly IGhre_ExamPaperServices _ghre_ExamPaperServices;
    private readonly ILogger<Ghre_ExamRecordServices> _logger;
    public Ghre_ExamRecordServices(ICaching caching,
        //IGhre_ExamPaperServices ghre_ExamPaperServices,
        IBaseRepository<Ghre_ExamRecord> dal, ILogger<Ghre_ExamRecordServices> logger)
    {
        this._dal = dal;
        base.BaseDal = dal;
        base._caching = caching;
        //_ghre_ExamPaperServices = ghre_ExamPaperServices;
        _logger = logger;
    }

    public override async Task<ServicePageResult<Ghre_ExamRecordDto>> QueryFilterPage(QueryBody filter, string condition, bool? IsEnable = true)
    {
        if (string.IsNullOrWhiteSpace(filter.orderBy))
            filter.orderBy = "CreateTime1 DESC";

        if (filter.pageSize == 0)
            filter.pageSize = 10000;

        var countSql = @$" SELECT COUNT(1) FROM Ghre_ExamRecord_V A";
        var sql = @$" SELECT *
                    FROM Ghre_ExamRecord_V A";

        string conditions = " WHERE  IsEnable = 1";
        conditions += $" AND dbo.FUserDataBelongPriv ({App.User.ID}, A.DataBelongID, NULL) = 1";

        if (!string.IsNullOrEmpty(condition)) conditions += " AND " + condition;
        if (filter.jsonParam != null)
            foreach (JProperty jProperty in filter.jsonParam.Properties())
            {
                var name = jProperty.Name;
                var value = jProperty.Value.ToString();
                if (name == "page" || name == "pageSize")
                    continue;

                if (name == "DueDate")
                {
                    var jsonParam = JsonConvert.DeserializeObject<JsonParam>(value);
                    conditions += $" AND FORMAT(DueDate, 'yyyy-MM-dd') = '{jsonParam.columnValue}'";
                    continue;

                }
                if (!string.IsNullOrWhiteSpace(value))
                {
                    var jsonParam = JsonConvert.DeserializeObject<JsonParam>(value);

                    switch (jsonParam.operationKey)
                    {
                        case "Include":
                            conditions += $" AND {name} LIKE '%{jsonParam.columnValue}%'";
                            break;
                        case "NotInclude":
                            conditions += $" AND {name} NOT LIKE '%{jsonParam.columnValue}%'";
                            break;
                        case "IsNull":
                            conditions += $" AND {name} IS NULL";
                            break;
                        case "NotNull":
                            conditions += $" AND {name} IS NOT NULL";
                            break;
                        case "Equal":
                            conditions += $" AND {name} ='{jsonParam.columnValue}'";
                            break;
                        case "NotEqual":
                            conditions += $" AND {name} !='{jsonParam.columnValue}'";
                            break;
                        default:
                            break;
                    }
                }
            }

        sql += conditions;
        countSql += conditions;
        int total = await Db.Ado.GetIntAsync(countSql);

        sql = "SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY " + filter.orderBy + ") NUM FROM (SELECT * FROM (" + sql + " ";
        sql += ") A ) B ) C";

        sql += " WHERE NUM <= " + filter.pageNum * filter.pageSize + " AND NUM >" + (filter.pageNum - 1) * filter.pageSize;

        var entitys = await Db.Ado.SqlQueryAsync<Ghre_ExamRecordDto>(sql);

        var attachments = new List<Ghre_Attachment>();
        var ids = entitys.Select(x => x.Id.ToString()).ToList();
        if (ids.Count > 0)
            attachments = await Db.Queryable<Ghre_Attachment>().Where(x => ids.Contains(x.TableName)).ToListAsync();

        attachments.ForEach(x =>
        {
            x.PhysicsPath = "/Advanced" + x.PhysicsPath;
            x.RelativePath = "/Advanced" + x.RelativePath;
            x.ThumbnailPath = "/Advanced" + x.ThumbnailPath;
            x.FileURL = "/Advanced" + x.FileURL;
        });
        entitys.ForEach(async x =>
        {
            x.ScoreMethodLabel = await GetParaLabel("ScoreMethod", x.ScoreMethod);
            x.ScoreStatusLabel = await GetParaLabel("TrainingExamScoreStatus", x.ScoreStatus);
            //x.CourseStatusLabel = await GetParaLabel("TrainingCourseStatus", x.CourseStatus);
            //x.StudyStatusLabel = await GetParaLabel("TrainingStudyStatus", x.StudyStatus);
            if (x.IsPass != null)
                x.IsPassLabel = x.IsPass == true ? "合格" : "不合格";
            if (x.FinallyIsPass != null)
                x.FinallyIsPassLabel = x.FinallyIsPass == true ? "合格" : "不合格";
            x.Attachments = attachments.Where(o => o.TableName == x.Id.ToString()).ToList();
            //x.InStatusLabel = x.InStatus == "1" ? "在职" : null;
            //x.InStatusLabel = x.InStatus == "2" ? "离职" : null;
            //x.InStatusLabel = x.InStatus == "0" ? "未入职" : null;

            if (!x.ExamDate.IsNull())
                x.ExamDate1 = DateTimeHelper.ConvertToDayString(x.ExamDate);
            if (x.BeginTime != null)
                x.ExamDate1 = x.BeginTime.Value.ToString("yyyy-MM-dd");


            x.TotalScore += x.Score ?? 0;
            x.TotalScore += x.AdjustScore ?? 0;
            x.TotalScore += x.ActualScore ?? 0;
            //if (x.DueDate != null)
            //    x.DueDate1 = x.DueDate.Value.ToString("yyyy-MM-dd");
            //if (x.ExamDate != null)
            //    x.ExamDate1 = x.ExamDate.Value.ToString("yyyy-MM-dd");
            x.DataBelongName = await GetDataBelongName(x.DataBelongID);

        });

        return new ServicePageResult<Ghre_ExamRecordDto>(filter.pageNum, total, filter.pageSize, entitys);

    }

    public async Task<ServicePageResult<Ghre_ExamRecordDto>> Query(string examId, QueryBody body)
    {
        return await QueryFilterPage(body, $"ExamId='{examId}'");
    }

    public async Task<ServiceResult> ModifyAdjustScore(string examRecordId, EditGhre_ExamRecordInput edit)
    {
        var entity = await QuerySingle(examRecordId);
        if (entity != null && entity.ExamId != null)
            if (await Db.Queryable<Ghre_Exam>().Where(x => x.Id == entity.ExamId.Value && x.Status == "Disabled").AnyAsync())
                return ServiceResult.OprateFailed($"该考试已归档，不可进行调整分数！");

        var paper = await Db.Queryable<Ghre_ExamPaper>().FirstAsync(x => x.Id == entity.ExamPaperId);
        if (paper == null)
            return ServiceResult.OprateFailed("该考试管理的试卷已被删除，暂不可变更调整分！");

        entity.AdjustScore = edit.AdjustScore ?? 0;
        //entity.Score += entity.AdjustScore;

        string score1 = Regex.Replace(entity.Score.ToString(), @"\.(0+)$", "") + "/" + Regex.Replace(entity.Score.ToString(), @"\.(0+)$", "");
        if (entity.Score < 0)
            return ServiceResult.OprateFailed($"调整后得分为【{score1}】,得分不可小于0！");
        if (entity.Score > paper.TotalScore)
            return ServiceResult.OprateFailed($"调整后得分为【{score1}】,不可大于卷面总分【{Regex.Replace(paper.TotalScore.ToString(), @"\.(0+)$", "") + "/" + Regex.Replace(paper.TotalScore.ToString(), @"\.(0+)$", "")}】！");

        #region 处理最终得分
        var exam = await Db.Queryable<Ghre_Exam>().Where(x => x.Id == entity.ExamId).FirstAsync();
        if (exam != null)
        {
            if (exam.OnlineScorePercentage != null && exam.OfflineScorePercentage != null)
                if (exam.OnlineScorePercentage > 0 && exam.OfflineScorePercentage > 0)
                {
                    decimal OnlineScorePercentage = exam.OnlineScorePercentage.Value / 100;
                    decimal OfflineScorePercentage = exam.OfflineScorePercentage.Value / 100;
                    entity.FinallyScore = (entity.Score + (entity.AdjustScore ?? 0)) * OnlineScorePercentage;
                    if (entity.ActualScore != null && entity.ActualScore > 0)
                        entity.FinallyScore += entity.ActualScore * OfflineScorePercentage;
                }
        }
        #endregion


        var paperId = entity.ExamPaperId;
        var examPaper = await Db.Queryable<Ghre_ExamPaper>().Where(x => x.Id == paperId).FirstAsync();
        if (examPaper != null)
            entity.IsPass = examPaper.PassScore > (entity.Score + entity.AdjustScore) ? false : true;

        await Update(entity, ["IsPass", "AdjustScore", "FinallyScore", "UpdateTime", "UpdateBy"]);

        return ServiceResult.OprateSuccess("修改成功！");

        //return await QueryFilterPage(body, $"ExamId='{examId}'");
    }

    public async Task<ServiceResult> ModifyActualScore(string examRecordId, EditGhre_ExamRecordInput edit)
    {
        var entity = await QuerySingle(examRecordId);
        if (entity != null && entity.ExamId != null)
            if (await Db.Queryable<Ghre_Exam>().Where(x => x.Id == entity.ExamId.Value && x.Status == "Disabled").AnyAsync())
                return ServiceResult.OprateFailed($"该考试已归档，不可进行调整分数！");

        if (edit.AdjustScore < 0)
            return ServiceResult.OprateFailed($"实操分为【{edit.AdjustScore}】,分数不可小于0！");
        entity.ActualScore = edit.AdjustScore;

        //string score1 = Regex.Replace(entity.Score.ToString(), @"\.(0+)$", "") + "/" + Regex.Replace(entity.Score.ToString(), @"\.(0+)$", "");

        #region 处理最终得分
        var exam = await Db.Queryable<Ghre_Exam>().Where(x => x.Id == entity.ExamId).FirstAsync();
        if (exam != null)
        {
            if (exam.OnlineScorePercentage != null && exam.OfflineScorePercentage != null)
                if (exam.OnlineScorePercentage > 0 && exam.OfflineScorePercentage > 0)
                {
                    decimal OnlineScorePercentage = exam.OnlineScorePercentage.Value / 100;
                    decimal OfflineScorePercentage = exam.OfflineScorePercentage.Value / 100;
                    entity.FinallyScore = (entity.Score + (entity.AdjustScore ?? 0)) * OnlineScorePercentage;
                    if (entity.ActualScore != null && entity.ActualScore > 0)
                        entity.FinallyScore += entity.ActualScore * OfflineScorePercentage;
                }
        }
        #endregion

        await Update(entity, ["ActualScore", "FinallyScore", "UpdateTime", "UpdateBy"]);

        return ServiceResult.OprateSuccess("修改成功！");
    }

    public async Task<ServiceResult> ModifyFinallyIsPass(string examRecordId, EditGhre_ExamRecordInput edit)
    {
        var entity = await QuerySingle(examRecordId);
        if (entity != null && entity.ExamId != null)
            if (await Db.Queryable<Ghre_Exam>().Where(x => x.Id == entity.ExamId.Value && x.Status == "Disabled").AnyAsync())
                return ServiceResult.OprateFailed($"该考试已归档，不可进行调整！");

        //if (entity.ActualScore is null && entity.AdjustScore is null)
        //    return ServiceResult.OprateFailed($"请先变更调整分或实操分！");

        entity.FinallyIsPass = edit.FinallyIsPass ?? false;

        //string score1 = Regex.Replace(entity.Score.ToString(), @"\.(0+)$", "") + "/" + Regex.Replace(entity.Score.ToString(), @"\.(0+)$", "");


        await Update(entity, ["FinallyIsPass", "UpdateTime", "UpdateBy"]);

        return ServiceResult.OprateSuccess("修改成功！");
    }

    public async Task<ServiceResult<Ghre_ExamRecordExtend>> ExtendAsync(long examRecordId, long? groupId)
    {
        var extend = new Ghre_ExamRecordExtend();
        var record = await QuerySingle(x => x.Id == examRecordId || x.StudyRecordId == examRecordId);
        examRecordId = record.Id;

        using var _context = ContextFactory.CreateContext();

        var src = _context.Ghre_ExamRecordDetail.Where(x => x.ExamRecordId == record.Id);
        var src1 = _context.Ghre_ExamRecordAnswer
            .OrderBy(x => x.TaxisNo)
            .Where(x => x.ExamRecordDetailId != null && x.ExamRecordId == record.Id);

        if (groupId != null)
            src = src.Where(x => x.GroupId == groupId);
        else
            src = src.Where(x => x.IsEnable == 1);

        var details = await src
            .ToListAsync();
        var detailIds = details.Select(x => x.Id).ToList();

        src1 = src1.Where(x => detailIds.Contains(x.ExamRecordDetailId.Value));

        var recordAnswers = await src1
            .ToListAsync();
        if (record.ScoreStatus == Consts.DIC_EXAM_RECORD_SCORE_STATUS.NO_SCORE)
            await ExamHelper.SystemMarkAsync(Db, record, details, recordAnswers);

        var exampaper = await Db.Queryable<Ghre_ExamPaper>().FirstAsync(x => x.Id == record.ExamPaperId);
        var baseData = new DefaultGhre_ExamPaperBaseData();
        baseData.PaperNo = exampaper.PaperNo;
        baseData.PaperName = exampaper.PaperName;
        baseData.AnswerTime = exampaper.AnswerTime;
        baseData.ScoreMethod = exampaper.ScoreMethod;
        baseData.TotalScore = exampaper.TotalScore;
        baseData.PassScore = exampaper.PassScore;
        baseData.RetakeTimes = exampaper.RetakeTimes;
        baseData.RemarkSz = exampaper.RemarkSz;
        baseData.LinkType = exampaper.LinkType;
        baseData.CourseId = exampaper.LinkType == "CourseId" ? exampaper.LinkId : null;
        baseData.CourseSceneId = exampaper.LinkType == "CourseSceneId" ? exampaper.LinkId : null;
        extend.baseData = baseData;


        extend.styleInfo.coverImage = exampaper.CoverUrl;
        extend.styleInfo.paperStyle = exampaper.Style;
        extend.styleInfo.coverBackGround = exampaper.CoverBackGround;

        var questions = await Db.Queryable<Ghre_ExamPaperQuestion>()
            //.Where(x => x.ExamPaperId == exampaper.Id)
            .Where(x => (x.ExamPaperId == exampaper.Id && exampaper.SetMethod == DIC_EXAM_PAPER_SET_METHOD.MANUAL) || (x.ExamPaperId == examRecordId && exampaper.SetMethod == DIC_EXAM_PAPER_SET_METHOD.RANDOM))

            .ToListAsync();
        var previews = questions.Where(x => x.QuestionId != null).Select(x => new DefaultGhre_ExamPaperPreview()
        {
            Id = x.Id,
            ConfigId = x.ConfigId,
            parentId = x.ConfigId,
            QuestionId = x.QuestionId.Value,
            ExamPaperId = x.ExamPaperId,
            Score = x.Score,
            RealScore = details.Where(m => m.QuestionId == x.QuestionId).Sum(m => (m.Score ?? 0) + (m.AdjustScore ?? 0)),
            //ExamRecordDetailId = details.Where(m => m.QuestionId == x.QuestionId).First()?.Id
        }).ToList();

        var questionIds = previews.Select(x => x.QuestionId).Distinct().ToList();

        var questions1 = await Db.Queryable<Ghre_Question>().Where(x => questionIds.Contains(x.Id)).ToListAsync();
        var answers = await Db.Queryable<Ghre_QuestionAnswer>().Where(x => x.QuestionId != null && questionIds.Contains(x.QuestionId.Value)).OrderBy(x => x.TaxisNo).ToListAsync(); ;

        previews.ForEach(x =>
        {
            var answers1 = answers.Where(y => y.QuestionId == x.QuestionId).ToList();
            x.QuestionType = questions1.FirstOrDefault(a => a.Id == x.QuestionId)?.QuestionType;
            x.QuestionContent = questions1.FirstOrDefault(a => a.Id == x.QuestionId)?.QuestionContent;
            if (!string.IsNullOrEmpty(x.QuestionContent))
                x.QuestionContent = WebUtility.HtmlDecode(x.QuestionContent);
            var detail = new FromGhre_QuestionQuestionTypeDetail();
            detail.content = x.QuestionContent;
            detail.difficulty = questions1.FirstOrDefault(a => a.Id == x.QuestionId)?.DifficultyLevel;
            detail.answer = answers1.Where(x => x.IsCorrect == true).FirstOrDefault()?.QuestionNo;
            detail.answer1 = answers1.Where(x => x.IsCorrect == true).Select(x => x.QuestionNo).ToList();
            detail.answerList = answers1.Select(x => new FromGhre_QuestionQuestionAnswerList()
            {
                No = x.QuestionNo,
                label = x.AnswerContent,
                imageUrl = x.ImageUrl,
                imgWidthPc = x.ImageWidthPc,
                imgWidthApp = x.ImageWidthApp,
            }).ToList();
            detail.RemarkSz = questions1.FirstOrDefault(a => a.Id == x.QuestionId)?.QuestionAnalysis;

            x.detail = detail;

            var recordDetail = details.FirstOrDefault(m => m.ExamPaperQuestionId == x.Id);

            if (recordDetail != null)
                x.ExamRecordDetailId = recordDetail.Id;
            switch (x.QuestionType)
            {
                case "Completion":
                case "ShortAnswer":
                    var answerIds1 = recordAnswers.Where(m => m.ExamRecordDetailId == recordDetail?.Id && m.QuestionAnswerId == null).Select(m => m.AnswerContent).ToList();
                    answerIds1.ForEach(m =>
                    {
                        x.value1.Add(m);
                    });
                    if (x.value1.Any())
                        x.value = x.value1.First();

                    break;
                default:
                    var answerIds = recordAnswers.Where(m => m.ExamRecordDetailId == recordDetail?.Id && m.QuestionAnswerId != null).Select(m => m.QuestionAnswerId).ToList();

                    answers1.Where(m => answerIds.Contains(m.Id)).ForEach(m =>
                    {
                        x.value1.Add(m.QuestionNo);

                    });
                    if (x.value1.Any())
                        x.value = x.value1.First();
                    break;
            }

        });

        extend.questionList = previews;

        string sql = @$"SELECT StaffNo,
                               StaffName,
                               dbo.FO_DeptInfo (DeptID,
                                                getdate (),
                                                1,
                                                'DeptNo') DeptNo,
                               dbo.FO_DeptInfo (DeptID,
                                                getdate (),
                                                1,
                                                'DeptFullPateName') DepteName
                        FROM Ghra_Staff
                        WHERE StaffID = {record.StaffId}";

        extend.StaffInfo = await Db.Ado.SqlQuerySingleAsync<StaffInfo>(sql);

        extend.StaffInfo.StaffScore = details.Sum(x => x.Score) ?? 0;

        sql = @$"SELECT A.StaffNo,
                       A.StaffName,
                       dbo.FO_DeptInfo (A.DeptID,
                                        getdate (),
                                        1,
                                        'DeptNo') DeptNo,
                       dbo.FO_DeptInfo (A.DeptID,
                                        getdate (),
                                        1,
                                        'DeptName') DepteName,
                       A.PhotoUrl,
                       B.TitleName
                FROM Ghra_Staff A LEFT JOIN Ghra_Title B ON B.TitleID = A.TitleID
                WHERE A.StaffID = {record.StaffId}";

        extend.CommentData = await Db.Ado.SqlQuerySingleAsync<CommentData>(sql);

        if (record.ScoreStatus == Consts.DIC_EXAM_RECORD_SCORE_STATUS.NO_SCORE)
            extend.CommentData.IsFirstTime = true;
        extend.CommentData.Comment = record.Comment;

        var body = new QueryBody();
        body.pageNum = 1;
        body.pageSize = 10000;
        var records = await QueryFilterPage(body, $"ExamId='{record.ExamId}'");
        var records1 = records.result.DT_TableDataT1;
        int index = records1.FindIndex(x => x.Id == examRecordId);

        extend.PreviousRecordId = index - 1 >= 0 && records1.Count > 1 ? records1[index - 1].Id : null;
        extend.NextRecordId = records1.Count > index + 1 ? records1[index + 1].Id : null;


        return ServiceResult<Ghre_ExamRecordExtend>.OprateSuccess("查询成功！", extend);
    }

    public async Task<ServiceResult> CommentAsync(Ghre_ExamRecordExtend extend, long examRecordId)
    {

        var record = await QuerySingle(x => x.Id == examRecordId);
        record.Score = extend.StaffInfo.StaffScore;
        record.ScoreStatus = Consts.DIC_EXAM_RECORD_SCORE_STATUS.HAS_SCORE;
        record.Comment = extend.CommentData.Comment;
        var details = await Db.Queryable<Ghre_ExamRecordDetail>().Where(x => x.ExamRecordId == record.Id).ToListAsync();

        extend.questionList.ForEach(x =>
        {
            //var recordDetail = details.FirstOrDefault(m => m.ExamPaperQuestionId == x.Id);
            var recordDetail = details.FirstOrDefault(m => m.Id == x.ExamRecordDetailId);
            if (recordDetail != null)
            {
                recordDetail.Score = x.RealScore;
                recordDetail.IsCorrect = x.Score == x.RealScore ? true : false;
            }
        });

        var paperId = record.ExamPaperId;
        var examPaper = await Db.Queryable<Ghre_ExamPaper>().Where(x => x.Id == paperId).FirstAsync();
        if (examPaper != null)
            record.IsPass = examPaper.PassScore > (record.Score + (record.AdjustScore ?? 0)) ? false : true;
        record.Score = details.Sum(x => x.Score);
        record.Score = extend.questionList.Sum(x => x.RealScore);
        await Db.Updateable(record).ExecuteCommandAsync();
        await Db.Updateable(details).ExecuteCommandAsync();

        var groupId = details.First()?.GroupId;
        var group = await Db.Queryable<Ghre_ExamRecordGroup>().Where(x => x.Id == groupId).FirstAsync();
        if (group != null)
        {
            group.Score = record.Score;
            await Db.Updateable(group).UpdateColumns(it => new { it.Score }, true)
                  .ExecuteCommandAsync();
        }

        return ServiceResult.OprateSuccess("提交成功！");
    }

    public async Task<ServiceResult<QueryExam>> QueryExamAsync(long id)
    {
        var extend = new QueryExam();
        var body = new QueryBody();
        body.pageNum = 1;
        body.pageSize = 10000;
        bool isOpenClass = false;
        long? examRecordId = 0;
        Ghre_Exam exam = null;

        var staffId = App.User.StaffId;

        var openClass = await Db.Queryable<Ghre_OpenClass>().Where(x => x.Id == id).FirstAsync();
        if (openClass != null)
        {
            var id1 = await Db.Queryable<Ghre_ExamRecord>().Where(x => x.OpenClassId == id && x.StaffId == staffId).Select(x => x.Id).FirstAsync();
            if (id1 > 0)
                id = id1;
            else
            {
                id1 = await Db.Queryable<Ghre_StudyRecord>().Where(x => x.OpenClassId == id && x.StaffId == staffId).Select(x => x.Id).FirstAsync();
                if (id1 > 0)
                    id = id1;
            }

            if (id1 == 0 && openClass.IsRequireStudy == false)
            {
                long? courseSnapId = null;
                if (openClass.LinkType == "Course")
                    courseSnapId = await Db.Queryable<Ghre_CourseSnap>().Where(x => x.CourseId == openClass.LinkId).Select(x => x.Id).FirstAsync();

                var insrt = new InsertGhre_ExamRecordInput()
                {
                    ExamId = openClass.ExamId,
                    StudyRecordId = null,
                    StaffId = staffId,
                    CourseSnapId = courseSnapId,
                    CourseSceneId = openClass.LinkType == "CourseScene" ? openClass.LinkId : null,
                    CourseId = openClass.LinkType == "Course" ? openClass.LinkId : null,
                    ExamPaperId = openClass.ExamPaperId,
                    ExamDate = DateTime.Now.Date,
                    RetakeTimes = 0,
                    Status = DIC_EXAM_RECORD_STATUS.WAIT,
                    ScoreStatus = DIC_EXAM_RECORD_SCORE_STATUS.NO_SCORE,
                    BeginTime = openClass.ExamStartTime,
                    EndTime = openClass.ExamEndTime,
                    OpenClassId = openClass?.Id
                };
                id = await base.Add(insrt);
            }

            exam = await Db.Queryable<Ghre_Exam>()
                .Where(x => x.Id == openClass.ExamId)
                .FirstAsync(x => x.Status == DIC_EXAM_STATUS.RELEASED);

            isOpenClass = true;
        }

        Ghre_StudyRecord studyRecord = null;
        if (await Db.Queryable<Ghre_Exam>().AnyAsync(x => x.Id == id))
        {
            studyRecord = await Db.Queryable<Ghre_StudyRecord>().FirstAsync(x => x.ExamId == id && x.StaffId == staffId);
            if (studyRecord != null)
                id = studyRecord.Id;
        }
        if (await Db.Queryable<Ghre_StudyRecord>().AnyAsync(x => x.Id == id && x.StaffId == staffId))
        {
            var examRecord = await Db.Queryable<Ghre_ExamRecord>().FirstAsync(x => x.StudyRecordId == id && x.StaffId == staffId);

            if (!examRecord.IsNull())
                examRecordId = examRecord.Id;
            else
            {

                studyRecord = await Db.Queryable<Ghre_StudyRecord>().FirstAsync(x => x.Id == id && x.StaffId == staffId);

                exam = await Db.Queryable<Ghre_Exam>()
                  .Where(x => x.Id == studyRecord.ExamId)
                  .FirstAsync(x => x.Status == Consts.DIC_EXAM_STATUS.RELEASED);
                if (exam.IsNull())
                    exam = await Db.Queryable<Ghre_Exam>()
                        .Where(x => x.Status == Consts.DIC_EXAM_STATUS.RELEASED
                        && ((x.DateType == Consts.DicExamDateType.EXAM_DATE
                        && x.BeginTime.Value.Date <= DateTime.Now.Date && x.EndTime.Value.Date >= DateTime.Now.Date) || x.DateType == Consts.DicExamDateType.AFTER_HOW_LONG))
                        .WhereIF(!studyRecord.CourseId.IsNull(), x => x.CourseId == studyRecord.CourseId)
                        .WhereIF(!studyRecord.CourseSceneId.IsNull(), x => x.CourseSceneId == studyRecord.CourseSceneId)
                        .FirstAsync();

                if (exam.IsNull())
                    return ServiceResult<QueryExam>.OprateFailed("该门课程尚未开启考试，请联系HR ！");

                var insrt = new InsertGhre_ExamRecordInput()
                {
                    ExamId = exam.Id,
                    StudyRecordId = studyRecord.Id,
                    StaffId = studyRecord.StaffId,
                    CourseSnapId = studyRecord.CourseSnapId,
                    CourseSceneId = studyRecord.CourseSceneId,
                    CourseId = studyRecord.CourseId,
                    ExamPaperId = exam.ExamPaperId,
                    ExamDate = DateTime.Now.Date,
                    RetakeTimes = 0,
                    Status = DIC_EXAM_RECORD_STATUS.WAIT,
                    ScoreStatus = DIC_EXAM_RECORD_SCORE_STATUS.NO_SCORE,
                    BeginTime = exam.BeginTime,
                    EndTime = exam.EndTime,
                    OpenClassId = openClass?.Id,
                };
                examRecordId = await base.Add(insrt);

                if (studyRecord.ExamId.IsNull())
                {
                    string sql = $@"UPDATE Ghre_StudyRecord SET ExamId={exam.Id} WHERE Id='{studyRecord.Id}'; ";
                    await Db.Ado.ExecuteCommandAsync(sql);
                }
            }
        }

        if (examRecordId == 0) examRecordId = id;

        var records = await QueryFilterPage(body, $"Id='{examRecordId}' AND StaffId='{staffId}'");

        if (!records.result.DT_TableDataT1.Any())
            return ServiceResult<QueryExam>.OprateFailed("无效的考试链接！");


        var record = records.result.DT_TableDataT1.FirstOrDefault();
        extend.Status1 = record.Status;

        if (studyRecord.IsNull())
            studyRecord = await Db.Queryable<Ghre_StudyRecord>().FirstAsync(x => x.Id == record.StudyRecordId);

        if (exam.IsNull())
            exam = await Db.Queryable<Ghre_Exam>()
                     .Where(x => x.Id == studyRecord.ExamId)
                     .FirstAsync(x => x.Status == Consts.DIC_EXAM_STATUS.RELEASED || x.Status == Consts.DIC_EXAM_STATUS.DISABLED);
        if (exam.StudyFinishedRule != DIC_EXAM_STUDY_FINISHED_RULE.NO_STUDY_EXAM_PASS)
            if ((isOpenClass == false && exam.IsRequireStudy == true) || (isOpenClass == true && openClass.IsRequireStudy == true))
                if (studyRecord.StudyProgress.IsNull() || (!studyRecord.StudyProgress.IsNull() && studyRecord.StudyProgress < 100))
                    return ServiceResult<QueryExam>.OprateFailed("学习尚未结束暂不可考试！");

        if (exam.IsNull() && (record.Status == DIC_EXAM_RECORD_STATUS.WAIT || record.Status == DIC_EXAM_RECORD_STATUS.EXAMING))
            return ServiceResult<QueryExam>.OprateFailed("该门课程尚未开启考试，请联系HR ！");


        if (exam.Status == Consts.DIC_EXAM_STATUS.DISABLED && (record.Status == DIC_EXAM_RECORD_STATUS.WAIT || record.Status == DIC_EXAM_RECORD_STATUS.EXAMING))
            return ServiceResult<QueryExam>.OprateFailed("该考试已归档，暂不可考试 ！");

        var dt = Db.GetDate();
        if (exam.DateType == Consts.DicExamDateType.AFTER_HOW_LONG)
        {
            record.BeginTime = studyRecord?.EndTime ?? DateTime.Now;
            if (!record.BeginTime.IsNull())
                record.EndTime = record.BeginTime.Value.AddDays(exam.AfterHowLong ?? 7);
        }

        if (isOpenClass)
        {
            if (record.Status == DIC_EXAM_RECORD_STATUS.WAIT && (record.EndTime < dt.Date || record.BeginTime > dt))
                extend.IsAllowExam = false;
        }
        else
        {
            if (!(record.BeginTime.Value.Date <= dt.Date && record.EndTime.Value.Date >= dt.Date) &&
                (record.Status == DIC_EXAM_RECORD_STATUS.WAIT || record.Status == DIC_EXAM_RECORD_STATUS.EXAMING))
            {
                extend.IsAllowExam = false;
            }
        }


        //return ServiceResult<QueryExam>.OprateFailed("考试已结束！");

        var details = await Db.Queryable<Ghre_ExamRecordDetail>().Where(x => x.ExamRecordId == record.Id).ToListAsync();
        var detailIds = details.Select(x => x.Id).ToList();
        var recordAnswers = await Db.Queryable<Ghre_ExamRecordAnswer>()
            .OrderBy(x => x.TaxisNo)
            .Where(x => x.ExamRecordDetailId != null && detailIds.Contains(x.ExamRecordDetailId.Value))
            .ToListAsync();
        //if (record.ScoreStatus == "NoScore")
        //    await ExamHelper.SystemMarkAsync(Db, record, details, recordAnswers);

        var exampaper = await Db.Queryable<Ghre_ExamPaper>().FirstAsync(x => x.Id == record.ExamPaperId);
        var baseData = new DefaultGhre_ExamPaperBaseData();
        baseData.PaperNo = exampaper.PaperNo;
        baseData.PaperName = exampaper.PaperName;
        baseData.AnswerTime = exampaper.AnswerTime;
        baseData.ScoreMethod = exampaper.ScoreMethod;
        baseData.TotalScore = exampaper.TotalScore;
        baseData.PassScore = exampaper.PassScore;
        baseData.RetakeTimes = exampaper.RetakeTimes;
        baseData.RemarkSz = exampaper.RemarkSz;
        baseData.LinkType = exampaper.LinkType;
        baseData.CourseId = exampaper.LinkType == "CourseId" ? exampaper.LinkId : null;
        baseData.CourseSceneId = exampaper.LinkType == "CourseSceneId" ? exampaper.LinkId : null;
        extend.baseData = baseData;


        extend.styleInfo.coverImage = exampaper.CoverUrl;
        extend.styleInfo.paperStyle = exampaper.Style;
        extend.styleInfo.coverBackGround = exampaper.CoverBackGround;

        if (exampaper.SetMethod == DIC_EXAM_PAPER_SET_METHOD.RANDOM && record.Status != DIC_EXAM_RECORD_STATUS.EXAM_END && record.Status != DIC_EXAM_RECORD_STATUS.SYSTEM_END)
        {
            await Db.Deleteable<Ghre_ExamPaperQuestion>().Where(x => x.ExamPaperId == examRecordId).ExecuteCommandAsync();
            var configs = await Db.Queryable<Ghre_ExamPaperConfig>().OrderBy(x => x.TaxisNo).Where(x => x.ExamPaperId == exampaper.Id).ToListAsync();

            var examPaperQuestionIds = new List<long>();

            for (int i = 0; i < configs.Count; i++)
            {
                var config = configs[i];
                string sql = $@"SELECT TOP {config.Quantity} *,NEWID() AS GuidValue FROM Ghre_Question WHERE IsEnable=1";
                if (!string.IsNullOrWhiteSpace(config.DifficultyLevel))
                    sql += $" AND DifficultyLevel='{config.DifficultyLevel}'";
                if (!string.IsNullOrWhiteSpace(config.QuestionType))
                    sql += $" AND QuestionType='{config.QuestionType}'";
                if (config.CourseId != null)
                    sql += $" AND (CourseId='{config.CourseId}' OR CourseIds like '%{config.CourseId}%')";
                if (config.QuestionId != null)
                    sql += $" AND Id='{config.QuestionId}'";
                if (examPaperQuestionIds.Any())
                    sql += $" AND Id NOT IN ({string.Join(",", examPaperQuestionIds)})";

                sql += $" ORDER BY GuidValue ASC";
                var questions2 = await Db.Ado.SqlQueryAsync<Ghre_Question>(sql);

                if (questions2.Any())
                {
                    examPaperQuestionIds.AddRange(questions2.Select(x => x.Id));

                    var insertExamPaperQuestions = questions2.Select(x => new Ghre_ExamPaperQuestion
                    {
                        Id = SnowFlakeSingle.instance.getID(),
                        CreateTime = DateTime.Now,
                        ExamPaperId = examRecordId,
                        QuestionId = x.Id,
                        ConfigId = x.Id,
                        Score = config.Score
                    }).ToList();

                    await Db.Insertable(insertExamPaperQuestions).ExecuteCommandAsync();
                }
            }
        }


        var questions = await Db.Queryable<Ghre_ExamPaperQuestion>()
            .Where(x => (x.ExamPaperId == exampaper.Id && exampaper.SetMethod == DIC_EXAM_PAPER_SET_METHOD.MANUAL) || (x.ExamPaperId == examRecordId && exampaper.SetMethod == DIC_EXAM_PAPER_SET_METHOD.RANDOM))
            .ToListAsync();
        var previews = questions.Where(x => x.QuestionId != null).Select(x => new DefaultGhre_ExamPaperPreview()
        {
            Id = x.Id,
            ConfigId = x.ConfigId,
            parentId = x.ConfigId,
            QuestionId = x.QuestionId.Value,
            ExamPaperId = x.ExamPaperId,
            Score = x.Score,
            RealScore = details.Where(m => m.QuestionId == x.QuestionId).Sum(m => (m.Score ?? 0) + (m.AdjustScore ?? 0)),
            //ExamRecordDetailId = details.Where(m => m.QuestionId == x.QuestionId).First()?.Id
        }).ToList();

        var questionIds = previews.Select(x => x.QuestionId).Distinct().ToList();

        var questions1 = await Db.Queryable<Ghre_Question>().Where(x => questionIds.Contains(x.Id)).ToListAsync();
        var answers = await Db.Queryable<Ghre_QuestionAnswer>().Where(x => x.QuestionId != null && questionIds.Contains(x.QuestionId.Value)).OrderBy(x => x.TaxisNo).ToListAsync(); ;

        previews.ForEach(x =>
        {
            var answers1 = answers.Where(y => y.QuestionId == x.QuestionId).ToList();
            x.QuestionType = questions1.FirstOrDefault(a => a.Id == x.QuestionId)?.QuestionType;
            x.QuestionContent = questions1.FirstOrDefault(a => a.Id == x.QuestionId)?.QuestionContent;
            if (!string.IsNullOrEmpty(x.QuestionContent))
                x.QuestionContent = WebUtility.HtmlDecode(x.QuestionContent);
            var detail = new FromGhre_QuestionQuestionTypeDetail();
            detail.content = x.QuestionContent;
            detail.difficulty = questions1.FirstOrDefault(a => a.Id == x.QuestionId)?.DifficultyLevel;
            //detail.answer = answers1.Where(x => x.IsCorrect == true).FirstOrDefault()?.QuestionNo;

            //detail.answer1 = answers1.Where(x => x.IsCorrect == true).Select(x => x.QuestionNo).ToList();
            if (x.QuestionType == "Completion")
                detail.answer1 = answers1.Where(x => x.IsCorrect == true).Select(x => "").ToList();

            if (x.QuestionType != "Completion")

                detail.answerList = answers1.Select(x => new FromGhre_QuestionQuestionAnswerList()
                {
                    No = x.QuestionNo,
                    label = x.AnswerContent,
                    imageUrl = x.ImageUrl,
                    imgWidthPc = x.ImageWidthPc,
                    imgWidthApp = x.ImageWidthApp,
                }).ToList();

            x.detail = detail;

            var recordDetail = details.FirstOrDefault(m => m.ExamPaperQuestionId == x.Id);
            if (recordDetail != null)
                x.ExamRecordDetailId = recordDetail.Id;
            switch (x.QuestionType)
            {
                case "Completion":
                case "ShortAnswer":
                    var answerIds1 = recordAnswers.Where(m => m.ExamRecordDetailId == recordDetail?.Id && m.QuestionAnswerId == null).Select(m => m.AnswerContent).ToList();
                    answerIds1.ForEach(m =>
                    {
                        x.value1.Add(m);
                    });
                    if (x.value1.Any())
                        x.value = x.value1.First();

                    break;
                default:
                    var answerIds = recordAnswers.Where(m => m.ExamRecordDetailId == recordDetail?.Id && m.QuestionAnswerId != null).Select(m => m.QuestionAnswerId).ToList();

                    answers1.Where(m => answerIds.Contains(m.Id)).ForEach(m =>
                    {
                        x.value1.Add(m.QuestionNo);

                    });
                    if (x.value1.Any())
                        x.value = x.value1.First();
                    break;
            }

        });

        extend.questionList = previews;

        extend.StaffNo = record.StaffNo;
        extend.StaffName = record.StaffName;
        extend.DeptNo = record.DeptNo;
        extend.DeptName = record.DeptName;
        extend.StaffPhoto = record.StaffPhotoUrl;
        extend.ExamName = record.ExamName + "(" + record.ExamNo + ")";
        extend.ExamRemark = exam.RemarkSz;
        if (isOpenClass)
        {
            extend.ExamBeginDate = DateTimeHelper.ConvertToMiniuteString(record.BeginTime);
            extend.ExamEndDate = DateTimeHelper.ConvertToMiniuteString(record.EndTime);
        }
        else
        {

            extend.ExamBeginDate = DateTimeHelper.ConvertToDayString(record.BeginTime);
            extend.ExamEndDate = DateTimeHelper.ConvertToDayString(record.EndTime);
        }
        extend.ExamStatus = record.Status;
        extend.TotalScore = details.Where(x => x.Score != null).Sum(x => x.Score);
        extend.Id = record.Id;
        extend.CourseName = record.CourseName;
        extend.CanRetake = true;
        extend.ScoreOut = false;

        if ((record.RetakeTimes ?? 0) >= (exampaper.RetakeTimes ?? 0))
            extend.CanRetake = false;


        //TimeSpan timeDifference = record.EndTime.Value - DateTime.Now;
        //extend.RemainingSecond = Convert.ToInt32(timeDifference.TotalSeconds);
        //if (extend.RemainingSecond < 0) extend.RemainingSecond = 0;
        extend.RemainingSecond = 3600;
        if (!exampaper.AnswerTime.IsNull())
            extend.RemainingSecond = exampaper.AnswerTime.Value * 60;

        #region 更新实际开始时间
        if (extend.ExamStatus != Consts.DIC_EXAM_RECORD_STATUS.EXAM_END)
        {
            string sql = $"UPDATE Ghre_ExamRecord SET ActualBeginTime = GETDATE(),ActualEndTime = NULL WHERE Id={examRecordId}";
            await Db.Ado.ExecuteCommandAsync(sql);
        }
        #endregion

        if (!record.ActualEndTime.IsNull())
        {
            TimeSpan timeDifference = record.ActualEndTime.Value - record.ActualBeginTime.Value;

            extend.UsageTime = $"{timeDifference.Minutes}分{timeDifference.Seconds}秒";
        }

        if (record.IsView == true)
            extend.CanRetake = false;

        if (exampaper.ScoreMethod == DIC_EXAM_PAPER_SCORE_METHOD.MANUAL && record.ScoreStatus == DIC_EXAM_RECORD_SCORE_STATUS.NO_SCORE && record.Status == DIC_EXAM_RECORD_STATUS.EXAM_END)
        {
            extend.ScoreOut = true;
            extend.ScoreOutTime = "等待人工阅卷";
            extend.IsAllowView = false;
        }

        if (record.Status == DIC_EXAM_RECORD_STATUS.SYSTEM_END)
        {
            extend.IsAllowView = false;
            extend.IsMissExam = true;
        }

        #region 根据参数判断 考完，是否允许查看答案和解析、考完，查看答案和解析后，是否允许重新考试
        if (record.Status == DIC_EXAM_RECORD_STATUS.EXAM_END &&
            exam.IsViewResult != true)
            extend.IsAllowView = false;

        if (record.Status == DIC_EXAM_RECORD_STATUS.EXAM_END &&
            exam.IsViewResult == true &&
            exam.IsAfterViewResultRetake == true)
        {
            if (exam.IsViewResult == true)
            {
                if (exam.IsAfterViewResultRetake == true && (record.RetakeTimes ?? 0) < (exampaper.RetakeTimes ?? 0))
                    extend.CanRetake = true;
                else
                    extend.CanRetake = false;
            }
            else
                extend.IsAllowView = false;
        }
        extend.IsAfterViewResultRetake = exam.IsAfterViewResultRetake;
        #endregion

        var Groups = await Db.Queryable<Ghre_ExamRecordGroup>()
               .OrderByDescending(x => x.ExamTime)
               .Where(x => x.ExamRecordId == record.Id)
               .Select(x => new
               {
                   GroupId = x.Id,
                   x.ExamRecordId,
                   x.ExamTime,
                   x.Score
               }).ToListAsync();
        extend.Groups = Groups
            .Select(x => new ExamGroup()
            {
                GroupId = x.GroupId,
                ExamRecordId = x.ExamRecordId,
                ExamTime = x.ExamTime.ObjToString() + (x.Score != null ? $"得分：{x.Score}" : ""),
            }).ToList();

        return ServiceResult<QueryExam>.OprateSuccess("查询成功！", extend);
    }

    public async Task<ServiceResult> StartExamAsync(long examRecordId)
    {
        var entity = await base.QuerySingle(examRecordId);

        if (entity is null)
            return ServiceResult.OprateFailed("无效的考试ID！");

        var exam = await Db.Queryable<Ghre_Exam>()
                  .Where(x => x.Id == entity.ExamId)
                  .FirstAsync(x => x.Status == Consts.DIC_EXAM_STATUS.RELEASED);

        var studyRecord = await Db.Queryable<Ghre_StudyRecord>().FirstAsync(x => x.Id == entity.StudyRecordId);
        if (exam.DateType == Consts.DicExamDateType.AFTER_HOW_LONG)
        {
            entity.BeginTime = studyRecord?.EndTime ?? DateTime.Now;

            if (!entity.BeginTime.IsNull())
                entity.EndTime = entity.BeginTime.Value.AddDays(exam.AfterHowLong ?? 7);
        }
        var dt = Db.GetDate();
        if (!(entity.BeginTime.Value.Date <= dt.Date && entity.EndTime.Value.Date >= dt.Date))
            return ServiceResult.OprateFailed("考试已结束！");

        #region 试卷 引用次数
        if (entity.Status == Consts.DIC_EXAM_RECORD_STATUS.WAIT)
        {
            string sql = $"UPDATE Ghre_ExamPaper SET LinkTimes = ISNULL(LinkTimes, 0)+1 WHERE Id={entity.ExamPaperId}";
            await Db.Ado.ExecuteCommandAsync(sql);
        }
        #endregion

        if (entity.ActualBeginTime is null)
            entity.ActualBeginTime = DateTime.Now;
        if (entity.Status == Consts.DIC_EXAM_RECORD_STATUS.WAIT)
            entity.Status = Consts.DIC_EXAM_RECORD_STATUS.EXAMING;



        await Update(entity, new List<string>()
        {
            "ActualBeginTime",
            "Status"
        });

        return ServiceResult.OprateSuccess("成功！");
    }

    public async Task<ServiceResult> RetakeExamAsync(long examRecordId)
    {
        var entity = await base.QuerySingle(examRecordId);

        if (entity is null)
            return ServiceResult.OprateFailed("无效的考试ID！");

        var exampaper = await Db.Queryable<Ghre_ExamPaper>().FirstAsync(x => x.Id == entity.ExamPaperId);


        if ((entity.RetakeTimes ?? 0) >= (exampaper.RetakeTimes ?? 0))
            return ServiceResult.OprateFailed($"重考次数已达上限，已重考次数【{entity.RetakeTimes ?? 0}】，允许重考次数【{exampaper.RetakeTimes ?? 0}】！");

        if (entity.Status == DIC_EXAM_RECORD_STATUS.EXAM_END)
            entity.Status = DIC_EXAM_RECORD_STATUS.EXAMING;

        entity.RetakeTimes = entity.RetakeTimes is null ? 1 : entity.RetakeTimes + 1;
        entity.ScoreStatus = DIC_EXAM_RECORD_SCORE_STATUS.NO_SCORE;
        entity.Score = 0;
        entity.IsPass = false;
        entity.FinallyIsPass = false;

        var sql = $@"UPDATE Ghre_ExamRecordDetail SET IsEnable=0 WHERE ExamRecordId='{entity.Id}';
                        UPDATE Ghre_ExamRecordAnswer SET IsEnable=0 WHERE ExamRecordId='{entity.Id}';";

        await Db.Ado.ExecuteCommandAsync(sql);

        await Update(entity, new List<string>()
        {
            "Status","RetakeTimes","ScoreStatus"
        });

        return ServiceResult.OprateSuccess("成功！");
    }
    public async Task<ServiceResult> AnswerExamAsync(List<DefaultGhre_ExamPaperPreview> answers, long studyRecordId)
    {
        var record = await base.QuerySingle(x => x.Id == studyRecordId);
        if (record is null) return ServiceResult.OprateFailed("无效的考试ID");
        using var _context = ContextFactory.CreateContext();
        var exampaper = await Db.Queryable<Ghre_ExamPaper>().FirstAsync(x => x.Id == record.ExamPaperId);

        var dt = Db.GetDate();

        var group = new Ghre_ExamRecordGroup()
        {
            StaffId = App.User.StaffId,
            ExamId = record.ExamId,
            ExamTime = DateTime.Now,
            ExamRecordId = record.Id,
            StudyRecordId = record.StudyRecordId
        };
        var groupId = await Db.Insertable(group).ExecuteReturnSnowflakeIdAsync();

        var exam = await Db.Queryable<Ghre_Exam>()
                  .Where(x => x.Id == record.ExamId)
                  .FirstAsync(x => x.Status == DIC_EXAM_STATUS.RELEASED);

        var studyRecord = await Db.Queryable<Ghre_StudyRecord>().FirstAsync(x => x.Id == record.StudyRecordId);
        if (exam.DateType == DicExamDateType.AFTER_HOW_LONG)
        {
            record.BeginTime = studyRecord?.EndTime ?? DateTime.Now;
            if (!record.BeginTime.IsNull())
                record.EndTime = record.BeginTime.Value.AddDays(exam.AfterHowLong ?? 7);
        }

        var endTime = record.EndTime.Value.AddDays(1).AddSeconds(9);
        if (!(record.BeginTime.Value.Date <= dt.Date && record.EndTime.Value.Date >= dt.Date))
            return ServiceResult.OprateFailed("考试已结束！");

        string sql = $@"UPDATE Ghre_ExamRecordDetail SET IsEnable=0 WHERE ExamRecordId='{record.Id}';
                        UPDATE Ghre_ExamRecordAnswer SET IsEnable=0 WHERE ExamRecordId='{record.Id}';";


        //多次考试成绩认定，Latest,最新分数; Highest,最高分数; Lowest,最低分数
        var ScoreRecognition = exam.ScoreRule ?? "Latest";
        //if (exampaper.ScoreMethod == DIC_EXAM_PAPER_SCORE_METHOD.SYSTEM && ScoreRecognition != "Latest")
        //{
        //    sql = $@"UPDATE Ghre_ExamRecordDetail SET IsEnable=2 WHERE ExamRecordId='{record.Id}';
        //                UPDATE Ghre_ExamRecordAnswer SET IsEnable=2 WHERE ExamRecordId='{record.Id}';";
        //}
        await Db.Ado.ExecuteCommandAsync(sql);

        var questionIds = answers.Select(x => x.QuestionId).ToList();
        var questionAnswers = await Db.Queryable<Ghre_QuestionAnswer>().Where(x => x.QuestionId != null && questionIds.Contains(x.QuestionId.Value)).OrderBy(x => x.TaxisNo).ToListAsync(); ;

        var staff = await Db.Queryable<Ghrs_User>().Where(x => x.UserId == App.User.ID).FirstAsync();

        var recordDetails = new List<Ghre_ExamRecordDetail>();
        var recordDetailAnswers = new List<Ghre_ExamRecordAnswer>();
        answers.ForEach(answer =>
        {
            long id = SnowFlakeSingle.instance.getID();

            recordDetails.Add(new Ghre_ExamRecordDetail()
            {
                Id = id,
                CreateTime = DateTime.Now,
                ExamRecordId = record.Id,
                ExamPaperId = answer.ExamPaperId,
                ExamPaperQuestionId = answer.Id,
                QuestionId = answer.QuestionId,
                StaffId = staff?.UserStaffID,
                Score = 0,
                AdjustScore = 0,
                GroupId = groupId
            });
            var questionAnswers1 = questionAnswers.Where(x => x.QuestionId == answer.QuestionId).ToList();
            switch (answer.QuestionType)
            {
                case "TrueOrFalse":
                case "Single":
                    recordDetailAnswers.Add(new Ghre_ExamRecordAnswer()
                    {
                        Id = SnowFlakeSingle.instance.getID(),
                        CreateTime = DateTime.Now,
                        ExamRecordDetailId = id,
                        ExamRecordId = record.Id,
                        QuestionAnswerId = answer.value.IsNull() ? null : questionAnswers1.First(x => x.QuestionNo == answer.value)?.Id,
                    });
                    break;
                case "Multiple":
                    var TaxisNo = 100;
                    if (answer.value1.IsNull() || (!answer.value1.IsNull() && !answer.value1.Any()))
                        recordDetailAnswers.Add(new Ghre_ExamRecordAnswer()
                        {
                            Id = SnowFlakeSingle.instance.getID(),
                            CreateTime = DateTime.Now,
                            ExamRecordDetailId = id,
                            ExamRecordId = record.Id,
                            AnswerContent = null,
                            TaxisNo = TaxisNo
                        });
                    else
                        foreach (var value in answer.value1)
                        {
                            recordDetailAnswers.Add(new Ghre_ExamRecordAnswer()
                            {
                                Id = SnowFlakeSingle.instance.getID(),
                                CreateTime = DateTime.Now,
                                ExamRecordDetailId = id,
                                ExamRecordId = record.Id,
                                QuestionAnswerId = value.IsNull() ? null : questionAnswers1.First(x => x.QuestionNo == value)?.Id,
                                TaxisNo = TaxisNo
                            });
                            TaxisNo += 100;
                        }

                    break;
                case "Completion":
                    var TaxisNo1 = 100;
                    if (answer.value1.IsNull() || (!answer.value1.IsNull() && !answer.value1.Any()))
                        recordDetailAnswers.Add(new Ghre_ExamRecordAnswer()
                        {
                            Id = SnowFlakeSingle.instance.getID(),
                            CreateTime = DateTime.Now,
                            ExamRecordDetailId = id,
                            ExamRecordId = record.Id,
                            AnswerContent = null,
                            TaxisNo = TaxisNo1
                        });
                    else
                        foreach (var value in answer.value1)
                        {
                            recordDetailAnswers.Add(new Ghre_ExamRecordAnswer()
                            {
                                Id = SnowFlakeSingle.instance.getID(),
                                CreateTime = DateTime.Now,
                                ExamRecordDetailId = id,
                                ExamRecordId = record.Id,
                                AnswerContent = value,
                                TaxisNo = TaxisNo1
                            });
                            TaxisNo1 += 100;
                        }
                    break;
                case "ShortAnswer":
                    recordDetailAnswers.Add(new Ghre_ExamRecordAnswer()
                    {
                        Id = SnowFlakeSingle.instance.getID(),
                        CreateTime = DateTime.Now,
                        ExamRecordId = record.Id,
                        ExamRecordDetailId = id,
                        AnswerContent = answer.value
                    });
                    break;
                default:

                    break;
            }
        });

        await _context.Ghre_ExamRecordDetail.AddRangeAsync(recordDetails);
        await _context.Ghre_ExamRecordAnswer.AddRangeAsync(recordDetailAnswers);

        await _context.SaveChangesAsync();

        record.Status = DIC_EXAM_RECORD_STATUS.EXAM_END;
        record.ActualEndTime = DateTime.Now;
        record.ExamDate = DateTime.Now.Date;
        if (record.AnswerCount.IsNullOrEmpty())
            record.AnswerCount = 1;
        else record.AnswerCount = record.AnswerCount + 1;
        var lastScore = record.Score;

        #region 打分-系统评分
        if (record.ScoreStatus == DIC_EXAM_RECORD_SCORE_STATUS.NO_SCORE && exampaper.ScoreMethod == DIC_EXAM_PAPER_SCORE_METHOD.SYSTEM)
        {
            await ExamHelper.SystemMarkAsync(Db, record, recordDetails, recordDetailAnswers);
            record.ScoreStatus = DIC_EXAM_RECORD_SCORE_STATUS.HAS_SCORE;
            record.AdjustScore = 0;

            _context.Ghre_ExamRecordDetail.UpdateRange(recordDetails);
            _context.Ghre_ExamRecordAnswer.UpdateRange(recordDetailAnswers);
            await _context.SaveChangesAsync();
        }
        #endregion

        group.Score = record.Score;
        await Db.Updateable(group).UpdateColumns(it => new { it.Score }, true)
               .ExecuteCommandAsync();

        #region 多次考试成绩认定
        if (exampaper.ScoreMethod == DIC_EXAM_PAPER_SCORE_METHOD.SYSTEM && (ScoreRecognition == "Highest" || ScoreRecognition == "Lowest"))
        {
            if ((ScoreRecognition == "Highest" && record.Score < lastScore) || ScoreRecognition == "Lowest" && record.Score > lastScore)
            {
                record.Score = lastScore;
                //sql = $@"UPDATE Ghre_ExamRecordDetail SET IsEnable=0 WHERE ExamRecordId='{record.Id}';
                //        UPDATE Ghre_ExamRecordAnswer SET IsEnable=0 WHERE ExamRecordId='{record.Id}';";

                //await Db.Ado.ExecuteCommandAsync(sql);

                //sql = $@"UPDATE Ghre_ExamRecordDetail SET IsEnable=1 WHERE IsEnable=2 AND ExamRecordId='{record.Id}';
                //        UPDATE Ghre_ExamRecordAnswer SET IsEnable=1 WHERE IsEnable=2 AND ExamRecordId='{record.Id}';";
                //await Db.Ado.ExecuteCommandAsync(sql);
            }

            #region 处理最终得分
            if (exam.OnlineScorePercentage != null && exam.OfflineScorePercentage != null)
                if (exam.OnlineScorePercentage > 0 && exam.OfflineScorePercentage > 0)
                {
                    decimal OnlineScorePercentage = exam.OnlineScorePercentage.Value / 100;
                    decimal OfflineScorePercentage = exam.OfflineScorePercentage.Value / 100;
                    record.FinallyScore = (record.Score + (record.AdjustScore ?? 0)) * OnlineScorePercentage;
                    if (record.ActualScore != null && record.ActualScore > 0)
                        record.FinallyScore += record.ActualScore * OfflineScorePercentage;
                }
            #endregion
        }
        #endregion

        record.UpdateTime = DateTime.Now;
        await Update(record, new List<string> { "Status", "Score", "FinallyScore", "AdjustScore", "ActualEndTime", "ScoreStatus", "UpdateTime", "ExamDate", "AnswerCount" }, null, $"Id='{record.Id}'");

        if (exampaper.ScoreMethod == DIC_EXAM_PAPER_SCORE_METHOD.SYSTEM)
            await DealPass(Db, studyRecordId);

        return ServiceResult.OprateSuccess("提交成功！");
    }

    public async Task DealPass(ISqlSugarClient Db, long studyRecordId)
    {
        try
        {
            var record = await Db.Queryable<Ghre_ExamRecord>().FirstAsync(x => x.Id == studyRecordId);
            _logger.LogInformation($"【DealPass：{studyRecordId}】1");

            var studyRecord = await Db.Queryable<Ghre_StudyRecord>().FirstAsync(x => x.Id == record.StudyRecordId);
            studyRecord.ReverseI1 = 1;
            await Db.Updateable(studyRecord).UpdateColumns(it => new { it.ReverseI1 }, true)//true表示追加AOP赋值列
               .ExecuteCommandAsync();

            var examPaper = await Db.Queryable<Ghre_ExamPaper>().FirstAsync(x => x.Id == record.ExamPaperId);
            _logger.LogInformation($"【DealPass：{studyRecordId}】PassScore：{examPaper.PassScore}，Score：{record.Score}，PassScore：{record.AdjustScore}，");

            record.IsPass = examPaper.PassScore > ((record.Score ?? 0) + (record.AdjustScore ?? 0)) ? false : true;
            _logger.LogInformation($"【DealPass：{studyRecordId}】IsPass：{record.IsPass}");

            record.FinallyIsPass = record.IsPass;

            await Db.Updateable(record).UpdateColumns(it => new { it.IsPass, it.FinallyIsPass }, true)//true表示追加AOP赋值列
                .ExecuteCommandAsync();

            await Db.Deleteable<Ghre_CreditPoint>().Where(x => x.ExamId == studyRecord.ExamId).ExecuteCommandAsync();

            if (record.IsPass == true)
            {
                if (studyRecord.CourseSceneId.IsNull())
                {
                    var course = await Db.Queryable<Ghre_Course>().FirstAsync(x => x.Id == studyRecord.CourseId);
                    #region 学分发放
                    var creditPoint = new Ghre_CreditPoint()
                    {
                        CourseId = studyRecord.CourseId,
                        CourseSnapId = studyRecord.CourseSnapId,
                        StaffId = studyRecord.StaffId,
                        ExamId = studyRecord.ExamId,
                        Date = DateTime.Now.Date,
                        CreditPoints = course.CreditPoints
                    };

                    await Db.Insertable(creditPoint).ExecuteReturnSnowflakeIdListAsync();
                    #endregion

                    #region 证书发放

                    #endregion
                }
                else
                {
                    var courses = await Db.Queryable<Ghre_Course>().Where(x => x.CourseSceneId == studyRecord.CourseSceneId).ToListAsync();

                    for (int i = 0; i < courses.Count; i++)
                    {
                        var snap = await Db.Queryable<Ghre_CourseSnap>().FirstAsync(x => x.CourseId == courses[i].Id);

                        #region 学分发放
                        var creditPoint = new Ghre_CreditPoint()
                        {
                            CourseId = courses[i].Id,
                            CourseSnapId = snap?.Id,
                            StaffId = studyRecord.StaffId,
                            ExamId = studyRecord.ExamId,
                            Date = DateTime.Now.Date,
                            CreditPoints = courses[i].CreditPoints
                        };

                        await Db.Insertable(creditPoint).ExecuteReturnSnowflakeIdListAsync();
                        #endregion
                    }

                }

            }

            #region 处理培训记录有效时间
            if (studyRecord.StudyRuleId != null)
            {
                var studyRule = await Db.Queryable<Ghre_StudyRule>().FirstAsync(x => x.Id == studyRecord.StudyRuleId);
                if (studyRule != null && studyRule.ResultValidPeriod != null)
                {
                    studyRecord.ValidBeginTime = DateTime.Now;
                    studyRecord.ValidEndTime = studyRecord.ValidBeginTime.Value.AddMonths(studyRule.ResultValidPeriod.Value);

                    await Db.Updateable(studyRecord).UpdateColumns(it => new { it.ValidBeginTime, it.ValidEndTime }, true)//true表示追加AOP赋值列
                        .ExecuteCommandAsync();

                    record.ValidBeginTime = studyRecord.ValidBeginTime;
                    record.ValidEndTime = studyRecord.ValidEndTime;
                    await Db.Updateable(record).UpdateColumns(it => new { it.ValidBeginTime, it.ValidEndTime })
                        .ExecuteCommandAsync();
                }
            }
            #endregion

            #region 处理学习完成状态
            studyRecord.CompleteStatus = DIC_STUDY_RECORD_STUDY_COMPLETE_STATUS.NO_FINISH;
            await Db.Updateable(studyRecord)
                .UpdateColumns(it => new
                {
                    it.CompleteStatus
                }, true)
               .ExecuteCommandAsync();
            if (record.IsPass == true)
                await ExamHelper.MarkCompleteStatusAsync(Db, studyRecord);

            #endregion

            _logger.LogInformation($"【DealPass：{studyRecordId}】2");

        }
        catch (Exception E)
        {
            _logger.LogInformation($"【DealPass：{studyRecordId}】Message：{E.Message}");
            _logger.LogInformation($"【DealPass：{studyRecordId}】StackTrace：{E.StackTrace}");
        }
    }

    public async Task<ServiceResult> ViewExamPaperCallBackAsync(long examRecordId)
    {
        var entity = await base.QuerySingle(examRecordId);

        if (entity is null)
            return ServiceResult.OprateFailed("无效的考试ID！");

        entity.IsView = true;
        entity.ViewTime = DateTime.Now;

        await Update(entity, new List<string>()
        {
            "IsView","ViewTime"
        });

        return ServiceResult.OprateSuccess("成功！");
    }

    #region Excel导入
    public override async Task<ServiceResult<string>> DownloadExcel(string menuName)
    {
        var physicsPath = $"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}wwwroot";
        var path = $"{$"{Path.DirectorySeparatorChar}files{Path.DirectorySeparatorChar}ExcelTemplate{Path.DirectorySeparatorChar}"}";
        if (!Directory.Exists(physicsPath + path))
            Directory.CreateDirectory(physicsPath + path);

        Type entityType = typeof(Ghre_ExamRecord);
        var fileName = entityType.GetEntityTableName() + ".xlsx";


        var physicsPath1 = physicsPath + path + fileName;
        //if (dataSourceLists.Any())
        //    physicsPath1 = physicsPath + path + newFileName;
        var result = ServiceResult<string>.OprateSuccess("考试成绩_" + DateTimeHelper.ConvertToSecondString1(DateTime.Now) + ".xlsx", physicsPath1);
        return result;
    }
    public override async Task<ServiceResult<ExcelData>> ImportExcel(IFormFile file, string menuName = null, long? MasterId = null)
    {
        var data = new ExcelData();
        long id = SnowFlakeSingle.instance.getID();
        var physicsPath = $"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}wwwroot";
        var path = $"{$"{Path.DirectorySeparatorChar}files{Path.DirectorySeparatorChar}import{Path.DirectorySeparatorChar}{id}{Path.DirectorySeparatorChar}"}";
        if (!Directory.Exists(physicsPath + path))
            Directory.CreateDirectory(physicsPath + path);

        var filepath = physicsPath + path + file.FileName;
        using (var stream = File.Create(filepath))
        {
            await file.CopyToAsync(stream);
        }
        string extension = Path.GetExtension(filepath);

        bool isExistError = false;
        var id1 = SnowFlakeSingle.instance.getID();
        string errorFileName = path + SnowFlakeSingle.instance.getID() + extension;

        var dt = NPOIHelper.ImportExcel(filepath, "考试成绩");
        if (dt.Columns["Comments"] == null)
            dt.Columns.Add("Comments", typeof(string));

        var fields = new List<string>
        {
            "工号",
            "姓名",
            "考试日期",
            "考试分数",
            "调整分",
            "实操分",
            "是否合格",
            "备注"
        };
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            var comments = new List<string>();


            bool isContinue = false;

            fields.ForEach(x =>
            {
                if (!dt.Columns.Contains(x))
                {
                    comments.Add("未查询到【" + x + "】列！");
                    data.ErrorCount++;
                    dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                    isExistError = true;
                    isContinue = true;
                }
            });

            if (isContinue)
                continue;

            var StaffNo = dt.Rows[i]["工号"].ToString();
            var StaffName = dt.Rows[i]["姓名"].ToString();
            var ExamDate = dt.Rows[i]["考试日期"].ToString();
            var Score = dt.Rows[i]["考试分数"].ToString();
            var AdjustScore = dt.Rows[i]["调整分"].ToString();
            var ActualScore = dt.Rows[i]["实操分"].ToString();
            var IsPass = dt.Rows[i]["是否合格"].ToString();

            if (StaffNo.IsNullOrEmpty() && StaffName.IsNullOrEmpty())
                continue;

            var remarkSz = dt.Rows[i]["备注"].ToString();

            var staff = await Db.Queryable<Ghra_Staff>().Where(x => x.StaffNo == StaffNo && x.StaffName == StaffName).FirstAsync();
            if (staff == null)
            {
                comments.Add($"未查询到该员工，工号或姓名填写错误！");
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }
            var exam = await Db.Queryable<Ghre_Exam>().Where(x => x.Id == MasterId).FirstAsync();



            if (ExamDate.IsNullOrEmpty())
                ExamDate = DateTime.Now.ToString();
            if (Score.IsNullOrEmpty())
                Score = "0";

            try
            {
                Convert.ToInt32(Score);
            }
            catch (Exception)
            {
                comments.Add($"考试分数填写有误！");
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }
            try
            {
                Convert.ToInt32(AdjustScore);
            }
            catch (Exception)
            {
                comments.Add($"调整分填写有误！");
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }
            try
            {
                Convert.ToInt32(ActualScore);
            }
            catch (Exception)
            {
                comments.Add($"实操分填写有误！");
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }
            try
            {
                Convert.ToDateTime(ExamDate);
            }
            catch (Exception)
            {
                comments.Add($"考试日期填写有误！");
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }
            //if (await base.AnyAsync(x => x.CertificateRuleId == rule.Id && x.StaffId == staff.StaffID && x.CourseId == course.Id))
            //{
            //    comments.Add($"系统已存在相同证照数据！");
            //    data.ErrorCount++;
            //    dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
            //    isExistError = true;
            //    continue;
            //}
            var snap = await Db.Queryable<Ghre_CourseSnap>().FirstAsync(x => x.CourseId == exam.CourseId);
            var ExamRecordId = SnowFlakeSingle.Instance.NextId();
            var StudyRecordId = SnowFlakeSingle.Instance.NextId();
            var dict1 = new Dictionary<string, object>
                {
                    { "Id", StudyRecordId },
                    { "CreateBy", App.User.ID },
                    { "CreateTime", DateTime.Now },
                    { "ExamId", MasterId },
                    { "StaffId", staff.StaffID },
                    { "CourseId", exam.CourseId },
                    { "CourseSnapId", snap?.Id },
                    { "CourseSceneId", exam.CourseSceneId },
                    { "JoinTime", DateTime.Now },
                    { "RemarkSz", "导入考试成绩生成" }
                };
            var dict = new Dictionary<string, object>
                {
                { "Id", ExamRecordId },
                { "CreateBy", App.User.ID },
                { "CreateTime", DateTime.Now },
                { "ExamId", MasterId },
                { "StudyRecordId", StudyRecordId },
                { "StaffId", staff.StaffID },
                //{ "CourseId", exam.CourseId },
                { "CourseSnapId", snap?.Id },
                { "Score", Score },
                { "AdjustScore", Score },
                { "ActualScore", ActualScore },
                { "ExamDate", ExamDate },
                { "IsPass", IsPass=="是"?true:false },
                { "ScoreStatus", "HasScore" },
                { "Source", "ExcelImport" },
                { "ExamPaperId",exam.ExamPaperId },
                { "RemarkSz", remarkSz }
              };
            try
            {
                await Db.Insertable(dict1).AS("Ghre_StudyRecord").ExecuteCommandAsync();
                await Db.Insertable(dict).AS("Ghre_ExamRecord").ExecuteCommandAsync();
                data.SuccessCount++;
                //data.SuccessCount += list.Count;
            }
            catch (Exception E)
            {
                comments.Add(E.Message);
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }

        }

        if (isExistError)
        {
            NPOIHelper.ExportExcel(dt, null, "考试成绩", physicsPath + errorFileName);
            data.filePath = "/Advanced" + errorFileName;
        }
        return ServiceResult<ExcelData>.OprateSuccess("导入成功！", data);
    }
    #endregion

    #region 提交附件
    public async Task<ServiceResult> SubmitAttachment(long examRecordId, List<InsertGhre_AttachmentInput> attachments)
    {
        var path = attachments.Select(x => x.RelativePath.Replace("/Advanced", null)).Distinct().ToList();
        await Db.Updateable<Ghre_Attachment>()
          .SetColumns(it => new Ghre_Attachment() { TableName = null })
          .Where(it => it.TableName == examRecordId.ObjToString())
          .ExecuteCommandAsync();
        await Db.Updateable<Ghre_Attachment>()
         .SetColumns(it => new Ghre_Attachment() { TableName = examRecordId.ObjToString() })
         .Where(it => path.Contains(it.RelativePath))
         .ExecuteCommandAsync();
        return ServiceResult.OprateSuccess("保存成功！");
    }
    #endregion

    #region 发放证书
    /// <summary>
    /// 发放证书
    /// </summary>
    /// <returns></returns>
    public async Task<ServiceResult> IssueCertificate()
    {
        var now = DateTime.Now;
        //抓取当天提交考试的数据
        var records = await Db.Queryable<Ghre_ExamRecord>()
            .Where(x =>
            x.ExamDate != null &&
            x.ExamDate.Value.Date == now.Date &&
            //x.IsPass == true &&
            (x.IsIssueCertificate == null || x.IsIssueCertificate == false))
            .ToListAsync();
        _logger.LogInformation($"【发放证书】查询到{records.Count}条考试数据");

        var rules = new List<Ghre_CertificateRule>();
        if (records.Any())
        {
            for (int i = 0; i < records.Count; i++)
            {
                var record = records[i];
                await IssueCourseCertificate(record.StaffId, null, record.Id, record.CourseId, record.CourseSceneId);

                if (record.CourseSceneId != null)
                {
                    var courses = await Db.Queryable<Ghre_Course>()
                        .Where(x => x.CourseSceneIds != null && x.CourseSceneIds.Contains(record.CourseSceneId.ObjToString()))
                        .ToListAsync();
                    if (courses.Any())
                        for (int j = 0; j < courses.Count; j++)
                        {
                            await IssueCourseCertificate(record.StaffId, null, record.Id, courses[j].Id, null);
                        }
                }
            }
        }


        if (await Db.Queryable<Ghre_StudyRecord>()
            .Where(x =>
            x.StudyStatus == "HasFinish" &&
            (x.IsIssueCertificate == null || x.IsIssueCertificate == false))
            .AnyAsync())
        {

            var studyRecords = await Db.Queryable<Ghre_StudyRecord>()
            .Where(x =>
            x.StudyStatus == "HasFinish" &&
            (x.IsIssueCertificate == null || x.IsIssueCertificate == false))
            .ToListAsync();

            _logger.LogInformation($"【发放证书】查询到{studyRecords.Count}条待发放学习数据！");


            for (int i = 0; i < studyRecords.Count; i++)
            {
                await IssueCourseCertificate(studyRecords[i].StaffId, studyRecords[i].Id, null, studyRecords[i].CourseId, studyRecords[i].CourseSceneId);

                if (studyRecords[i].CourseSceneId != null)
                {
                    var courses = await Db.Queryable<Ghre_Course>()
                        .Where(x => x.CourseSceneIds != null && x.CourseSceneIds.Contains(studyRecords[i].CourseSceneId.ObjToString()))
                        .ToListAsync();
                    if (courses.Any())
                        for (int j = 0; j < courses.Count; j++)
                        {
                            await IssueCourseCertificate(studyRecords[i].StaffId, studyRecords[i].Id, null, courses[j].Id, null);
                        }
                }
            }
            _logger.LogInformation($"【发放证书】学习数据处理完成！");

        }
        else
            _logger.LogInformation($"【发放证书】未查询到待发放学习数据！");

        return ServiceResult.OprateSuccess("发放成功！");
    }

    /// <summary>
    /// 处理证书数据
    /// </summary>
    /// <param name="staffId">员工ID</param>
    /// <param name="studyRecordId">学习记录ID</param>
    /// <param name="examRecordId">考试记录ID</param>
    /// <param name="courseId">课程ID</param>
    /// <param name="courseSceneId">课程场景ID</param>
    /// <returns></returns>
    private async Task IssueCourseCertificate(int? staffId, long? studyRecordId = null, long? examRecordId = null, long? courseId = null, long? courseSceneId = null)
    {
        var now = DateTime.Now;

        var rules = await Db.Queryable<Ghre_CertificateRule>()
            .WhereIF(studyRecordId != null, x => x.SendRule == "CourseFinish")
            .WhereIF(examRecordId != null, x => (x.SendRule == "ExamPass" || x.SendRule == "ExamScore"))
            .WhereIF(courseId != null, x => x.CourseId1 != null && x.CourseId1.Contains(courseId.ObjToString()))
            .WhereIF(courseSceneId != null, x => x.CourseSceneId1 != null && x.CourseSceneId1.Contains(courseSceneId.ObjToString()))
            .WhereIF(courseId != null && courseSceneId != null, x => x.Id == 0)
            .WhereIF(studyRecordId != null && examRecordId != null, x => x.Id == 0)
            .ToListAsync();

        for (int j = 0; j < rules.Count; j++)
        {
            var rule = rules[j];

            if (examRecordId != null)
            {
                if (rule.SendRule == "ExamPass" && !await Db.Queryable<Ghre_ExamRecord>()
                    .Where(x => x.Id == examRecordId.Value && x.IsPass == true).AnyAsync())
                    continue;

                if (rule.SendRule == "ExamScore" && !await Db.Queryable<Ghre_ExamRecord>()
                    .Where(x => x.Id == examRecordId.Value
                    && x.Score >= rule.ScoreMin
                    && x.Score <= rule.ScoreMax
                    ).AnyAsync())
                    continue;
            }

            string ValidityPeriod = string.Empty;
            DateTime? ValidityPeriodTime = null;

            if (rule.ValidityType == "StaticDuration" && rule.StaticNum != null)
            {
                if (rule.StaticType == "year")
                    ValidityPeriodTime = now.AddYears(rule.StaticNum.Value);
                else if (rule.StaticType == "day")
                    ValidityPeriodTime = now.AddDays(rule.StaticNum.Value);
                else if (rule.StaticType == "month")
                    ValidityPeriodTime = now.AddMonths(rule.StaticNum.Value);
                ValidityPeriod = DateTimeHelper.ConvertToSecondString(ValidityPeriodTime);
            }
            else if (rule.ValidityType == "Option" && rule.ValidityTime != null)
            {
                ValidityPeriodTime = rule.ValidityTime;
                ValidityPeriod = DateTimeHelper.ConvertToSecondString(ValidityPeriodTime);

            }
            else if (rule.ValidityType == "Unlimited")
            {
                ValidityPeriodTime = DateTime.MaxValue;
                ValidityPeriod = "长期";
            }

            var certificate = new Ghre_Certificate()
            {
                CertificateRuleId = rule.Id,
                StaffId = staffId,
                CourseId = courseId,
                AwardDate = now,
                ValidityPeriod = ValidityPeriod,
                ValidityPeriodTime = ValidityPeriodTime,
                AwardSource = studyRecordId != null ? $"学习完成" : $"考试完成",
                Reverse1 = studyRecordId != null ? $"{studyRecordId}" : $"{examRecordId}"

            };
            await Db.Insertable(certificate).ExecuteReturnSnowflakeIdAsync();
        }



        if (studyRecordId != null)
            await Db.Updateable<Ghre_StudyRecord>()
                .SetColumns(it => new Ghre_StudyRecord() { IsIssueCertificate = true }, true)
                .Where(x => x.Id == studyRecordId)
                .ExecuteCommandAsync();


        if (examRecordId != null)
            await Db.Updateable<Ghre_ExamRecord>()
                .SetColumns(it => new Ghre_ExamRecord() { IsIssueCertificate = true }, true)
                .Where(x => x.Id == examRecordId)
                .ExecuteCommandAsync();
    }
    #endregion

    #region 查询考试组

    public async Task<ServiceResult<List<ExamGroup>>> QueryGroups(long examRecordId)
    {
        var Groups = await Db.Queryable<Ghre_ExamRecordGroup>()
               .OrderByDescending(x => x.ExamTime)
               .Where(x => x.ExamRecordId == examRecordId)
               .Select(x => new
               {
                   GroupId = x.Id,
                   x.ExamRecordId,
                   x.ExamTime,
                   x.Score
               }).ToListAsync();
        var groups = Groups
             .Select(x => new ExamGroup()
             {
                 GroupId = x.GroupId,
                 ExamRecordId = x.ExamRecordId,
                 ExamTime = x.ExamTime.ObjToString() + (x.Score != null ? $"得分：{x.Score}" : ""),
             }).ToList();

        return ServiceResult<List<ExamGroup>>.OprateSuccess("成功！", groups);
    }

    #endregion
}