using Microsoft.Extensions.Logging;
using MongoDB.Driver.Linq;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using static Tiobon.Core.DataAccess.ReportHelper;
using static Tiobon.Core.Model.Consts;

namespace Tiobon.Core.Services;

/// <summary>
/// 培训记录 (服务)
/// </summary>
public class Ghre_StudyRecordServices : BaseServices<Ghre_StudyRecord, Ghre_StudyRecordDto, InsertGhre_StudyRecordInput, EditGhre_StudyRecordInput>, IGhre_StudyRecordServices
{
    private readonly IBaseRepository<Ghre_StudyRecord> _dal;
    private readonly ILogger<Ghre_StudyRecordServices> _logger;
    private IGhre_CourseServices _ghre_CourseServices;
    public Ghre_StudyRecordServices(ICaching caching,
        IGhre_CourseServices ghre_CourseServices,
        IBaseRepository<Ghre_StudyRecord> dal, ILogger<Ghre_StudyRecordServices> logger)
    {
        this._dal = dal;
        base.BaseDal = dal;
        base._caching = caching;
        _ghre_CourseServices = ghre_CourseServices;
        _logger = logger;
    }
    public override async Task<ServicePageResult<Ghre_StudyRecordDto>> 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_StudyRecord_V A";
        var sql = @$" SELECT *
                    FROM Ghre_StudyRecord_V  A";

        string conditions = " WHERE  ((( IsRequireStudy='true' OR IsRequireStudy IS NULL )) OR IsRequireStudy='false')  ";
        if (await Db.Queryable<Ghrs_Menu>().Where(x => x.DataPrivType == "Priv" && x.MenuNo == filter.menuName).AnyAsync())
        {
            var staffIds = await GetUserStaffPrivIds((int)App.User.ID);
            if (staffIds.Any())
                conditions = $" WHERE  ((( IsRequireStudy='true' OR IsRequireStudy IS NULL )) OR IsRequireStudy='false') AND StaffId IN ({string.Join(",", staffIds.Select(id => "'" + id + "'"))})";
        }

        if (IsEnable == true)
            conditions += " AND IsEnable = 1";
        else if (IsEnable == false)
            conditions += " AND IsEnable = 0";

        if (!string.IsNullOrWhiteSpace(condition))
            conditions += " AND " + condition;

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

        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 == "Date")
                {
                    var jsonParam = JsonConvert.DeserializeObject<JsonParam1>(value);
                    conditions += $" AND ((ExamDate BETWEEN '{jsonParam.columnValue[0]}' AND '{jsonParam.columnValue[1]}') OR (CourseBeginTime BETWEEN '{jsonParam.columnValue[0]}' AND '{jsonParam.columnValue[1]}') OR (CourseEndTime BETWEEN '{jsonParam.columnValue[0]}' AND '{jsonParam.columnValue[1]}'))";

                    continue;
                }

                if (name == "IsPass" || name == "Source")
                {
                    value = value.Replace("Include", "Equal");
                }
                if (!string.IsNullOrWhiteSpace(value))
                    conditions = DealConditions(conditions, name, value);
            }

        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_StudyRecordDto>(sql);

        var courseSceneIds = entitys.Select(x => x.CourseSceneId).Distinct().ToList();

        var courses = await Db.Queryable<Ghre_Course>().Where(x => x.CourseSceneId != null && courseSceneIds.Contains(x.CourseSceneId)).ToListAsync();


        for (int i = 0; i < entitys.Count; i++)
        {
            var entity = entitys[i];
            entity.StudyStatus = await GetParaLabel("TrainingStudyStatus", entity.StudyStatus);
            entity.StudyFinishedRule = await GetParaLabel("TrainStudyFinishedRule", entity.StudyFinishedRule);
            entity.CompleteStatus = entity.CompleteStatus == DIC_STUDY_RECORD_STUDY_COMPLETE_STATUS.FINISHED ? "已完成" : "未完成";
            if (!string.IsNullOrWhiteSpace(entity.Indate))
                entity.Indate = DateTimeHelper.ConvertToDayString(entity.Indate);
            entity.ExamDate = DateTimeHelper.ConvertToDayString(entity.ExamDate);

            if (entity.ActualBeginTime != null && entity.ActualEndTime != null)
            {
                TimeSpan timeDifference = entity.ActualEndTime.Value - entity.ActualBeginTime.Value;
                entity.ExamDuration = StringHelper.TrimDecimalString(Convert.ToDecimal(timeDifference.TotalMinutes), 2);
            }

            if (entity.CourseType == "ManualInsert")
                entity.UpdateYN = 1;
            if (entity.ExamStatus != "SystemEnd" && entity.ExamStatus.IsNotEmptyOrNull())
                entity.IsViewResult = true;

            #region 处理场景对应课程
            if (entity.CourseSceneId.IsNotEmptyOrNull())
                entity.CourseName = string.Join("\n", courses.Where(x => x.CourseSceneId == entity.CourseSceneId).Select(x => x.CourseName + " (" + x.CourseNo + ")"));
            #endregion

            if (entity.ExamStatus == DIC_EXAM_RECORD_STATUS.EXAM_END)
                if (entity.ValidBeginTime != null && entity.ValidEndTime != null)
                    entity.ResultValidPeriod = DateTimeHelper.ConvertToDayString(entity.ValidBeginTime) + "~" + DateTimeHelper.ConvertToDayString(entity.ValidEndTime);
                else entity.ResultValidPeriod = "长期";
            entity.DataBelongName = await GetDataBelongName(entity.DataBelongID);

            entitys[i] = entity;
        }

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

    }

    public async Task<ServicePageResult<Ghre_StudyRecordDto>> QueryStaff(QueryBody filter)
    {
        if (string.IsNullOrWhiteSpace(filter.orderBy))
            filter.orderBy = "CreateTime1 DESC";

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

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

        string conditions = $" WHERE BeginTime IS NOT NULL AND UserId= {App.User.ID} ";
        var IsEnable = true;
        string condition = string.Empty;
        if (IsEnable == true)
            conditions += " AND IsEnable = 1";
        else if (IsEnable == false)
            conditions += " AND IsEnable = 0";

        if (!string.IsNullOrWhiteSpace(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 == "Date")
                {
                    var jsonParam = JsonConvert.DeserializeObject<JsonParam1>(value);
                    conditions += $" AND ((ExamDate BETWEEN '{jsonParam.columnValue[0]}' AND '{jsonParam.columnValue[1]}') OR (CourseBeginTime BETWEEN '{jsonParam.columnValue[0]}' AND '{jsonParam.columnValue[1]}') OR (CourseEndTime BETWEEN '{jsonParam.columnValue[0]}' AND '{jsonParam.columnValue[1]}'))";

                    continue;
                }

                if (name == "IsPass" || name == "Source")
                {
                    value = value.Replace("Include", "Equal");
                }
                if (!string.IsNullOrWhiteSpace(value))
                    conditions = DealConditions(conditions, name, value);
            }

        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_StudyRecordDto>(sql);

        var courseSceneIds = entitys.Select(x => x.CourseSceneId).Distinct().ToList();

        var courses = await Db.Queryable<Ghre_Course>().Where(x => x.CourseSceneId != null && courseSceneIds.Contains(x.CourseSceneId)).ToListAsync();

        for (int i = 0; i < entitys.Count; i++)
        {
            var entity = entitys[i];
            if (!string.IsNullOrWhiteSpace(entity.Indate))
                entity.Indate = DateTimeHelper.ConvertToDayString(entity.Indate);
            entity.ExamDate = DateTimeHelper.ConvertToDayString(entity.ExamDate);

            if (entity.ActualBeginTime != null && entity.ActualEndTime != null)
            {
                TimeSpan timeDifference = entity.ActualEndTime.Value - entity.ActualBeginTime.Value;
                entity.ExamDuration = StringHelper.TrimDecimalString(Convert.ToDecimal(timeDifference.TotalMinutes), 2);
            }

            if (entity.CourseType == "ManualInsert")
                entity.UpdateYN = 1;
            if (entity.ExamStatus != "SystemEnd" && entity.ExamStatus.IsNotEmptyOrNull())
                entity.IsViewResult = true;

            #region 处理场景对应课程
            if (entity.CourseSceneId.IsNotEmptyOrNull())
            {
                entity.CourseName = string.Join("\n", courses.Where(x => x.CourseSceneId == entity.CourseSceneId).Select(x => x.CourseName + " (" + x.CourseNo + ")"));
            }
            #endregion

            if (entity.ExamRecordId != null)
            {

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

            entitys[i] = entity;
        }

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

    public async Task<ServiceResult<ExcelData>> ExportStaffExcel(QueryExport body)
    {
        QueryBody filter = new QueryBody();
        filter.pageNum = 1;
        filter.pageSize = 1000000;
        filter.langId = body.langId;

        var ids = new List<long>();
        if (body.exportSet.SelectRowKeys != null && body.exportSet.SelectRowKeys.Any())
            ids = body.exportSet.SelectRowKeys;

        var data = await QueryFilterPage(filter, $"UserId={App.User.ID}", true);


        string sql = $@"SELECT *
                            FROM Ghrs_PageSettingQuery
                            WHERE     IsEnable = 1
                                  AND PageNo = '{body.menuName}'
                                  AND (defaultHidden = 'false' or defaultHidden is null)
                            ORDER BY SortNo ASC";

        var columns = await Db.Ado.SqlQueryAsync<QueryExportColumn>(sql);

        var fieldDescs = new Dictionary<string, string>();
        if (body.exportSet.ExFields.Any())
            body.exportSet.ExFields.ForEach(x =>
            {
                if (columns.Any(o => o.field == x))
                    fieldDescs.Add(x, columns.FirstOrDefault(o => o.field == x)?.label);
            });
        else
            fieldDescs = columns.ToDictionary(item => item.field, item => item.label);
        var dt = ToDataTable(data.result.DT_TableDataT1, fieldDescs, null);
        // 获取所有列名
        var dtColumns = dt.Columns;

        var id = SnowFlakeSingle.instance.getID();
        var physicsPath = $"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}wwwroot";
        var path = $"{$"{Path.DirectorySeparatorChar}files{Path.DirectorySeparatorChar}export{Path.DirectorySeparatorChar}{id}{Path.DirectorySeparatorChar}"}";
        if (!Directory.Exists(physicsPath + path))
            Directory.CreateDirectory(physicsPath + path);

        path = path + body.exportSet.TitleName + ".xlsx";
        NPOIHelper.ExportExcel(dt, body.exportSet.TitleName, "sheet1", physicsPath + path);
        var result = new ExcelData();
        result.filePath = path;
        result.fileName = body.exportSet.TitleName + ".xlsx";
        return ServiceResult<ExcelData>.OprateSuccess("导出成功", result);
    }

    public override async Task<long> Add(InsertGhre_StudyRecordInput entity)
    {
        if (entity.BeginTime != null && entity.EndTime != null)
        {
            if (entity.EndTime < entity.BeginTime)
                throw new Exception("学习结束时间需大于学习开始时间！");

            if (entity.EndTime > DateTime.Now)
                throw new Exception("学习结束时间需小于当前时间！");
            TimeSpan timeDifference = entity.EndTime.Value - entity.BeginTime.Value;
            entity.StudyDuration = (decimal)timeDifference.TotalMinutes;

            entity.CourseBeginTime = entity.BeginTime;
            entity.CourseEndTime = entity.EndTime;
        }
        if (await Db.Queryable<Ghre_StudyRecord>()
            .WhereIF(!entity.CourseId.IsNullOrEmpty(), x => x.CourseId == entity.CourseId)
            .WhereIF(!entity.CourseSceneId.IsNullOrEmpty(), x => x.CourseSceneId == entity.CourseSceneId)
            .Where(x => (x.CourseBeginTime <= entity.CourseBeginTime && x.CourseEndTime >= entity.CourseBeginTime) || (x.CourseBeginTime <= entity.CourseEndTime && x.CourseEndTime >= entity.CourseEndTime))
            .AnyAsync(x => x.StaffId == entity.StaffId))
            throw new Exception("该用户存在相同学习记录！");

        entity.StudyStatus = "HasFinish";
        entity.CompleteStatus = DIC_STUDY_RECORD_STUDY_COMPLETE_STATUS.FINISHED;


        var snap = await Db.Queryable<Ghre_CourseSnap>().FirstAsync(x => x.CourseId == entity.CourseId);
        entity.CourseSnapId = snap?.Id;
        if (entity.CourseType.IsNullOrEmpty())
            entity.CourseType = "ManualInsert";
        var result = await base.Add(entity);

        var id = SnowFlakeSingle.Instance.NextId();
        var examRecord = new Ghre_ExamRecord()
        {
            Id = id,
            StudyRecordId = result,
            StaffId = entity.StaffId,
            CourseSnapId = snap?.Id,
            Score = entity.Score,
            AdjustScore = entity.AdjustScore,
            ExamDate = entity.ExamDate,
            IsPass = entity.IsPass,
        };
        await Db.Insertable(examRecord).ExecuteCommandAsync();

        return result;
    }

    public override async Task<bool> Update(long Id, EditGhre_StudyRecordInput editModel)
    {
        if (await Db.Queryable<Ghre_StudyRecord>()
            .WhereIF(!editModel.CourseId.IsNullOrEmpty(), x => x.CourseId == editModel.CourseId)
            .WhereIF(!editModel.CourseSceneId.IsNullOrEmpty(), x => x.CourseSceneId == editModel.CourseSceneId)
            .AnyAsync(x => x.StaffId == editModel.StaffId && x.Id != Id))
            throw new Exception("该用户存在相同学习记录！");

        if (editModel.BeginTime != null && editModel.EndTime != null)
        {
            if (editModel.EndTime < editModel.BeginTime)
                throw new Exception("学习结束时间需大于学习开始时间！");

            if (editModel.EndTime > DateTime.Now)
                throw new Exception("学习结束时间需小于当前时间！");
            TimeSpan timeDifference = editModel.EndTime.Value - editModel.BeginTime.Value;
            editModel.StudyDuration = (decimal)timeDifference.TotalMinutes;
        }

        var snap = await Db.Queryable<Ghre_CourseSnap>().FirstAsync(x => x.CourseId == editModel.CourseId);
        editModel.CourseSnapId = snap?.Id;
        editModel.CourseType = "ManualInsert";
        var result = await base.Update(Id, editModel);
        var snapId = snap?.Id;
        await Db.Updateable<Ghre_ExamRecord>()
            .SetColumns(it => new Ghre_ExamRecord()
            {
                StaffId = editModel.StaffId,
                CourseSnapId = snapId,
                Score = editModel.Score,
                AdjustScore = editModel.AdjustScore,
                ExamDate = editModel.ExamDate,
                IsPass = editModel.IsPass
            })
            .Where(it => it.StudyRecordId == Id)
            .ExecuteCommandAsync();

        return result;
    }

    public override async Task<ServiceFormResult<Ghre_StudyRecordDto>> QueryForm(QueryForm body)
    {
        var result = await base.QueryForm(body);

        var DT_TableDataT1 = result.result.DT_TableDataT1;
        for (int i = 0; i < DT_TableDataT1.Count; i++)
        {
            var record = await Db.Queryable<Ghre_ExamRecord>().FirstAsync(x => x.StudyRecordId == DT_TableDataT1[i].Id);

            if (record != null)
            {
                DT_TableDataT1[i].Score = record.Score;
                DT_TableDataT1[i].AdjustScore = record.AdjustScore;
                if (record.ExamDate != null)
                    DT_TableDataT1[i].ExamDate = record.ExamDate.Value.ToString();
                if (record.IsPass != null)
                    DT_TableDataT1[i].IsPass = record.IsPass;
                //DT_TableDataT1[i].IsPass = record.IsPass == true ? "true" : "false";
            }

        }
        result.result.DT_TableDataT1 = DT_TableDataT1;
        return result;
    }

    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_StudyRecord);
        var fileName = entityType.GetEntityTableName() + ".xlsx";
        //physicsPath = physicsPath + path + fileName;

        IWorkbook hssfworkbook;
        ISheet sheet;
        using (FileStream file = new FileStream(physicsPath + path + fileName, FileMode.Open, FileAccess.Read))
        {
            //hssfworkbook = new HSSFWorkbook(file);
            //hssfworkbook = new XSSFWorkbook(file);
            hssfworkbook = WorkbookFactory.Create(file);
        }
        ISheet sheet2 = hssfworkbook.CreateSheet("下拉数据");

        var newFileName = Guid.NewGuid() + ".xlsx";
        int listColIndex = 0;
        string sql = @"select 'Course' field, Id id, CourseNo no, CourseName name from Ghre_Course where IsEnable=1 and Status='Released'";
        var dataSourceLists = await Db.Ado.SqlQueryAsync<DataSourceList>(sql);
        if (dataSourceLists.Any())
        {
            var types = new List<string>
            {
            "学习记录"
            };

            types.ForEach(sheetName =>
            {
                int sheetIndex = hssfworkbook.GetSheetIndex(sheetName);
                if (sheetIndex >= 0)
                {
                    sheet = hssfworkbook.GetSheetAt(sheetIndex);

                    SetCellDropdownList(sheet, 0, 0, dataSourceLists.Select(x => x.name).ToArray());
                }

            });
            MemoryStream ms;
            using (ms = new MemoryStream())
            {
                hssfworkbook.Write(ms);
                ms.Flush();
                hssfworkbook.Dispose();
                //ms.Position = 0;
                //return ms;
            }
            using (FileStream fs = new FileStream(physicsPath + path + newFileName, FileMode.Create, FileAccess.Write))
            {
                byte[] data = ms.ToArray();
                fs.Write(data, 0, data.Length);
                fs.Flush();
            }

        }

        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;
    }

    #region Excel导入
    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;
        //types.ForEach(async x =>
        //{

        //    string questionType = ConvertQuestionType1(x);
        //    DataTable dt = NPOIHelper.ImportExcel(filepath, x);

        //    NPOIHelper.ExportExcel(dt, null, x, path + id1 + extension);
        //});
        DataTable dt = NPOIHelper.ImportExcel(filepath, "学习记录");
        if (dt.Columns["Comments"] == null)
            dt.Columns.Add("Comments", typeof(string));

        for (int i = 0; i < dt.Rows.Count; i++)
        {
            var comments = new List<string>();

            if (!dt.Columns.Contains("课程（必填）"))
            {
                comments.Add("未查询到【课程（必填）】列！");
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }
            if (!dt.Columns.Contains("课程场景"))
            {
                comments.Add("未查询到【课程场景】列！");
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }
            if (!dt.Columns.Contains("员工（必填）"))
            {
                comments.Add("未查询到【员工（必填）】列！");
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }
            if (!dt.Columns.Contains("考试日期（必填）"))
            {
                comments.Add("未查询到【考试日期（必填）】列！");
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }
            if (!dt.Columns.Contains("学习开始时间"))
            {
                comments.Add("未查询到【学习开始时间】列！");
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }
            if (!dt.Columns.Contains("学习结束时间"))
            {
                comments.Add("未查询到【学习结束时间】列！");
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }
            if (!dt.Columns.Contains("考试分数（必填）"))
            {
                comments.Add("未查询到【考试分数（必填）】列！");
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }
            if (!dt.Columns.Contains("调整分（必填）"))
            {
                comments.Add("未查询到【调整分（必填）】列！");
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }
            if (!dt.Columns.Contains("是否合格（必填）"))
            {
                comments.Add("未查询到【是否合格（必填）】列！");
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }
            if (!dt.Columns.Contains("备注"))
            {
                comments.Add("未查询到【备注】列！");
                data.ErrorCount++;
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                isExistError = true;
                continue;
            }

            var courseName = dt.Rows[i]["课程（必填）"].ToString();
            var staffName = dt.Rows[i]["员工（必填）"].ToString();
            var courseScene = dt.Rows[i]["课程场景"].ToString();
            var examDate = dt.Rows[i]["考试日期（必填）"].ToString();
            var courseBeginTime = dt.Rows[i]["学习开始时间"].ToString();
            var courseEndTime = dt.Rows[i]["学习结束时间"].ToString();
            var score = dt.Rows[i]["考试分数（必填）"].ToString();
            var adjustScore = dt.Rows[i]["调整分（必填）"].ToString();
            var isPass = dt.Rows[i]["是否合格（必填）"].ToString();
            var remarkSz = dt.Rows[i]["备注"].ToString();

            if (courseName.IsNullOrEmpty())
            {
                dt.Rows[i]["Comments"] = "课程为必填项！";
                data.ErrorCount++;
                isExistError = true;
                continue;
            }

            if (staffName.IsNullOrEmpty())
            {
                dt.Rows[i]["Comments"] = "员工为必填项！";
                data.ErrorCount++;
                isExistError = true;
                continue;
            }

            if (examDate.IsNullOrEmpty())
            {
                dt.Rows[i]["Comments"] = "考试日期为必填项！";
                data.ErrorCount++;
                isExistError = true;
                continue;
            }
            if (score.IsNullOrEmpty())
            {
                dt.Rows[i]["Comments"] = "考试分数为必填项！";
                data.ErrorCount++;
                isExistError = true;
                continue;
            }
            if (isPass.IsNullOrEmpty())
            {
                dt.Rows[i]["Comments"] = "是否合格为必填项！";
                data.ErrorCount++;
                isExistError = true;
                continue;
            }

            var staff = await Db.Queryable<Ghra_Staff>().Where(x => x.StaffEname == staffName || x.StaffName == staffName || x.PinYinName == staffName).FirstAsync();

            if (staff.IsNullOrEmpty())
            {
                dt.Rows[i]["Comments"] = "该员工在系统中不存在存在！";
                data.ErrorCount++;
                isExistError = true;
                continue;
            }
            var course = await _ghre_CourseServices.QuerySingleDto(x => x.CourseName == courseName);
            if (course.IsNullOrEmpty())
            {
                dt.Rows[i]["Comments"] = "该课程在系统中不存在存在！";
                data.ErrorCount++;
                isExistError = true;
                continue;
            }

            var scene = await Db.Queryable<Ghre_CourseScene>().Where(x => x.CourseName == courseScene).FirstAsync();

            DateTime? dtExamDate = null;
            try
            {
                dtExamDate = Convert.ToDateTime(examDate);
            }
            catch (Exception)
            {
                dt.Rows[i]["Comments"] = "无效的考试日期！";
                data.ErrorCount++;
                isExistError = true;
                continue;
            }

            DateTime? dtCourseBeginTime = null;
            if (courseBeginTime.IsNotEmptyOrNull())
            {
                try
                {
                    dtCourseBeginTime = Convert.ToDateTime(courseBeginTime);
                }
                catch (Exception)
                {
                    dt.Rows[i]["Comments"] = "无效的学习开始时间！";
                    data.ErrorCount++;
                    isExistError = true;
                    continue;
                }
            }

            DateTime? dtCourseEndTime = null;
            if (courseEndTime.IsNotEmptyOrNull())
            {
                try
                {
                    dtCourseEndTime = Convert.ToDateTime(courseEndTime);
                }
                catch (Exception)
                {
                    dt.Rows[i]["Comments"] = "无效的学习结束时间！";
                    data.ErrorCount++;
                    isExistError = true;
                    continue;
                }
            }

            decimal? Score = null;
            if (score.IsNotEmptyOrNull())
            {
                try
                {
                    Score = Convert.ToDecimal(score);
                }
                catch (Exception)
                {
                    dt.Rows[i]["Comments"] = "无效的考试分数！";
                    data.ErrorCount++;
                    isExistError = true;
                    continue;
                }
            }

            decimal? AdjustScore = null;
            if (adjustScore.IsNotEmptyOrNull())
            {
                try
                {
                    AdjustScore = Convert.ToDecimal(adjustScore);
                }
                catch (Exception)
                {
                    dt.Rows[i]["Comments"] = "无效的学习结束时间！";
                    data.ErrorCount++;
                    isExistError = true;
                    continue;
                }
            }

            try
            {
                var insert = new InsertGhre_StudyRecordInput()
                {
                    CourseId = course?.Id,
                    StaffId = staff.StaffID,
                    CourseSceneId = scene?.Id,
                    Score = Score,
                    AdjustScore = AdjustScore ?? 0,
                    IsPass = isPass == "是" ? true : false,
                    ExamDate = dtExamDate,
                    CourseBeginTime = dtCourseBeginTime,
                    CourseEndTime = dtCourseEndTime,
                    RemarkSz = remarkSz,
                    CourseType = "ExcelImport"
                };
                await Add(insert);
                data.SuccessCount++;
            }
            catch (Exception E)
            {
                dt.Rows[i]["Comments"] = E.Message;
                data.ErrorCount++;
                isExistError = true;
                continue;
            }


        }

        if (isExistError)
        {
            NPOIHelper.ExportExcel(dt, null, "学习记录", physicsPath + errorFileName);
            data.filePath = "/Advanced" + errorFileName;
        }

        return ServiceResult<ExcelData>.OprateSuccess("导入成功！", data);
    }

    #endregion

    public static void SetCellDropdownList(ISheet sheet, int firstcol, int lastcol, string[] vals)
    {

        //設置生成下拉框的行和列
        var cellRegions = new CellRangeAddressList(1, 65535, firstcol, lastcol);
        IDataValidation validation = null;

        if (sheet.GetType().Name.Contains("XSSF")) // .xlsx
        {
            XSSFDataValidationHelper helper = new XSSFDataValidationHelper((XSSFSheet)sheet);//获得一个数据验证Helper  
                                                                                             //IDataValidation
            validation = helper.CreateValidation(
            helper.CreateExplicitListConstraint(vals), cellRegions);//创建约束
        }
        else // HSSF .xls
        {
            //設置 下拉框內容
            DVConstraint constraint = DVConstraint.CreateExplicitListConstraint(vals);
            validation = new HSSFDataValidation(cellRegions, constraint);


            /*綁定下拉框和作用區域，並設置錯誤提示信息
            HSSFDataValidation dataValidate = new HSSFDataValidation(cellRegions, constraint);
            dataValidate.CreateErrorBox("輸入不合法", "請輸入或選擇下拉列表中的值。");
            dataValidate.ShowPromptBox = true;
*/
        }

        validation.CreateErrorBox("输入不合法", "请输入或选择下拉列表中的值。");
        validation.ShowPromptBox = true;

        sheet.AddValidationData(validation);
    }
    #region 获取ESS查询条件
    public async Task<ServiceResult<CoursePublicSearch>> QueryESSSearchFields(QueryBody body)
    {
        var entity = new CoursePublicSearch();
        string sql = @"SELECT Langkey field,
                       CASE {2}
                          WHEN 1 THEN isnull (Value01, LangValue)
                          WHEN 2 THEN isnull (Value02, LangValue)
                          WHEN 3 THEN isnull (Value03, LangValue)
                          WHEN 4 THEN isnull (Value04, LangValue)
                          WHEN 5 THEN isnull (Value05, LangValue)
                          WHEN 6 THEN isnull (Value06, LangValue)
                          WHEN 7 THEN isnull (Value07, LangValue)
                          WHEN 8 THEN isnull (Value08, LangValue)
                          WHEN 9 THEN isnull (Value09, LangValue)
                          WHEN 10 THEN isnull (Value10, LangValue)
                       END label
                FROM Ghrs_LangKey
                WHERE     IsEnable = 1
                      AND (LangKey LIKE 'GHR_Page%' OR LangKey LIKE 'GHR_Common%')";
        sql = string.Format(sql, body.menuName, App.User.ID, body.langId);
        entity.DT_PageMutiMsg = await Db.Ado.SqlQueryAsync<DT_PageMutiMsg>(sql);
        entity.SearchFields.Add(new CoursePublicSearchField()
        {
            label = "开班名称",
            field = "OpenClassName",
            elementType = "Input",
            editable = true,
            required = false,
            multipleSelect = false,
        });
        entity.SearchFields.Add(new CoursePublicSearchField()
        {
            label = "课程编号/名称",
            field = "CourseNoOrName",
            elementType = "Input",
            editable = true,
            required = false,
            multipleSelect = false,
        });
        entity.SearchFields.Add(new CoursePublicSearchField()
        {
            label = "课程分类",
            field = "CourseClassId",
            elementType = "ApiSelect",
            dataSource = "CommonList_TrainingCourseClass",
            editable = true,
            required = false,
            multipleSelect = false,
        });
        entity.SearchFields.Add(new CoursePublicSearchField()
        {
            label = "课程场景",
            field = "CourseSceneId",
            elementType = "ApiSelect",
            dataSource = "CommonList_TrainingCourseScene",
            editable = true,
            required = false,
            multipleSelect = false,
        });
        //entity.SearchFields.Add(new CoursePublicSearchField()
        //{
        //    label = "课程状态",
        //    field = "CourseStatus",
        //    elementType = "ApiSelect",
        //    dataSource = "TBParaDetail_Train_TrainingCourseStatus",
        //    editable = true,
        //    required = false,
        //    multipleSelect = false,
        //});
        entity.SearchFields.Add(new CoursePublicSearchField()
        {
            label = "学习状态",
            field = "CompleteStatus",
            elementType = "ApiSelect",
            dataSource = "TBParaDetail_Train_TrainingStudyStatus",
            editable = true,
            required = false,
            multipleSelect = false,
        });
        return ServiceResult<CoursePublicSearch>.OprateSuccess("", entity);
    }
    #endregion

    #region 获取我的学习
    /// <summary>
    /// 
    /// </summary>
    /// <param name="filter"></param>
    /// <param name="condition"></param>
    /// <param name="IsEnable"></param>
    /// <returns></returns>
    public async Task<ServicePageResult<Ghre_StudyRecordESS>> QueryESS(QueryBody filter, string condition, bool? IsEnable = true)
    {

        string courseType = "Required";
        if (filter.jsonParam != null)
            foreach (JProperty jProperty in filter.jsonParam.Properties())
            {
                var name = jProperty.Name;
                var value = jProperty.Value.ToString();

                if (name == "CourseType")
                {
                    var jsonParam = JsonConvert.DeserializeObject<JsonParam>(value);
                    courseType = jsonParam.columnValue.ObjToString();

                    continue;
                }
            }

        if (courseType == "OpenClass")
            return await QueryOpenClass(filter, condition, IsEnable);

        else
        {
            if (await QueryCompanyCode() == "Ushio" && string.IsNullOrWhiteSpace(filter.orderBy))
                filter.orderBy = "CoursePublishTime DESC";
            else if (string.IsNullOrWhiteSpace(filter.orderBy))
                filter.orderBy = "JoinTime DESC";

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

            var countSql = @$" SELECT COUNT(1) FROM  Ghre_StudyRecord_V";
            var sql = @$" SELECT A.Id,
                               A.StaffId,
                               A.CourseSnapId,
                               A.CourseId,
                               A.CoverUrl,
                               A.UseDefaultCoverImage,
                               A.DefaultCoverImageName,
                               A.CourseName,
                               A.StandardHour,
                               A.CourseCreditPoints CreditPoints,
                               A.CourseBeginTime CourseBeginDate,
                               A.CourseEndTime CourseEndDate,
                               A.ExamDate,
                               A.ExamBeginDate,
                               A.ExamEndDate,
                               A.JoinTime,
                               A.CourseClassId,
                               A.CourseSceneId,
                               A.CourseType,
                               A.ExamDateType,
                               A.AfterHowLong,
                               A.StudyProgress,
                               A.ExamId,A.ExamStatus,A.CoursePublishTime,A.IsRequireStudy,A.CompleteStatus,A.StudyFinishedRule
                        FROM Ghre_StudyRecord_V A";

            string conditions = $" WHERE UserId={App.User.ID} ";

            if (IsEnable == true)
                conditions += " AND IsEnable = 1";
            else if (IsEnable == false)
                conditions += " AND IsEnable = 0";

            if (!string.IsNullOrWhiteSpace(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 == "CourseNoOrName" || name == "KeyWords")
                    {
                        var jsonParam = JsonConvert.DeserializeObject<JsonParam>(value);
                        conditions += $" AND CourseName LIKE '%{jsonParam.columnValue}%'";

                        continue;
                    }
                    if (name == "CourseClassId")
                    {
                        var jsonParam = JsonConvert.DeserializeObject<JsonParam>(value);
                        conditions += $" AND CourseClassId LIKE '%{jsonParam.columnValue}%' ";

                        continue;
                    }
                    if (name == "CourseType")
                    {
                        var jsonParam = JsonConvert.DeserializeObject<JsonParam>(value);

                        var value1 = jsonParam.columnValue;
                        conditions += $" AND {name} LIKE '%{jsonParam.columnValue}%'";

                        continue;
                    }

                    if (name == "CourseStatus")
                    {
                        var jsonParam = JsonConvert.DeserializeObject<JsonParam>(value);
                        var dtTime = DateTime.Now;
                        var value1 = jsonParam.columnValue;
                        switch (value1)
                        {
                            case "In":
                                conditions += $" AND '{DateTimeHelper.ConvertToSecondString(dtTime)}' BETWEEN CourseBeginTime AND CourseEndTime";
                                break;
                            case "Over":
                                conditions += $" AND CourseEndTime >'{DateTimeHelper.ConvertToSecondString(dtTime)}'";
                                break;
                            case "NOStart":
                                conditions += $" AND CourseBeginTime >'{DateTimeHelper.ConvertToSecondString(dtTime)}'";
                                break;
                            default:
                                break;
                        }
                        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;
                            case "GreaterOrEqual"://大于等于
                                conditions += $" AND {name} >='{jsonParam.columnValue}'";
                                break;
                            case "Greater"://大于
                                conditions += $" AND {name} >'{jsonParam.columnValue}'";
                                break;
                            case "LessOrEqual"://小于等于
                                conditions += $" AND {name} <='{jsonParam.columnValue}'";
                                break;
                            case "Less"://小于
                                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_StudyRecordESS>(sql);
            var dt = DateTime.Now.Date;
            entitys.ForEach(x =>
            {
                if (x.CourseBeginDate != null && x.CourseEndDate != null)
                    x.CourseDateString = DateTimeHelper.ConvertToDayString(x.CourseBeginDate) + "~" + DateTimeHelper.ConvertToDayString(x.CourseEndDate);

                if (!x.ExamId.IsNull())
                {
                    if (x.ExamBeginDate != null && x.ExamEndDate != null)
                        x.ExamDateString = DateTimeHelper.ConvertToDayString(x.ExamBeginDate) + "~" + DateTimeHelper.ConvertToDayString(x.ExamEndDate);
                    else x.ExamDateString = $"学完{x.AfterHowLong}天";
                }

                //if (x.CourseBeginDate != null && x.CourseEndDate != null)
                //    if (x.StudyProgress >= 100 || !(x.CourseBeginDate.Value.Date <= DateTime.Now.Date && x.CourseEndDate.Value.Date >= DateTime.Now.Date))
                //        x.DisableStudyBtn = true;

                if ((x.StudyProgress < 100 || x.ExamId.IsNull()) && x.IsRequireStudy != false)
                    x.DisableExamBtn = true;
                if (x.ExamId.IsNotEmptyOrNull() && (x.ExamBeginDate > dt || dt > x.ExamEndDate))
                    x.DisableExamBtn = true;

                if (x.StudyFinishedRule == DIC_EXAM_STUDY_FINISHED_RULE.NO_STUDY_EXAM_PASS)
                    x.DisableExamBtn = false;

                if (x.FeedbackOrderId.IsNull())
                    x.ShowFeedbackBtn = false;

                if (x.ShowFeedbackBtn == true && x.StudyProgress < 100)
                {
                    x.DisableFeedbackBtn = true;
                }

                #region 处理学习进度

                if (x.ExamId.IsNull())
                    x.ShowExamBtn = false;

                if (!x.ExamId.IsNull() && x.FeedbackOrderId.IsNull())
                {
                    if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.WAIT || x.ExamStatus.IsNull())
                        x.StudyProgress = x.StudyProgress / 2;
                    else if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.EXAMING)
                        x.StudyProgress = 75;
                    else if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.EXAM_END)
                        x.StudyProgress = 100;
                }

                if (!x.ExamId.IsNull() && !x.FeedbackOrderId.IsNull())
                {
                    if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.WAIT)
                        x.StudyProgress = x.StudyProgress / 3;
                    else if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.EXAMING)
                        x.StudyProgress = 45;
                    else if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.EXAM_END)
                        x.StudyProgress = 60;
                }
                #endregion

                if (x.IsRequireStudy == false)
                    x.ShowStudyBtn = false;



                if (dt >= x.CourseBeginDate && dt <= x.CourseEndDate)
                    x.DisableStudyBtn = false;
                else
                    x.DisableStudyBtn = true;
            });

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

    /// <summary>
    /// 开班查询
    /// </summary>
    /// <param name="filter"></param>
    /// <param name="condition"></param>
    /// <param name="IsEnable"></param>
    /// <returns></returns>
    public async Task<ServicePageResult<Ghre_StudyRecordESS>> QueryOpenClass(QueryBody filter, string condition, bool? IsEnable = true)
    {
        if (string.IsNullOrWhiteSpace(filter.orderBy))
            filter.orderBy = "PublishTime DESC";

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

        var staffId = App.User.StaffId;


        var sql = @$"SELECT * from (SELECT A.Id,
       A.StartTime  CourseBeginDate,
       A.EndTime CourseEndDate,
       A.RegisterStartTime,
       A.RegisterEndTime,
       A.ExamStartTime ExamBeginDate,
       A.ExamEndTime ExamEndDate,
       A.OpenClassName CourseName,
       A.OpenClassName,
       isnull (C.StandardHour, D.StandardHour) StandardHour,
       isnull
       (
          C.CoverUrl,
          '/File/UploadPath/41_20240807204236365_Snipaste_2024-08-07_20-41-44.png') CoverUrl,
       C.UseDefaultCoverImage,
       C.DefaultCoverImageName,
       isnull (C.CreditPoints, D.CreditPoints) CreditPoints,
       'ExamDate' ExamDateType,
       A.ExamId,
       E.Status ExamStatus,
       A.Status OpenClassStatus,  
       A.CreateTime PublishTime, ISNULL (F.StudyProgress, 0) StudyProgress, 
       A.IsRequireStudy, 
       A.FeedbackId FeedbackOrderId,ISNULL( F.CompleteStatus , 'NoFinish') CompleteStatus, G.Status OpenClassFeedbackStatus
FROM Ghre_OpenClass A
     LEFT JOIN Ghre_StaffGroup B ON A.StaffGroupId = B.Id
     LEFT JOIN Ghre_Course C ON A.LinkId = C.Id
     LEFT JOIN Ghre_CourseScene D ON A.LinkId = D.Id
     LEFT JOIN Ghre_ExamRecord E ON A.Id = E.OpenClassId AND E.StaffId = '{staffId}'
     LEFT JOIN Ghre_StudyRecord F ON A.Id = F.OpenClassId And F.IsEnable=1 AND F.StaffId = '{staffId}'
     LEFT JOIN Ghre_OpenClassFeedback G ON A.Id = G.OpenClassId AND G.Source = 'Trainee' AND G.StaffId = '{staffId}'
WHERE A.Status !='Temporary' AND A.Status !='Close' AND A.IsEnable=1 AND   (   EXISTS
             (SELECT 1
              FROM Ghre_OpenClassStaff C
              WHERE C.OpenClassId = A.ID AND c.StaffId = '{staffId}')
       OR   dbo.[FE_CheckStaffGroup]({staffId},A.StaffGroupId)=1)) A WHERE 1=1 ";

        string conditions = $"";

        if (!string.IsNullOrWhiteSpace(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 == "CourseNoOrName" || name == "KeyWords")
                {
                    var jsonParam = JsonConvert.DeserializeObject<JsonParam>(value);
                    conditions += $" AND CourseName LIKE '%{jsonParam.columnValue}%'";

                    continue;
                }
                if (name == "CourseClassId")
                {
                    var jsonParam = JsonConvert.DeserializeObject<JsonParam>(value);
                    conditions += $" AND CourseClassId LIKE '%{jsonParam.columnValue}%' ";

                    continue;
                }
                if (name == "CourseType")
                    continue;

                if (name == "CourseStatus")
                {
                    var jsonParam = JsonConvert.DeserializeObject<JsonParam>(value);
                    var dtTime = DateTime.Now;
                    var value1 = jsonParam.columnValue;
                    switch (value1)
                    {
                        case "In":
                            conditions += $" AND '{DateTimeHelper.ConvertToSecondString(dtTime)}' BETWEEN CourseBeginTime AND CourseEndTime";
                            break;
                        case "Over":
                            conditions += $" AND CourseEndTime >'{DateTimeHelper.ConvertToSecondString(dtTime)}'";
                            break;
                        case "NOStart":
                            conditions += $" AND CourseBeginTime >'{DateTimeHelper.ConvertToSecondString(dtTime)}'";
                            break;
                        default:
                            break;
                    }
                    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;
                        case "GreaterOrEqual"://大于等于
                            conditions += $" AND {name} >='{jsonParam.columnValue}'";
                            break;
                        case "Greater"://大于
                            conditions += $" AND {name} >'{jsonParam.columnValue}'";
                            break;
                        case "LessOrEqual"://小于等于
                            conditions += $" AND {name} <='{jsonParam.columnValue}'";
                            break;
                        case "Less"://小于
                            conditions += $" AND {name} <'{jsonParam.columnValue}'";
                            break;
                        default:
                            break;
                    }
                }
            }

        sql += conditions;
        var countSql = @$" SELECT COUNT(1) FROM  ({sql}) A";

        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_StudyRecordESS>(sql);

        var ids = entitys.Select(x => x.Id).ToList();

        var openClassStaffs = await Db.Queryable<Ghre_OpenClassStaff>().Where(x => x.OpenClassId != null && ids.Contains(x.OpenClassId.Value) && x.StaffId == staffId).ToListAsync();

        var dt = DateTime.Now;
        entitys.ForEach(x =>
        {

            x.ShowExamBtn = false;
            x.ShowRegisterBtn = false;

            x.DisableExamBtn = true;
            x.DisableStudyBtn = true;


            if (x.OpenClassStatus == "Publish" && !openClassStaffs.Any(o => o.OpenClassId == x.Id))
            {
                x.ShowRegisterBtn = true;
                x.DisableRegisterBtn = true;
                if (dt >= x.RegisterStartTime && dt <= x.RegisterEndTime)
                    x.DisableRegisterBtn = false;

            }
            else if (openClassStaffs.Any(o => o.OpenClassId == x.Id))
            {
                x.ShowStudyBtn = true;
                x.ShowExamBtn = true;
            }
            if (openClassStaffs.Any(o => o.OpenClassId == x.Id))
            {
                if (dt >= x.CourseBeginDate && dt <= x.CourseEndDate && (x.OpenClassStatus == "Publish" || x.OpenClassStatus == "Opening") && openClassStaffs.Any(o => o.OpenClassId == x.Id))
                    x.DisableStudyBtn = false;

                if (x.CourseBeginDate != null && x.CourseEndDate != null)
                    x.CourseDateString = DateTimeHelper.ConvertToDayString(x.CourseBeginDate) + "~" + DateTimeHelper.ConvertToDayString(x.CourseEndDate);

                if (x.IsRequireStudy == false)
                    x.ShowStudyBtn = false;

                if (dt >= x.CourseBeginDate && dt <= x.CourseEndDate)
                    x.DisableStudyBtn = false;
                else
                    x.DisableStudyBtn = true;

                if (!x.ExamId.IsNull())
                {
                    if (x.ExamBeginDate != null && x.ExamEndDate != null)
                        x.ExamDateString = DateTimeHelper.ConvertToDayString(x.ExamBeginDate) + "~" + DateTimeHelper.ConvertToDayString(x.ExamEndDate);
                    else x.ExamDateString = $"学完{x.AfterHowLong}天";
                }

                //if (x.CourseBeginDate != null && x.CourseEndDate != null)
                //    if (x.StudyProgress >= 100 || !(x.CourseBeginDate.Value.Date <= DateTime.Now.Date && x.CourseEndDate.Value.Date >= DateTime.Now.Date))
                //        x.DisableStudyBtn = true;
                if (!x.ExamId.IsNull() && x.ExamBeginDate != null && x.ExamEndDate != null && x.ExamBeginDate <= dt && x.ExamEndDate >= dt)
                    x.DisableExamBtn = false;

                if (x.StudyProgress >= 100 && x.ExamId.IsNotEmptyOrNull() && x.IsRequireStudy != false)
                    x.DisableExamBtn = false;

                if (x.FeedbackOrderId.IsNotEmptyOrNull() && x.OpenClassStatus == "Opening")
                {

                    if (x.ShowFeedbackBtn == true && x.StudyProgress >= 100)
                        x.DisableFeedbackBtn = false;
                }
                else
                    x.ShowFeedbackBtn = false;

                #region 处理学习进度

                if (x.ExamId.IsNull())
                    x.ShowExamBtn = false;

                //if (!x.ExamId.IsNull() && x.FeedbackOrderId.IsNull())
                //{
                //    if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.WAIT || x.ExamStatus.IsNull())
                //        x.StudyProgress = x.StudyProgress / 2;
                //    else if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.EXAMING)
                //        x.StudyProgress = 75;
                //    else if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.EXAM_END)
                //        x.StudyProgress = 100;
                //}

                //if (!x.ExamId.IsNull() && !x.FeedbackOrderId.IsNull())
                //{
                //    if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.WAIT)
                //        x.StudyProgress = x.StudyProgress / 3;
                //    else if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.EXAMING)
                //        x.StudyProgress = 45;
                //    else if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.EXAM_END)
                //        x.StudyProgress = 60;
                //}

                //if (x.OpenClassFeedbackStatus.IsNotEmptyOrNull())
                //    if (x.OpenClassFeedbackStatus == "N")
                //        x.StudyProgress = 83;
                //    else x.StudyProgress = 100;
                if (x.IsRequireStudy == true)
                {
                    if (x.ShowStudyBtn == true && x.ShowExamBtn == true && x.ShowFeedbackBtn == false)
                    {
                        if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.WAIT || x.ExamStatus.IsNull())
                            x.StudyProgress = x.StudyProgress / 2;
                        else if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.EXAMING)
                            x.StudyProgress = 75;
                        else if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.EXAM_END)
                            x.StudyProgress = 100;
                    }
                    else if (x.ShowStudyBtn == true && x.ShowExamBtn == true && x.ShowFeedbackBtn == true)
                    {
                        if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.WAIT || x.ExamStatus.IsNull())
                            x.StudyProgress = x.StudyProgress / 3;
                        else if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.EXAMING)
                            x.StudyProgress = 50;
                        else if (x.ExamStatus == DIC_EXAM_RECORD_STATUS.EXAM_END)
                            x.StudyProgress = 75;

                        if (x.OpenClassFeedbackStatus == "Y")
                            x.StudyProgress = 100;
                    }
                }
                #endregion
            }
            else
            {
                x.ShowExamBtn = false;
                x.ShowFeedbackBtn = false;
                x.ShowStudyBtn = false;
            }
        });

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

    #endregion 

    #region 获取课程
    /// <summary>
    /// 获取课程
    /// </summary>
    /// <param name="courseId"></param> 
    /// <returns></returns>
    public async Task<ServiceResult<Ghre_StudyRecordCourse>> QueryCourse(QueryBody body, long id)
    {
        var course = new Ghre_StudyRecordCourse();

        #region 处理开班自动绑定学习记录
        if (await Db.Queryable<Ghre_OpenClass>().Where(x => x.Id == id).AnyAsync() &&
            !await Db.Queryable<Ghre_StudyRecord>().Where(x => x.OpenClassId == id && x.StaffId == App.User.StaffId).AnyAsync())
        {
            var openClass = await Db.Queryable<Ghre_OpenClass>().Where(x => x.Id == id).FirstAsync();
            var snap = await Db.Queryable<Ghre_CourseSnap>().FirstAsync(x => x.CourseId == openClass.LinkId);
            var studyRecord = new InsertGhre_StudyRecordInput()
            {
                StaffId = App.User.StaffId,
                ExamId = openClass.ExamId,
                CourseSnapId = snap?.Id,
                CourseId = openClass.LinkType == "Course" ? openClass.LinkId : null,
                CourseSceneId = openClass.LinkType == "CourseScene" ? openClass.LinkId : null,
                JoinTime = DateTime.Now,
                CourseBeginTime = openClass.StartTime,
                CourseEndTime = openClass.EndTime,
                //CourseType = rule.RuleType,
                CourseStatus = DIC_STUDY_RECORD_COURSE_STATUS_IN,
                StudyStatus = DIC_STUDY_RECORD_STUDY_STATUS.NO_JOIN,
                CompleteStatus = DIC_STUDY_RECORD_STUDY_COMPLETE_STATUS.NO_FINISH,
                OpenClassId = openClass.Id,
                PlanId = openClass.PlanId
            };
            id = await base.Add(studyRecord);
        }
        else
            id = await Db.Queryable<Ghre_StudyRecord>()
                .Where(x => (x.OpenClassId == id || x.Id == id) && x.StaffId == App.User.StaffId)
                .Select(x => x.Id).FirstAsync();
        #endregion

        string sql = @$"SELECT A.Id,
       A.CourseId,
       A.CourseSceneId,
       ISNULL (B.CourseName, G.SceneName)
          CourseName,
       ISNULL (B.UseDefaultCoverImage, G.UseDefaultCoverImage)
          UseDefaultCoverImage,
       ISNULL (B.DefaultCoverImageName, G.DefaultCoverImageName)
          DefaultCoverImageName,
       ISNULL (B.CoverUrl, G.CoverUrl)
          CoverUrl,
       B.SchoolTeacherId,
       B.SchoolId,
       B.InOrOut,
       E.TeacherName,
       --  E.TeacherEName,


       CASE B.InOrOut
          WHEN 'In' THEN C.StaffEname
          WHEN 'Out' THEN NULL
          ELSE NULL
       END
          AS TeacherEName,
       E.PhotoUrl
          TeacherPhotoUrl,
       CASE E.TeacherType
          WHEN 'In'
          THEN
             dbo.FO_DeptInfo (E.DeptID,
                              getdate (),
                              1,
                              'DeptFullPateName')
          WHEN 'Out'
          THEN
             F.SchoolName
          ELSE
             NULL
       END
          AS DeptOrSchoolName,
       E.SkillPoints
          TeacherRemarkSz,
       ISNULL (B.StandardHour, G.StandardHour)
          StandardHour,
       ISNULL (B.CreditPoints, G.CreditPoints)
          UseDefaultCoverImage,
       B.Outline
          CourseRemarkSz,
       A.StudyProgress,
       A.CourseBeginTime,
       A.CourseEndTime,
       A.StandardDuration
          CourseStandardDuration1,
       A.StudyDuration StudyDuration1,
G.SceneDescription
FROM Ghre_StudyRecord A
     LEFT JOIN Ghre_Course B ON A.CourseId = B.Id
     LEFT JOIN Ghra_Staff c ON B.TeacherId = c.StaffID
     LEFT JOIN Ghre_Teacher E ON B.SchoolTeacherId = E.Id
     LEFT JOIN Ghre_School F ON E.SchoolId = F.Id
     LEFT JOIN Ghre_CourseScene G ON A.CourseSceneId = G.Id
WHERE A.Id  = '{id}'";
        course = await Db.Ado.SqlQuerySingleAsync<Ghre_StudyRecordCourse>(sql);
        if (course.IsNull())
            return ServiceResult<Ghre_StudyRecordCourse>.OprateFailed("无效的学习记录ID！");

        if (course.CourseSceneId.IsNull())
        {
            sql = @$"SELECT A.Id, A.Source, A.Link
                        FROM Ghre_CourseWare A
                        WHERE A.CourseIds LIKE '%{course.CourseId}%' AND A.IsEnable = 1";

            course.CourseWareList = await Db.Ado.SqlQueryAsync<Ghre_StudyRecordCourseWare>(sql);

            if (!course.CourseWareList.Any())
            {

                var CourseWareId = await Db.Queryable<Ghre_Course>().Where(x => x.Id == course.CourseId).Select(x => x.CourseWareId).FirstAsync();
                sql = @$"SELECT A.Id, A.Source, A.Link
                        FROM Ghre_CourseWare A
                        WHERE A.Id = '{CourseWareId}' AND A.IsEnable = 1 order by SortNo ASC";
                course.CourseWareList = await Db.Ado.SqlQueryAsync<Ghre_StudyRecordCourseWare>(sql);

            }

            course.CourseWareList.ForEach(x =>
            {
                x.CourseId = course.CourseId;
                x.CourseName = course.CourseName;
            });
            course.CourseTeacherList =
            [
                new Ghre_StudyRecordCourseTeacher() {
                    TeacherName = course.TeacherName,
                    TeacherEName = course.TeacherEName,
                    TeacherPhotoUrl = course.TeacherPhotoUrl,
                    DeptOrSchoolName = course.DeptOrSchoolName,
                    TeacherRemarkSz = course.TeacherRemarkSz,
                    CourseName = course.CourseName
                }
            ];

            course.CourseRemarkSzs =
            [
                new Ghre_StudyRecordCourseCourseRemarkSzs()
                {
                    CourseName = course.CourseName,
                    Outline = course.CourseRemarkSz
                },
            ];
        }
        else
        {
            course.CourseWareList = new List<Ghre_StudyRecordCourseWare>();
            course.CourseTeacherList = new List<Ghre_StudyRecordCourseTeacher>();
            var courses = await Db.Queryable<Ghre_Course>().Where(x => (x.CourseSceneId == course.CourseSceneId || x.CourseSceneIds.Contains(course.CourseSceneId.ToString())) && x.Status == Consts.DIC_COURSE_STATUS.RELEASED).OrderBy(x => x.SortNo).ToListAsync();

            for (int i = 0; i < courses.Count; i++)
            {
                var course1 = courses[i];

                sql = @$"SELECT A.Id, A.Source, A.Link
                        FROM Ghre_CourseWare A
                        WHERE A.CourseIds LIKE '%{course1.Id}%' AND A.IsEnable = 1 order by SortNo ASC";

                var courseWareList = await Db.Ado.SqlQueryAsync<Ghre_StudyRecordCourseWare>(sql);


                if (!courseWareList.Any())
                {
                    sql = @$"SELECT A.Id, A.Source, A.Link
                        FROM Ghre_CourseWare A
                        WHERE A.Id = '{course1.CourseWareId}' AND A.IsEnable = 1 order by SortNo ASC";
                    course.CourseWareList = await Db.Ado.SqlQueryAsync<Ghre_StudyRecordCourseWare>(sql);

                }
                courseWareList.ForEach(x =>
                {
                    x.CourseId = course1.Id;
                    x.CourseName = course1.CourseName;
                });
                course.CourseWareList.AddRange(courseWareList);



                sql = $@"SELECT a.ID,
                               C.TeacherName,
                               CASE A.InOrOut
                                  WHEN 'In' THEN B.StaffEname
                                  WHEN 'Out' THEN NULL
                                  ELSE NULL
                               END AS TeacherEName,
                               C.PhotoUrl TeacherPhotoUrl,
                               CASE A.InOrOut
                                  WHEN 'In'
                                  THEN
                                     dbo.FO_DeptInfo (b.DeptID,
                                                      getdate (),
                                                      1,
                                                      'DeptFullPateName')
                                  WHEN 'Out'
                                  THEN
                                     D.SchoolName
                                  ELSE
                                     NULL
                               END AS DeptOrSchoolName,
                               c.SkillPoints TeacherRemarkSz,
                               a.CourseName, A.Outline
                        FROM Ghre_Course A
                             LEFT JOIN Ghra_Staff B ON A.TeacherId = B.StaffID
                             LEFT JOIN Ghre_Teacher C ON A.SchoolTeacherId = C.Id
                             LEFT JOIN Ghre_School D ON C.SchoolId = D.Id
                        WHERE a.id = '{course1.Id}'";

                course.CourseTeacherList.Add(await Db.Ado.SqlQuerySingleAsync<Ghre_StudyRecordCourseTeacher>(sql));
                course.CourseRemarkSzs = course.CourseTeacherList.Select(x => new Ghre_StudyRecordCourseCourseRemarkSzs()
                {
                    CourseName = x.CourseName,
                    Outline = x.Outline
                }).ToList();
                course.TeacherName = string.Join("、", course.CourseTeacherList.Where(x => x.TeacherName != null).Select(x => x.TeacherName));

            }
        }

        var details = await Db.Queryable<Ghre_StudyRecordDetail>()
            .Where(x => x.StudyRecordId == id)
            .GroupBy(x => new { x.CourseWareAttachmentId, x.CourseWareId })
            .Select(x => new
            {
                x.CourseWareAttachmentId,
                x.CourseWareId,
                StudyDuration = SqlFunc.AggregateSumNoNull(x.StudyDuration)
            })
            .ToListAsync();

        for (int j = 0; j < course.CourseWareList.Count; j++)
        {
            var attachments = await Db.Queryable<Ghre_CourseWareAttachment>().Where(x => x.CourseWareId == course.CourseWareList[j].Id).ToListAsync();

            var attachmentDtos = attachments.Where(x => x.AttachFileExtension != "http").OrderBy(x => x.SortNo).ToList();

            course.CourseWareList[j].Attachments = Mapper.Map(attachmentDtos).ToANew<List<Ghre_CourseWareAttachmentDto>>();
            if (course.CourseWareList[j].Attachments != null && course.CourseWareList[j].Attachments.Any())
                course.CourseWareList[j].Attachments.ForEach(x => x.RelativePath = "/Advanced" + x.RelativePath);

            course.CourseWareList[j].Attachments.ForEach(x =>
            {
                x.HasLearnDuration = details.FirstOrDefault(o => o.CourseWareAttachmentId == x.Id)?.StudyDuration ?? 0;
                if (x.HasLearnDuration != 0 && x.LearnDuration != 0)
                {
                    x.HasLearnPercent = (x.HasLearnDuration / x.LearnDuration) * 100;
                    if (x.HasLearnPercent > 100)
                        x.HasLearnPercent = 100;
                    x.HasLearnPercent = x.HasLearnPercent.RemoveZero().ObjToDecimal();
                }
            });

            course.CourseWareList[j].Links = attachments
                .Where(x => x.AttachFileExtension == "http")
                .OrderBy(x => x.SortNo)
            .Select(x => new Ghre_CourseWareLink()
            {
                Id = x.Id,
                LinkName = x.AttachmentName,
                LinkAddress = x.RelativePath,
                LearnDuration = x.LearnDuration
            }).ToList();

            course.CourseWareList[j].Links.ForEach(x =>
            {
                x.HasLearnDuration = details.FirstOrDefault(o => o.CourseWareAttachmentId == x.Id)?.StudyDuration ?? 0;
                if (x.HasLearnDuration != 0 && x.LearnDuration != 0)
                {
                    x.HasLearnPercent = (x.HasLearnDuration / x.LearnDuration) * 100;
                    if (x.HasLearnPercent > 100)
                        x.HasLearnPercent = 100;
                    x.HasLearnPercent = x.HasLearnPercent.RemoveZero().ObjToDecimal();
                }
            });
        }

        if (course.CourseBeginTime != null && course.CourseEndTime != null)
            course.CourseDateString = DateTimeHelper.ConvertToDayString(course.CourseBeginTime) + "~" + DateTimeHelper.ConvertToDayString(course.CourseEndTime);

        if (course.CourseStandardDuration.IsNull())
        {
            if (course.CourseId.IsNotEmptyOrNull())
                sql = $@"SELECT SUM (ISNULL (A.Hours, 0) * 60 + A.Minutes) Minutes
                            FROM Ghre_CourseWare A
                            WHERE A.Id IN
                                     (SELECT CourseWareId
                                      FROM Ghre_Course
                                      WHERE (Id = '{course.CourseId}') AND IsEnable = 1)";
            else
                sql = $@"SELECT SUM (ISNULL (A.Hours, 0) * 60 + A.Minutes) Minutes
                            FROM Ghre_CourseWare A
                            WHERE A.Id IN
                                     (SELECT CourseWareId
                                      FROM Ghre_Course
                                      WHERE    (CourseSceneId = '{course.CourseSceneId}' OR CourseSceneIds like '%{course.CourseSceneId}%') AND IsEnable = 1)";
            var mins = await Db.Ado.GetDecimalAsync(sql);

            course.CourseStandardDuration1 = mins;
        }

        if (course.StudyDuration1.IsNull())
            course.StudyDuration = $"0 小时 0 分 0 秒";
        else
        {
            var dt = DateTime.Now;
            var dt1 = dt.AddMinutes((double)course.StudyDuration1);
            var subTract = dt1.Subtract(dt);
            course.StudyDuration = $"{subTract.Hours} 小时 {subTract.Minutes} 分 {subTract.Seconds} 秒";
        }

        if (course.CourseStandardDuration1.IsNull())
            course.CourseStandardDuration = $"0 小时 0 分 0 秒";
        else
        {
            var dt = DateTime.Now;
            var dt1 = dt.AddMinutes((double)course.CourseStandardDuration1);
            var subTract = dt1.Subtract(dt);
            course.CourseStandardDuration = $"{subTract.Hours} 小时 {subTract.Minutes} 分 {subTract.Seconds} 秒";
        }
        return ServiceResult<Ghre_StudyRecordCourse>.OprateSuccess("查询成功！", course);
    }

    #endregion

    #region 加入学习
    public async Task<ServiceResult> Join(long courseId)
    {
        var staffId = GetStaffId();
        if (!await base.AnyAsync(x => x.CourseId == courseId && x.StaffId == staffId))
        {
            var course = await Db.Queryable<Ghre_Course>().Where(x => x.Id == courseId && x.Status == DIC_COURSE_STATUS.RELEASED).FirstAsync();
            if (course.IsNull())
                return ServiceResult.OprateFailed("无效的课程！");

            DateTime courseTime = Db.GetDate();
            var snap = await Db.Queryable<Ghre_CourseSnap>().FirstAsync(x => x.CourseId == courseId);

            var exam = await Db.Queryable<Ghre_Exam>()
                .Where(x => x.Status == DIC_EXAM_STATUS.RELEASED &&
                x.CourseId == courseId
                && ((x.DateType == DicExamDateType.EXAM_DATE
                && x.BeginTime.Value.Date <= DateTime.Now.Date && x.EndTime.Value.Date >= DateTime.Now.Date) || x.DateType == DicExamDateType.AFTER_HOW_LONG))
                .FirstAsync();
            await base.Add(new InsertGhre_StudyRecordInput
            {
                StaffId = staffId,
                CourseSnapId = snap?.Id,
                CourseId = courseId,
                JoinTime = courseTime,
                CourseBeginTime = courseTime.Date,
                CourseEndTime = courseTime.Date.AddMonths(snap?.ValidityPeriod ?? 1),
                CourseType = "ManualElective",
                CourseStatus = DIC_STUDY_RECORD_COURSE_STATUS_IN,
                StudyStatus = DIC_STUDY_RECORD_STUDY_STATUS.NO_JOIN,
                CompleteStatus = DIC_STUDY_RECORD_STUDY_COMPLETE_STATUS.NO_FINISH,
                ExamId = exam?.Id
            });

            if (exam != null)
            {
                var insertStaff = new Ghre_ExamStaff()
                {
                    ExamId = exam?.Id,
                    StaffId = staffId,
                    Source = DIC_EXAM_STAFF_SOURCE.MANUAL_ELECTIVE
                };
                await Db.Insertable(insertStaff).ExecuteReturnSnowflakeIdAsync();
            }
        }
        return ServiceResult.OprateSuccess("加入成功！");
    }
    #endregion

    #region 记录学习时长
    [UseTran]
    public async Task<ServiceResult> RecordDuration(long studyRecordId, decimal? duration, long attachmentId)
    {
        //var sql = $"UPDATE Ghre_StudyRecord SET StudyDuration = ISNULL(StudyDuration, 0)+{duration} WHERE Id='{studyRecordId}' AND  StaffId='{staffId}'";
        //await Db.Ado.ExecuteCommandAsync(sql);

        var standDuration = await Db.Queryable<Ghre_CourseWareAttachment>()
            .Where(x => x.Id == attachmentId)
            .Select(x => x.LearnDuration)
            .FirstAsync() ?? 1000000000;

        var studyDuration = await Db.Queryable<Ghre_StudyRecordDetail>()
            .Where(x => x.StudyRecordId == studyRecordId && x.CourseWareAttachmentId == attachmentId)
            .SumAsync(it => it.StudyDuration);

        studyDuration = studyDuration ?? 0;

        decimal? duration1 = 0;

        if (studyDuration == 0)
        {
            if (duration > standDuration)
                duration1 = standDuration;
            else
                duration1 = duration;
        }
        else
        {
            if (standDuration > (studyDuration + duration))
                duration1 = duration;
            else duration1 = standDuration - studyDuration;
        }
        if (duration1 > 0)
            await Db.Updateable<Ghre_StudyRecord>()
               .SetColumns(it => new Ghre_StudyRecord() { StudyDuration = (it.StudyDuration ?? 0) + duration1 }, true)
               .Where(it => it.Id == studyRecordId && it.StaffId == App.User.StaffId)
               .ExecuteCommandAsync();
        //decimal? duration1 = 0;
        //if (standDuration < (studyDuration + duration))
        //    duration1 = standDuration - studyDuration;

        //if (duration1 > 0)


        await GenerateStaffStudyRecord(Db, studyRecordId, duration.Value, attachmentId);


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

    public async Task<bool> GenerateStaffStudyRecord(ISqlSugarClient Db, long studyRecordId, decimal duration, long attachmentId)
    {
        _logger.LogInformation($"【记录学习时长】GenerateStaffStudyRecord");

        var record = await Db.Queryable<Ghre_StudyRecord>().FirstAsync(x => x.Id == studyRecordId);

        var attachment = await Db.Queryable<Ghre_CourseWareAttachment>().FirstAsync(x => x.Id == attachmentId);

        var courseWareIds = new List<long?>();

        if (record.CourseId.IsNullOrEmpty())
            courseWareIds = await Db.Queryable<Ghre_Course>().Where(x => (x.CourseSceneId == record.CourseSceneId || x.CourseSceneIds.Contains(record.CourseSceneId.ObjToString())) && x.Status == Consts.DIC_COURSE_STATUS.RELEASED).Select(x => x.CourseWareId).ToListAsync();
        else
            courseWareIds = await Db.Queryable<Ghre_Course>().Where(x => x.Id == record.CourseId && x.Status == Consts.DIC_COURSE_STATUS.RELEASED).Select(x => x.CourseWareId).ToListAsync();

        #region 记录学习明细
        var detail = new Ghre_StudyRecordDetail()
        {
            StudyRecordId = studyRecordId,
            StaffId = record.StaffId,
            CourseWareId = attachment.CourseWareId,
            CourseWareAttachmentId = attachmentId,
            StudyDuration = duration
        };
        await Db.Insertable(detail).ExecuteCommandAsync();
        #endregion

        decimal studyProgress = 0;
        _logger.LogInformation($"【记录学习时长】studyProgress:{studyProgress}");

        var sql = $@"SELECT SUM(ISNULL (A.Hours, 0) * 60 + A.Minutes) Minutes
                            FROM Ghre_CourseWare A
                            WHERE A.Id IN
                                     (SELECT CourseWareId
                                      FROM Ghre_Course
                                      WHERE    (Id = '{record.CourseId}') AND IsEnable = 1)";
        if (record.CourseId.IsNullOrEmpty())
            sql = $@"SELECT SUM(ISNULL (A.Hours, 0) * 60 + A.Minutes) Minutes
                            FROM Ghre_CourseWare A
                            WHERE A.Id IN
                                     (SELECT CourseWareId
                                      FROM Ghre_Course
                                      WHERE    (CourseSceneId = '{record.CourseSceneId}'
                                            OR CourseSceneIds like '%{record.CourseSceneId}%') AND IsEnable = 1)";
        var mins = await Db.Ado.GetDecimalAsync(sql);

        if (mins > 0)
        {
            duration = record.StudyDuration ?? 0;



            studyProgress = (duration / mins) * 100;
            if (studyProgress > 100)
                studyProgress = 100;
        }
        _logger.LogInformation($"【记录学习时长】studyProgress1:{studyProgress}");



        #region 判断所有附件 是否都被打开
        if (studyProgress == 100)
        {
            var detailWareAttachmentCount = await Db.Queryable<Ghre_StudyRecordDetail>().Where(x => x.StudyRecordId == studyRecordId).Select(x => x.CourseWareAttachmentId).Distinct().CountAsync();

            var wareAttachmentCount = await Db.Queryable<Ghre_CourseWareAttachment>().Where(x => courseWareIds.Contains(x.CourseWareId)).CountAsync();

            if (wareAttachmentCount > detailWareAttachmentCount)
                studyProgress = 99;
        }

        #endregion

        var studyStatus = DIC_STUDY_RECORD_STUDY_STATUS.NO_FINISH;

        var completeStatus = record.CompleteStatus ?? DIC_STUDY_RECORD_STUDY_COMPLETE_STATUS.NO_FINISH;

        //处理学习记录完成状态
        if (studyProgress == 100)
        {
            studyStatus = DIC_STUDY_RECORD_STUDY_STATUS.HAS_FINISH;
            await ExamHelper.MarkCompleteStatusAsync(Db, record);
        }

        var studyProgress1 = Convert.ToInt32(studyProgress);
        _logger.LogInformation($"【记录学习时长】studyProgress2:{studyProgress}");
        _logger.LogInformation($"【记录学习时长】studyProgress3:{studyProgress1}");
        if (studyProgress > 0)
            await Db.Updateable<Ghre_StudyRecord>()
                .SetColumns(it => new Ghre_StudyRecord()
                {
                    StudyProgress = studyProgress1,
                    StudyStatus = studyStatus,
                    StandardDuration = mins,
                    //ReverseI1 = 1
                })
                .Where(it => it.Id == studyRecordId)
                .ExecuteCommandAsync();

        await Db.Updateable<Ghre_StudyRecord>()
              .SetColumns(it => new Ghre_StudyRecord()
              {
                  BeginTime = DateTime.Now,
                  StudyStatus = studyStatus,
              })
              .Where(it => it.Id == studyRecordId && it.BeginTime == null)
              .ExecuteCommandAsync();


        if (studyProgress1 >= 100)
        {
            await Db.Updateable<Ghre_StudyRecord>()
                .SetColumns(it => new Ghre_StudyRecord()
                {
                    EndTime = DateTime.Now,
                })
                .Where(it => it.Id == studyRecordId && it.EndTime == null)
                .ExecuteCommandAsync();
        }
        return true;
    }
    #endregion

    #region 同步学习记录至ESS
    public async Task SyncToESS()
    {
        var dt = DateTime.Now;
        var records = await Db.Queryable<Ghre_StudyRecord>().Where(x => x.EndTime != null && x.EndTime.Value.Date == dt.AddDays(-1).Date && x.StaffTrainingId == null).Select(x => x.Id).ToListAsync();
        for (int i = 0; i < records.Count; i++)
        {
            var sql = @$"SELECT A.Id,
                               A.CourseId,
                               A.StaffId,
                               A.EndTime,
                               A.BeginTime,
                               A.CourseEndTime,
                               A.CourseBeginTime,
                               A.CourseSceneId,
                               A.IsPass,
                               isnull (A.CourseName, A.CourseScene) CourseName,
                               A.StandardHour,
                               isnull (c.SchoolName, '内部培训') Reverse1,A.CreditPoints,A.StaffTrainingId
                        FROM Ghre_StudyRecord_V A
                             LEFT JOIN Ghre_Course b ON A.CourseId = b.Id
                             LEFT JOIN Ghre_School c ON b.SchoolId = c.Id
                        WHERE A.id = {records[i]} ";
            var record = await Db.Ado.SqlQuerySingleAsync<Ghre_StudyRecordDto>(sql);


            var train = new Ghra_StaffTraining()
            {
                StaffID = record.StaffId,
                CourseName = record.CourseName,
                TrainingOrgName = record.Reverse1,
                ClassHour = record.StandardHour,
                ClassCredit = record.CreditPoints,
                BeginDate = record.BeginTime,
                EndDate = record.EndTime,
                IsPass = record.IsPass == true ? 1 : 0,
                CreateBy = 0,
                CreateTime = DateTime.Now
            };
            var result = await Db.Insertable(train).ExecuteReturnIdentityAsync();

            await Db.Updateable<Ghre_StudyRecord>()
            .SetColumns(it => new Ghre_StudyRecord()
            {
                StaffTrainingId = result
            })
            .Where(it => it.Id == records[i])
            .ExecuteCommandAsync();

        }
    }
    #endregion

    #region 获取我的学习
    /// <summary>
    /// 
    /// </summary>
    /// <param name="filter"></param>
    /// <param name="condition"></param>
    /// <param name="IsEnable"></param>
    /// <returns></returns>
    public async Task<ServicePageResult<TeacherClassAnalysis>> QueryTeacherClassAnalysis(QueryBody filter)
    {
        if (string.IsNullOrWhiteSpace(filter.orderBy))
            filter.orderBy = "DeptName ASC";

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

        string conditions = $" AND 1=1 ";

        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 (!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;
                        case "GreaterOrEqual"://大于等于
                            conditions += $" AND {name} >='{jsonParam.columnValue}'";
                            break;
                        case "Greater"://大于
                            conditions += $" AND {name} >'{jsonParam.columnValue}'";
                            break;
                        case "LessOrEqual"://小于等于
                            conditions += $" AND {name} <='{jsonParam.columnValue}'";
                            break;
                        case "Less"://小于
                            conditions += $" AND {name} <'{jsonParam.columnValue}'";
                            break;
                        default:
                            break;
                    }
                }
            }


        var sql = @$"SELECT DeptName,
       TeacherName,
       TeacherLevel,
       CourseName,
       SUM (StandardHour) StandardHour,
       count (0) NUM
FROM (SELECT ISNULL
             (C.DeptName + ' (' + C.DeptNo + ')',
              D.SchoolName + ' (' + D.SchoolNo + ')') DeptName,
             E.TeacherName + ' (' + E.TeacherNo + ')' TeacherName,
             E.TeacherLevel,
             B.CourseName,
             B.StandardHour
      FROM Ghre_StudyRecord_V A
           LEFT JOIN Ghre_Course B ON A.CourseId = B.Id
           LEFT JOIN Ghro_Dept C ON B.TeacherDeptId = C.DeptID
           LEFT JOIN Ghre_School D ON B.SchoolId = D.Id
           LEFT JOIN Ghre_Teacher E ON B.SchoolTeacherId = E.Id
      WHERE A.BeginTime IS NOT NULL AND dbo.FUserDataBelongPriv ({App.User.ID}, A.DataBelongID, NULL) = 1 
AND A.CourseId IS NOT NULL {conditions}) A WHERE TeacherName is not null
GROUP BY DeptName,
         TeacherName,
         TeacherLevel,
         CourseName
ORDER BY {filter.orderBy}";

        var entitys = await Db.Ado.SqlQueryAsync<TeacherClassAnalysis>(sql);
        var dt = DateTime.Now.Date;
        entitys.ForEach(async x =>
        {
            x.TeacherLevelLabel = await GetParaLabel("TrainingTeacherLevel", x.TeacherLevel);
        });

        return new ServicePageResult<TeacherClassAnalysis>(filter.pageNum, entitys.Count, filter.pageSize, entitys);

    }

    #endregion

    #region 批量删除

    public override async Task<bool> DeleteById1(object id)
    {
        return await DeleteByIds1([id.ObjToLong()]);
    }
    /// <summary>
    /// 删除指定ID集合的数据(批量删除)
    /// </summary>
    /// <param name="ids">主键ID集合</param>
    /// <returns></returns>
    public override async Task<bool> DeleteByIds1(long[] ids)
    {

        var examRecords = await Db.Queryable<Ghre_ExamRecord>()
            .Where(it => it.StudyRecordId != null && ids.Contains(it.StudyRecordId.Value))
            .Select(x => new { x.Id, x.StaffId, x.ExamId }).ToListAsync();

        var examIds = examRecords.Select(x => x.ExamId).ToList();
        var staffIds = examRecords.Select(x => x.StaffId).ToList();
        var examRecordIds = examRecords.Select(x => x.Id).ToList();

        await Db.Updateable<Ghre_ExamRecord>()
          .SetColumns(it => new Ghre_ExamRecord() { IsEnable = 0 }, true)
          .Where(it => examRecordIds.Contains(it.Id))
          .ExecuteCommandAsync();

        await Db.Updateable<Ghre_ExamStaff>()
         .SetColumns(it => new Ghre_ExamStaff() { IsEnable = 0 }, true)
         .Where(it => staffIds.Contains(it.StaffId) && it.StaffId != null && it.ExamId != null && examIds.Contains(it.ExamId))
         .ExecuteCommandAsync();

        await Db.Updateable<Ghre_StudyRecord>()
           .SetColumns(it => new Ghre_StudyRecord() { IsEnable = 0 }, true)
           .Where(it => ids.Contains(it.Id))
           .ExecuteCommandAsync();

        #region 补充逻辑，只学习，未进入到考试页面
        var examId = await Db.Queryable<Ghre_StudyRecord>()
            .Where(x => ids.Contains(x.Id) && x.ExamId != null)
            .Select(x => x.ExamId).Distinct().ToListAsync();
        staffIds = await Db.Queryable<Ghre_StudyRecord>()
            .Where(x => ids.Contains(x.Id) && x.StaffId != null)
            .Select(x => x.StaffId).Distinct().ToListAsync();

        await Db.Updateable<Ghre_ExamStaff>()
            .SetColumns(it => new Ghre_ExamStaff() { IsEnable = 0 }, true)
            .Where(it => staffIds.Contains(it.StaffId) && it.StaffId != null && it.ExamId != null && examIds.Contains(it.ExamId))
            .ExecuteCommandAsync();
        #endregion

        return true;
    }
    #endregion

    #region 发放学分
    /// <summary>
    /// 发放学分
    /// </summary>
    /// <returns></returns>
    public async Task<ServiceResult> IssueCredit()
    {
        var now = DateTime.Now;
        //抓取当天提交考试的数据
        var records = await Db.Queryable<Ghre_StudyRecord>()
            .Where(x => x.StudyProgress == 100 && (x.IsIssueCredit == null || x.IsIssueCredit == false))
            .Take(100)
            .ToListAsync();
        _logger.LogInformation($"【学分发放】查询到{records.Count}条考试数据");
        if (!records.Any())
            return ServiceResult.OprateSuccess("发放成功！");

        var creditPoints = new List<Ghre_CreditPoint>();
        for (int i = 0; i < records.Count; i++)
        {
            long? creditRuleId = null;
            long? courseCreditPoints = 0;

            var record = records[i];
            if (record.CourseId.IsNotEmptyOrNull())
            {
                creditRuleId = await Db.Queryable<Ghre_Course>().Where(x => x.Id == record.CourseId).Select(x => x.CreditRuleId).FirstAsync();
                courseCreditPoints = await Db.Queryable<Ghre_Course>().Where(x => x.Id == record.CourseId).Select(x => x.CreditPoints).FirstAsync();
            }
            else if (record.CourseSceneId.IsNotEmptyOrNull())
            {
                creditRuleId = await Db.Queryable<Ghre_CourseScene>().Where(x => x.Id == record.CourseId).Select(x => x.CreditRuleId).FirstAsync();

            }
            if (courseCreditPoints <= 0)
                continue;

            if (creditRuleId != null)
            {
                var creditRule = await Db.Queryable<Ghre_CreditRule>().Where(x => x.Id == record.CourseId).Select(x => new
                {
                    x.RuleType,
                    x.ScoreRange,
                    x.StudyCompletedPercent,
                    x.ExamPassPercent
                }).FirstAsync();
                if (creditRule != null)
                {
                    var creditPoint = new Ghre_CreditPoint()
                    {
                        StaffId = record.StaffId,
                        StudyRecordId = record.Id,
                        ExamId = record.ExamId,
                        CreditRuleId = creditRuleId,
                        Date = DateTime.Now
                    };
                    if (creditRule.RuleType == "StudyCompletedPercent")//学习完成
                    {
                        creditPoint.CreditPoints = ((courseCreditPoints * creditRule.StudyCompletedPercent) / 100).ObjToInt();
                        record.IsIssueCredit = true;
                    }
                    else if (creditRule.RuleType == "ExamPassPercent")//考试合格
                    {
                        if (record.ExamId != null)
                        {
                            if (await Db.Queryable<Ghre_ExamRecord>().Where(x => x.StudyRecordId == record.Id && x.IsPass == true && x.Status == "ExamEnd").AnyAsync())
                                creditPoint.CreditPoints = ((courseCreditPoints * creditRule.ExamPassPercent) / 100).ObjToInt();
                        }
                    }
                    else if (creditRule.RuleType == "ScoreRanges")//分数段
                    {
                        var scoreRanges = JsonHelper.JsonToObj<List<CreditRuleScoreRange>>(creditRule.ScoreRange);

                        if (record.ExamId != null)
                        {
                            var examRecord = await Db.Queryable<Ghre_ExamRecord>().Where(x => x.StudyRecordId == record.Id && x.ScoreStatus == "HasScore" && x.IsPass == true && x.Status == "ExamEnd").FirstAsync();
                            if (examRecord != null && examRecord.Score > 0)
                            {
                                var exam = await Db.Queryable<Ghre_Exam>().Where(x => x.Id == examRecord.ExamId).FirstAsync();

                                if (exam != null)
                                {
                                    var examPaper = await Db.Queryable<Ghre_ExamPaper>().Where(x => x.Id == examRecord.ExamId).FirstAsync();
                                    if (examPaper != null)
                                    {

                                        var percent = (examRecord.Score / examPaper.TotalScore) * 100;

                                        percent = scoreRanges.Where(x => x.StartScore > percent && x.EndScore <= percent).Select(x => x.Credit).FirstOrDefault();

                                        if (percent != null)
                                            creditPoint.CreditPoints = ((courseCreditPoints * percent) / 100).ObjToInt();

                                    }
                                }
                            }
                        }
                    }

                    if (creditPoint.CreditPoints > 0)
                        creditPoints.Add(creditPoint);
                }
            }
        }

        await Db.Insertable(creditPoints).ExecuteReturnSnowflakeIdListAsync();
        await Db.Updateable(records)
            .UpdateColumns(it => new { it.IsIssueCredit }, true)
            .ExecuteCommandAsync();
        return ServiceResult.OprateSuccess("发放成功！");
    }
    #endregion

    #region 自动刷新完成状态
    /// <summary>
    /// 自动刷新完成状态
    /// </summary>
    /// <returns></returns>
    public async Task<ServiceResult> MarkCompleteStatus()
    {
        var now = DateTime.Now;
        //抓取当天提交考试的数据
        var records = await Db.Queryable<Ghre_StudyRecord>()
            .Where(x => x.ReverseI1 == 1)
            .ToListAsync();
        _logger.LogInformation($"【自动刷新完成状态】查询到{records.Count}条考试数据");
        if (!records.Any())
            return ServiceResult.OprateSuccess("自动刷新完成状态！");


        for (int i = 0; i < records.Count; i++)
        {
            await ExamHelper.MarkCompleteStatusAsync(Db, records[i]);
        }

        return ServiceResult.OprateSuccess("自动刷新完成状态！");
    }
    #endregion
}