using Serilog;
using static Tiobon.Core.Model.Consts;

namespace Tiobon.Core.Services;

/// <summary>
/// 培训需求 (服务)
/// </summary>
public class Ghre_RequestServices : BaseServices<Ghre_Request, Ghre_RequestDto, InsertGhre_RequestInput, EditGhre_RequestInput>, IGhre_RequestServices
{
    private readonly IBaseRepository<Ghre_Request> _dal;
    public Ghre_RequestServices(ICaching caching, IBaseRepository<Ghre_Request> dal)
    {
        this._dal = dal;
        base.BaseDal = dal;
        base._caching = caching;
    }

    public override async Task<ServicePageResult<Ghre_RequestDto>> QueryFilterPage(QueryBody filter, string condition, bool? IsEnable = true)
    {

        var sql = @"UPDATE A
SET A.CourseName = B.CourseName
FROM Ghre_Request A
     JOIN Ghre_Course B
        ON     A.CourseId = B.Id AND (A.CourseName ! = B.CourseName OR A.CourseName IS NULL)";
        await Db.Ado.ExecuteCommandAsync(sql);

        var result = await base.QueryFilterPage(filter, condition, IsEnable);
        //var courseIds = result.result.DT_TableDataT1.Where(x => x.CourseId != null).Select(x => x.CourseId).Distinct().ToList();
        //var courses = await Db.Queryable<Ghre_Course>().Where(x => courseIds.Contains(x.Id)).ToListAsync();
        var deptIds = result.result.DT_TableDataT1.Where(x => x.DeptId != null).Select(x => x.DeptId).Distinct().ToList();
        var depts = await Db.Queryable<Ghro_Dept>().Where(x => deptIds.Contains(x.DeptID)).ToListAsync();

        var sponsorIds = result.result.DT_TableDataT1.Where(x => x.SponsorId != null).Select(x => x.SponsorId).Distinct().ToList();
        var userIds = result.result.DT_TableDataT1.Where(x => x.RefuseUserId != null).Select(x => x.RefuseUserId).Distinct().ToList();
        userIds.AddRange(result.result.DT_TableDataT1.Where(x => x.AgreeUserId != null).Select(x => x.AgreeUserId).Distinct());
        result.result.DT_TableDataT1.ForEach(x =>
        {
            string trainStaffId = x.TrainStaffId;
            if (!string.IsNullOrWhiteSpace(trainStaffId))
            {
                x.TrainStaffIds = JsonHelper.JsonToObj<List<int>>(trainStaffId);
                var TrainStaffIds = JsonHelper.JsonToObj<List<int?>>(trainStaffId);
                sponsorIds.AddRange(TrainStaffIds);
            }


        });
        sponsorIds = sponsorIds.Distinct().ToList();
        var staffs = await Db.Queryable<Ghra_Staff>().Where(x => sponsorIds.Contains(x.StaffID)).ToListAsync();
        var users = await Db.Queryable<Ghrs_User>().Where(x => userIds.Contains(x.UserId)).ToListAsync();
        result.result.DT_TableDataT1.ForEach(async x =>
        {
            x.CourseSourceLabel = await GetParaLabel("TrainingRequestCourseSource", x.CourseSource);
            x.RequestSourceLabel = await GetParaLabel("TrainingRequestRequestSource", x.RequestSource);
            x.TrainClassLabel = await GetParaLabel("TrainingRequestTrainClass", x.TrainClass);
            x.TrainLevelLabel = await GetParaLabel("TrainingRequestTrainLevel", x.TrainLevel);
            x.InOrOutLabel = await GetParaLabel("CourseInOrOut", x.InOrOut);
            x.TeacherClassLabel = await GetParaLabel("TrainingTeacherType", x.InOrOut);
            x.TrainCategory = await GetParaLabel("TrainingCategory", x.TrainCategory);

            //if (x.CourseId != null)
            //    x.CourseName = courses.Where(o => x.CourseId == o.Id).FirstOrDefault()?.CourseName;

            if (x.DeptId != null)
            {
                x.DeptName = depts.Where(o => x.DeptId == o.DeptID).FirstOrDefault()?.DeptName;
                x.DeptNo = depts.Where(o => x.DeptId == o.DeptID).FirstOrDefault()?.DeptNo;

            }

            if (x.SponsorId != null)
                x.SponsorName = staffs.Where(o => x.SponsorId == o.StaffID).FirstOrDefault()?.StaffName;
            if (x.TrainStaffIds.IsNotEmptyOrNull())
                x.TrainStaffNames = string.Join("、", staffs.Where(o => x.TrainStaffIds.Contains(o.StaffID)).Select(o => o.StaffName));

            if (x.AgreeUserId != null)
                x.AgreeUserName = users.Where(o => x.AgreeUserId == o.UserId).FirstOrDefault()?.UserName;


            if (x.RefuseUserId != null)
                x.RefuseUserName = users.Where(o => x.RefuseUserId == o.UserId).FirstOrDefault()?.UserName;

            if (x.WorkState.IsNotEmptyOrNull())
            {
                if (x.WorkState == 0) x.WorkStateLabel = "审批中";
                if (x.WorkState == 1) x.WorkStateLabel = "审批通过";
            }

            if (x.RequestNum.IsNotEmptyOrNull() && x.RequestNum > 0)
                if (x.TrainDays.IsNotEmptyOrNull() && x.TrainDays > 0)
                {
                    var TotalTrainDays = x.TrainDays * x.RequestNum;
                    x.TotalTrainDays = StringHelper.TrimDecimalString(TotalTrainDays);
                }
            x.BuiltInLabel = x.BuiltIn == 1 ? "是" : "否";
        });
        return result;

    }

    public override async Task<long> Add(InsertGhre_RequestInput entity)
    {
        entity.SponsorId = GetStaffId();
        if (entity.TrainStaffIds.IsNotEmptyOrNull())
            entity.TrainStaffId = JsonHelper.ObjToJson(entity.TrainStaffIds);
        entity.RequestNo = await GenerateContinuousSequence("Ghre_Request", "RequestNo", "R");
        if (entity.RequestSource != "Dept")
            entity.RequestNum = null;

        if (entity.RequestSource == "Dept")
        {
            if (await QueryCompanyCode() == "Ushio")
            {
                if (entity.TrainStaffIds.Any() && entity.TrainStaffIds.Count != entity.RequestNum)
                    throw new Exception("培训对象数量须和需求人数保持一致！");
            }
            else
            {
                if (entity.TrainStaffIds.Count != entity.RequestNum)
                    throw new Exception("培训对象数量须和需求人数保持一致！");
            }
        }
        else
        {

            entity.RequestNum = 1;
            entity.TrainStaffId = $"[{entity.ApplicantId}]";
        }
        var id = await base.Add(entity);

        var sql = $"SELECT ISNULL(MAX(id)+1,1) FROM Ghre_Request WHERE Id !='{id}'";
        var id1 = await Db.Ado.GetLongAsync(sql);
        sql = $"UPDATE Ghre_Request SET Id={id1} WHERE  Id ='{id}'";
        await Db.Ado.ExecuteCommandAsync(sql);
        return id1;
    }

    public override async Task<bool> Update(long Id, EditGhre_RequestInput entity)
    {

        if (entity.TrainStaffIds.IsNotEmptyOrNull())
            entity.TrainStaffId = JsonHelper.ObjToJson(entity.TrainStaffIds);
        else entity.TrainStaffId = null;
        if (entity.RequestSource == "Dept")
        {
            if (await QueryCompanyCode() == "Ushio")
            {
                if (entity.TrainStaffIds.Any() && entity.TrainStaffIds.Count != entity.RequestNum)
                    throw new Exception("培训对象数量须和需求人数保持一致！");
            }
            else
            {
                if (entity.TrainStaffIds.Count != entity.RequestNum)
                    throw new Exception("培训对象数量须和需求人数保持一致！");
            }
        }
        else
        {
            entity.RequestNum = 1;
            entity.TrainStaffId = $"[{entity.ApplicantId}]";
        }
        return await base.Update(Id, entity, null, ["Status"]);
    }
    public async Task<ServiceResult<long>> InsertByStatus(InsertGhre_RequestInput insertModel, string status)
    {
        var data = ServiceResult<long>.OprateSuccess("新增成功", 0);
        insertModel.Status = status;
        var id = await Add(insertModel);

        data.Success = id > 0;
        if (data.Success)
            data.Data = id;
        else
            return ServiceResult<long>.OprateFailed("发布成功！");

        return data;
    }

    public override async Task<ServiceFormResult<Ghre_RequestDto>> QueryForm(QueryForm body)
    {
        var result = await base.QueryForm(body);
        string trainStaffId = result.result.DT_TableDataT1[0].TrainStaffId;
        if (!string.IsNullOrWhiteSpace(trainStaffId))
            result.result.DT_TableDataT1[0].TrainStaffIds = JsonHelper.JsonToObj<List<int>>(trainStaffId);
        else result.result.DT_TableDataT1[0].TrainStaffIds = new List<int>();
        return result;

    }

    public async Task<ServiceResult> UpdateStatus(InsertGhre_RequestInput input, string status)
    {

        HttpRequest request = UserContext.Context.Request;
        var api = request.Path.ObjToString().TrimEnd('/').ToLower();
        var ip = GetUserIp(UserContext.Context);

        var entities = new List<Ghre_Request>();
        foreach (var id in input.Ids)
        {
            if (!BaseDal.Any(id))
                continue;

            var entity = await BaseDal.QueryById(id);


            switch (status)
            {
                case DIC_REQUEST_STATUS.Active:
                    entity.AgreeReason = input.Reason;
                    entity.AgreeTime = DateTime.Now;
                    entity.AgreeUserId = App.User.ID;
                    break;
                case DIC_REQUEST_STATUS.Temporary:
                    entity.RefuseReason = input.Reason;
                    entity.RefuseTime = DateTime.Now;
                    entity.RefuseUserId = App.User.ID;
                    break;
            }

            entity.UpdateIP = ip;
            entity.UpdateProg = api;
            entity.Status = status;
            entities.Add(entity);
        }

        var result = await BaseDal.Update(entities);
        return ServiceResult.OprateSuccess("执行成功！");
        //if (status == Consts.DIC_COURSE_STATUS.RELEASED)
        //    return ServiceResult.OprateSuccess("发布成功！");
        //else if (status == Consts.DIC_COURSE_STATUS.DRAFT)
        //    return ServiceResult.OprateSuccess("已启用成功，请进入草稿箱查看！");
        //else
        //    return ServiceResult.OprateSuccess("停用成功！");

    }

    public async Task<ServicePageResult<Ghre_RequestDto>> QueryGroup(QueryBody filter, string type)
    {
        if (string.IsNullOrWhiteSpace(filter.orderBy))
            filter.orderBy = "DeptName ASC";

        if (filter.pageSize == 0)
            filter.pageSize = 10000;
        string conditions = "WHERE 1=1 ";

        foreach (JProperty jProperty in filter.jsonParam.Properties())
        {
            var name = jProperty.Name;
            var value = jProperty.Value.ToString();
            if (name == "page" || name == "pageSize")
                continue;
            if (name == "YearMonth")
            {
                if (value != null)
                {
                    var jsonParam = JsonHelper.JsonToObj<JsonParam>(value);
                    var ids1 = JsonHelper.JsonToObj<List<string>>(jsonParam.columnValue.ToString());

                    conditions += $" AND {name}>= '{ids1[0]}-01'";
                    conditions += $" AND {name}<= '{ids1[1]}-01'";
                }
                continue;
            }
            if (name == "Year")
            {
                if (value != null)
                {
                    var jsonParam = JsonHelper.JsonToObj<JsonParam>(value);
                    var ids1 = JsonHelper.JsonToObj<List<string>>(jsonParam.columnValue.ToString());

                    conditions += $" AND {name}>= '{ids1[0]}'";
                    conditions += $" AND {name}<= '{ids1[1]}'";
                }
                continue;
            }
            if (!string.IsNullOrWhiteSpace(value))
                conditions = DealConditions(conditions, name, value);
        }

        string sql = @$"SELECT *
                            FROM (SELECT sum (RequestNum) RequestNum,
                                         sum (TotalBudget) TotalBudget,
                                         CourseName,
                                         YearMonth1 YearMonthLabel,
                                         DeptName,
                                         TrainClass,
                                         TrainCategory,
                                         TrainLevel,
                                         InOrOut
                                  FROM (SELECT A.Id,
                                               A.CourseName,
                                               SUBSTRING (A.YearMonth, 1, 4) + '年' YearMonth1,
                                               -- CAST (A.YearMonth + '-01' AS DATE)  YearMonthDate,
                                               CONVERT (INT, SUBSTRING (A.YearMonth, 1, 4)) Year,
                                               ISNULL (B.DeptName, D.DeptName) DeptName,
                                               ISNULL (B.DeptId, D.DeptId) DeptId,
                                               ISNULL (A.RequestNum, 1) RequestNum,
                                               A.TrainClass,
                                               A.TrainCategory,
                                               A.CourseSource,
                                               A.RequestSource,
                                               TrainLevel,
                                               A.InOrOut,
                                               ISNULL (A.TotalBudget, 0) TotalBudget
                                        FROM Ghre_Request A
                                             LEFT JOIN Ghro_Dept B ON A.DeptId = B.DeptID
                                             LEFT JOIN Ghra_Staff C ON A.ApplicantId = C.StaffID
                                             LEFT JOIN Ghro_Dept D ON C.DeptID = D.DeptID
                                        WHERE A.IsEnable = 1 AND dbo.FUserDataBelongPriv ({App.User.ID}, A.DataBelongID, NULL) = 1) A {conditions}
                                  GROUP BY CourseName,
                                           YearMonth1,
                                           DeptName,
                                           TrainClass,
                                           TrainCategory,
                                           TrainLevel,
                                           InOrOut) A
                        ORDER BY {filter.orderBy}";

        if (type == "Month")
            sql = @$"SELECT *
                        FROM (SELECT sum (RequestNum) RequestNum,
                                     sum (TotalBudget) TotalBudget,
                                     CourseName,
                                     YearMonth1 YearMonthLabel,
                                     DeptName,
                                     TrainClass, 
                                     TrainCategory, 
                                     TrainLevel,
                                     InOrOut
                              FROM (SELECT A.Id,
                                           A.CourseName,
                                             SUBSTRING (A.YearMonth, 1, 4)
                                           + '年'
                                           + SUBSTRING (A.YearMonth, 6, 2)
                                           + '月' YearMonth1,
                                           CAST (A.YearMonth + '-01' AS DATE) YearMonth,
                                           ISNULL (B.DeptName, D.DeptName) DeptName,
                                           ISNULL (B.DeptId, D.DeptId) DeptId,
                                           ISNULL (A.RequestNum, 1) RequestNum,
                                           A.TrainClass,
                                           A.TrainCategory,
                                           A.CourseSource,
                                           TrainLevel,
                                           A.RequestSource,
                                           A.InOrOut,
                                           ISNULL (A.TotalBudget, 0) TotalBudget
                                    FROM Ghre_Request A
                                         LEFT JOIN Ghro_Dept B ON A.DeptId = B.DeptID
                                         LEFT JOIN Ghra_Staff C ON A.ApplicantId = C.StaffID
                                         LEFT JOIN Ghro_Dept D ON C.DeptID = D.DeptID
                                    WHERE A.IsEnable = 1 AND dbo.FUserDataBelongPriv ({App.User.ID}, A.DataBelongID, NULL) = 1) A {conditions}
                              GROUP BY CourseName,
                                       YearMonth1,
                                       DeptName,
                                       TrainClass,
                                       TrainCategory,
                                       TrainLevel,
                                       InOrOut) A
                        ORDER BY {filter.orderBy}";
        var result = await Db.Ado.SqlQueryAsync<Ghre_RequestDto>(sql);

        result.ForEach(async x =>
        {
            x.TrainClassLabel = await GetParaLabel("TrainingRequestTrainClass", x.TrainClass);
            x.TrainCategory = await GetParaLabel("TrainingCategory", x.TrainCategory);
            x.TrainLevelLabel = await GetParaLabel("TrainingRequestTrainLevel", x.TrainLevel);
            x.InOrOutLabel = await GetParaLabel("CourseInOrOut", x.InOrOut);
            x.TeacherClassLabel = await GetParaLabel("TrainingTeacherType", x.InOrOut);

        });
        //return ServiceResult<List<>>.OprateSuccess("查询成功", result);
        return new ServicePageResult<Ghre_RequestDto>(filter.pageNum, result.Count, filter.pageSize, result);


    }

    #region Excel导入

    public async Task<(List<Dictionary<string, object>>, int)> ValidImportExcel(ISqlSugarClient Db, List<QueryExportColumn> columns, DataTable dt)
    {
        var CompanyCode = await QueryCompanyCode();
        Type entityType = typeof(Ghre_Request);
        var properties = entityType.GetGenericProperties();
        int ErrorCount = 0;
        var dictList = new List<Dictionary<string, object>>();
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            var dict = ReportHelper.GetDefaultDict();
            var comments = new List<string>();
            for (int j = 0; j < columns.Count; j++)
            {
                var x = columns[j];
                if (!dt.Columns.Contains(x.label))
                    comments.Add("未查询到【" + x.label + "】列！");
                else
                {
                    var value = dt.Rows[i][x.label].ToString();
                    var courseSource = dt.Rows[i]["课程来源"].ToString();

                    if (x.label == "需求来源" && value == "部门需求")
                    {

                        var RequestNum = dt.Rows[i]["需求人数"].ObjToInt();
                        var TrainStaffIds1 = dt.Rows[i]["培训对象"].ToString();
                        TrainStaffIds1 = TrainStaffIds1.Replace("，", ",");
                        TrainStaffIds1 = TrainStaffIds1.Replace("；", ",");
                        TrainStaffIds1 = TrainStaffIds1.Replace(";", ",");
                        var value1 = value.Split(',').ToList();
                        if (CompanyCode == "Ushio")
                        {
                            if (value1.Any() && value1.Count != RequestNum)
                                throw new Exception("培训对象数量须和需求人数保持一致！！");
                        }
                        else
                        {
                            if (value1.Count != RequestNum)
                                throw new Exception("培训对象数量须和需求人数保持一致！！");
                        }

                    }

                    if (x.label == "需求课程" || x.label == "新增课程")
                    {

                        if (x.label == "需求课程" && courseSource == "已有课程" && value.IsNullOrEmpty())
                        {
                            comments.Add(x.label + "不能为空！");
                            dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                        }
                        else if (x.label == "新增课程" && courseSource == "新增课程" && value.IsNullOrEmpty())
                        {
                            comments.Add(x.label + "不能为空！");
                            dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                        }
                    }
                    else
                    if (x.required == "true" && value.IsNullOrEmpty())
                    {
                        comments.Add(x.label + "不能为空！");
                        dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                    }

                    if (x.dataSourceType.IsNullOrEmpty() && value.IsNotEmptyOrNull())
                    {
                        if (x.dataType == "int" || x.dataType == "decimal")
                        {
                            try
                            {
                                Convert.ToDecimal(value);
                            }
                            catch (Exception)
                            {
                                comments.Add(x.label + "无效的数字类型！");
                            }
                        }
                        else if (x.dataType == "date")
                        {
                            try
                            {
                                Convert.ToDateTime(value);
                            }
                            catch (Exception)
                            {
                                comments.Add(x.label + "无效的日期类型！");
                            }
                        }
                    }

                    if (value.IsNotEmptyOrNull())
                    {
                        if (x.field == "TrainStaffIds")
                        {
                            value = value.Replace("，", ",");
                            value = value.Replace("；", ",");
                            value = value.Replace(";", ",");
                            var value1 = value.Split(',').ToList();
                            var ids = await Db.Queryable<Ghra_Staff>().Where(o => value1.Contains(o.StaffName) || value1.Contains(o.StaffNo) || value1.Contains(o.StaffEname)).Select(x => x.StaffID).ToListAsync();
                            dict.Add("TrainStaffId", JsonHelper.ObjToJson(ids));
                        }
                        else
                        {
                            if (x.elementType == "Switch")
                                value = value == "是" ? "true" : "false";
                            if (x.dataSourceId.IsNotEmptyOrNull() && x.dataSourceType.IsNotEmptyOrNull() && !x.dataSource.StartsWith("OrgTreeWith")
                             && !x.dataSource.StartsWith("StaffWith"))
                            {

                                if (x.dataSourceType == "CommonList")
                                {
                                    var commonSql = await Db.Queryable<Ghrs_ListCommonSql>().Where(o => o.ListCommonSqlId == x.dataSourceId).FirstAsync();

                                    if (commonSql != null)
                                    {
                                        string sql = @$"SELECT [value]
                                FROM ({commonSql.SelectSql}) A
                                WHERE label = '{value}'";
                                        sql = sql.Replace("{@LangID}", "1");
                                        sql = sql.Replace("{@UserID}", App.User.ID.ObjToString());
                                        sql = sql.Replace("{@KeyWords}", null);
                                        var id2 = await Db.Ado.GetLongAsync(sql);
                                        if (properties.Any(o => o.Name == x.field))
                                            dict.Add(x.field, id2);
                                    }
                                }
                                else if (x.dataSourceType == "ParaDetailNo")
                                {
                                    var sql = @$"SELECT ParaDetailNo
                                FROM Ghrs_ParaDetail
                                WHERE     ParaMasterId IN (SELECT ParaMasterId
                                                           FROM Ghrs_ParaMaster
                                                           WHERE ParaMasterId = {x.dataSourceId.ObjToInt()})
                                      AND IsEnable = 1
                                      AND ParaDetailName = '{value}'";
                                    var id2 = await Db.Ado.GetStringAsync(sql);

                                    if (properties.Any(o => o.Name == x.field))
                                        dict.Add(x.field, id2);
                                }
                            }
                            else if (x.dataSource == "OrgTreeWithPriv")
                            {
                                string sql = @$"SELECT DeptID FROM Ghro_Dept WHERE DeptName = '{value}' OR DeptNo = '{value}' OR DeptEname = '{value}'";
                                var id2 = await Db.Ado.GetLongAsync(sql);
                                if (properties.Any(o => o.Name == x.field))
                                    dict.Add(x.field, id2);
                            }
                            else if (x.dataSource == "StaffWithoutPriv")
                            {
                                string sql = @$"SELECT StaffID FROM Ghra_Staff WHERE StaffName = '{value}' OR StaffNo = '{value}' OR StaffEname = '{value}'";
                                var id2 = await Db.Ado.GetLongAsync(sql);
                                if (properties.Any(o => o.Name == x.field))
                                    dict.Add(x.field, id2);
                            }
                            else
                            {
                                if (properties.Any(o => o.Name == x.field))
                                    dict.Add(x.field, value);

                            }
                        }
                    }
                }
            }
            if (comments.Any())
            {
                dt.Rows[i]["Comments"] = string.Join(";", comments.Select(a => a));
                ErrorCount++;
                continue;
            }
            else
                dictList.Add(dict);
        }

        return (dictList, ErrorCount);
    }
    public override async Task<ServiceResult<ExcelData>> ImportExcel(IFormFile file, string menuName = null, long? MasterId = null)
    {
        var data = new ExcelData();
        var (path, filepath) = await ReportHelper.GetImportFilePath(file, menuName);
        var id1 = SnowFlakeSingle.instance.getID();
        string errorFileName = path + SnowFlakeSingle.instance.getID() + FileHelper.GetPostfixStr(filepath);

        var dt = ReportHelper.ReadImportExcel(filepath);
        var columns = await QueryExportColumn(menuName);

        var (dictList, errorCount) = await ValidImportExcel(Db, columns, dt);
        Type entityType = typeof(Ghre_Request);
        var properties = entityType.GetGenericProperties();
        if (errorCount > 0)
        {
            NPOIHelper.ExportExcel(dt, null, "导入数据", FileHelper.GetPhysicsPath() + errorFileName);
            data.filePath = "/Advanced" + errorFileName;
            data.ErrorCount = errorCount;
        }
        else
        {
            await Db.Insertable(dictList).AS(entityType.GetEntityTableName()).ExecuteCommandAsync();

            data.SuccessCount = dictList.Count;
        }

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


    #region 牛尾培训需求同步
    public async Task Ushio_Sync()
    {
        Log.Information($"【牛尾培训需求同步】开始同步");
        try
        {


            string sql = @"SELECT *, TrainStaffId TrainStaffId1, OutSideOrg SchoolId
                            FROM [120.26.205.42].[GhrUshio].[dbo].Ghrz_Ushio_TrainRequestApply_GHR50_V
                            WHERE     RequestNo NOT IN (SELECT RequestNo
                                                        FROM Ghre_Request
                                                        WHERE IsEnable = 1)
                                  AND EnableYN = 'Y'";

            var dt = await Db.Ado.GetDataTableAsync(sql);

            var list = Db.Utilities.DataTableToList<Ghre_RequestDto>(dt);

            Log.Information($"【牛尾培训需求同步】查询到待同步{list.Count}条数据");
            for (int i = 0; i < list.Count; i++)
            {
                Log.Information($"【牛尾培训需求同步】同步队列{i + 1}/{list.Count}");

                var insert = Mapper.Map(list[i]).ToANew<InsertGhre_RequestInput>();

                if (await base.AnyAsync(x => x.RequestNo == insert.RequestNo))
                    continue;
                if (list[i].DeptNo.IsNotEmptyOrNull())
                    insert.DeptId = (await Db.Queryable<Ghro_Dept>().Where(x => x.DeptNo == list[i].DeptNo).FirstAsync())?.DeptID;

                if (list[i].SponsorNo.IsNotEmptyOrNull())
                    insert.SponsorId = (await Db.Queryable<Ghra_Staff>().Where(x => x.StaffNo == list[i].SponsorNo).FirstAsync())?.StaffID;
                if (list[i].TrainStaffId1.IsNotEmptyOrNull())
                {
                    var staffNos = list[i].TrainStaffId1.Split(',').ToList();

                    if (staffNos.Any())
                    {
                        var staffIds = await Db.Queryable<Ghra_Staff>().Where(x => staffNos.Contains(x.StaffNo)).Select(x => x.StaffID).ToListAsync();
                        insert.TrainStaffId = JsonHelper.ObjToJson(staffIds);
                    }
                }

                insert.WorkNo = insert.RequestNo;

                if (insert.CourseId == 0) insert.CourseId = null;

                #region 根据参数 处理数据默认状态
                var config = await Db.Queryable<Ghre_Config>().FirstAsync(x => x.ConfigCode == "ESS_Request_Apply_Status");
                if (config != null)
                    insert.Status = config.ConfigValue;

                #endregion
                var inserts = new List<InsertGhre_RequestInput>();
                var yearMonths = list[i].YearMonth.Split(',').ToList();
                if (yearMonths.Count > 1)
                {
                    yearMonths.ForEach(x =>
                    {
                        var insert1 = Mapper.Map(insert).ToANew<InsertGhre_RequestInput>();
                        insert1.YearMonth = x;
                        inserts.Add(insert1);
                    });
                    await base.Add(inserts);
                }
                else
                    await base.Add(insert);

            }

            Log.Information($"【牛尾培训需求同步】查询到待同步{list.Count}条作废数据");
            sql = @"SELECT *, TrainStaffId TrainStaffId1
                            FROM [120.26.205.42].[GhrUshio].[dbo].Ghrz_Ushio_TrainRequestApply_GHR50_V
                            WHERE     RequestNo IN (SELECT RequestNo
                                                        FROM Ghre_Request
                                                        WHERE IsEnable = 1)
                                  AND EnableYN = 'N'";

            dt = await Db.Ado.GetDataTableAsync(sql);

            list = Db.Utilities.DataTableToList<Ghre_RequestDto>(dt);

            Log.Information($"【牛尾培训需求同步】查询到待同步{list.Count}条数据");
            for (int i = 0; i < list.Count; i++)
            {
                Log.Information($"【牛尾培训需求同步】同步队列{i + 1}/{list.Count}");

                await Db.Updateable<Ghre_Request>()
                    .SetColumns(it => new Ghre_Request() { IsEnable = 0 })
                    .Where(it => it.RequestNo == list[i].RequestNo)
                    .ExecuteCommandAsync();
            }

            #region 同步需求数据
            sql = @"INSERT INTO [120.26.205.42].[GhrUshio].[dbo].Ghre_GHR50Request (
               RequestID,
               RequestSource,
               DeptName,
               StaffName,
               YearMonth,
               CourseID,
               CourseName,
               TrainDays,
               RequestNum,
               IsEnable,
               CreateBy,
               CreateDate,
               CreateProg,
               DeptNo,
               StaffNo,
               LastUpdateDate,TrainStaffId,TrainClass,InOrOut)
   SELECT A.Id,
          A.RequestSource,
          c.DeptName,
          D.StaffName,
          A.YearMonth,
          A.CourseId,
          isnull (A.CourseName, e.CourseName) CourseName,
          A.TrainDays,
          A.RequestNum,
          A.IsEnable,
          A.CreateBy,
          A.CreateTime,
          '',
          c.DeptNo,
          d.StaffNo,
          isnull (A.UpdateTime, A.CreateTime),
    STUFF((
        SELECT ',' + S.StaffNo
        FROM OPENJSON(A.TrainStaffId) WITH (TrainStaffId INT '$') AS JsonData
        INNER JOIN Ghra_Staff S ON JsonData.TrainStaffId = S.StaffID
        FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS StaffNames,A.TrainClass,A.InOrOut
   FROM Ghre_Request A
        LEFT JOIN [120.26.205.42].[GhrUshio].[dbo].Ghre_GHR50Request B
           ON B.RequestID = A.Id
        LEFT JOIN Ghro_Dept C ON a.DeptId = c.DeptID
        LEFT JOIN Ghra_Staff D ON a.ApplicantId = D.StaffID
        LEFT JOIN Ghre_Course E ON a.CourseId = E.Id
   WHERE  A.TrainClass='Temporary' AND A.WorkNo IS NULL AND B.RequestID IS NULL;
delete from [120.26.205.42].[GhrUshio].[dbo].Ghre_GHR50Plan;
INSERT INTO [120.26.205.42].[GhrUshio].[dbo].Ghre_GHR50Plan (PlanID,
                                                             IsEnable,
                                                             CreateBy,
                                                             CreateDate,
                                                             LastUpdateDate,
                                                             CreateProg,
                                                             DeptNo,    --部门编号
                                                             DeptName,  --部门名称
                                                             TrainYear,   --年份
                                                             TrainMonth, --计划实施月份
                                                             CourseID,  --课程ID
                                                             CourseName, --课程名称
                                                             TrainDays, --培训天数
                                                             TrainStaffId, --培训对象 工号拼接
                                                             TrainNum,   --培训人数
InorOut )
   SELECT A.Id,
          1,
          A.CreateBy,
          getdate(),
          getdate(),
          '',
          C.DeptNo,
          C.DeptName,
         A.[Year],
       A.Month, 
       A.CourseId,
          ISNULL (E.CourseName, A.CourseName),
          A.TrainDays,
    STUFF((
        SELECT ',' + S.StaffNo
        FROM OPENJSON(A.StaffIds) WITH (TrainStaffId INT '$') AS JsonData
        INNER JOIN Ghra_Staff S ON JsonData.TrainStaffId = S.StaffID
        FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS StaffNames,
          A.TrainNum,A.InorOut
   FROM Ghre_Plan A
        LEFT JOIN [120.26.205.42].[GhrUshio].[dbo].Ghre_GHR50Plan B
           ON B.PlanID = A.Id
        LEFT JOIN Ghro_Dept C ON a.DeptId = c.DeptID
        LEFT JOIN Ghre_Course E ON a.CourseId = E.Id
   WHERE A.IsEnable = 1 and (A.Status ='Active' OR A.Status ='Wait') AND B.PlanID IS NULL;
UPDATE A
SET A.IsEnable = B.IsEnable,A.LastUpdateDate=isnull (B.UpdateTime, B.CreateTime)
FROM [120.26.205.42].[GhrUshio].[dbo].Ghre_GHR50Request A
     JOIN Ghre_Request B ON a.RequestID = B.Id
WHERE    B.IsEnable ! = A.IsEnable
      OR isnull (B.UpdateTime, B.CreateTime) ! = A.LastUpdateDate;

UPDATE A
SET A.IsEnable = B.IsEnable,A.LastUpdateDate=isnull (B.UpdateTime, B.CreateTime)
FROM [120.26.205.42].[GhrUshio].[dbo].Ghre_GHR50Plan A
     JOIN Ghre_Plan B ON a.PlanID = B.Id
WHERE    B.IsEnable ! = A.IsEnable
      OR isnull (B.UpdateTime, B.CreateTime) ! = A.LastUpdateDate";
            await Db.Ado.ExecuteCommandAsync(sql);

            sql = @"INSERT INTO [120.26.205.42].[GhrUshio].[dbo].Ghre_Course (CourseNo,
                                                          CourseName,
                                                          CreateDate,
                                                          EnableYN,
                                                          CompanyID,
                                                          SubCompanyID,
                                                          CreateBy,
                                                          CreateProg,
                                                          IsDefault,
                                                          Reverse1)
   SELECT A.CourseNo,
          A.CourseName,
          getdate (),
          'Y',
          0,
          0,
          0,
          '',
          0,
          A.Id
   FROM Ghre_Course A
        LEFT JOIN [120.26.205.42].[GhrUshio].[dbo].Ghre_Course B
           ON B.Reverse1 = A.Id
   WHERE A.IsEnable = 1 AND B.Reverse1 IS NULL;

INSERT INTO [120.26.205.42].[GhrUshio].[dbo].Ghre_Course (CourseNo,
                                                          CourseName,
                                                          CreateDate,
                                                          EnableYN,
                                                          CompanyID,
                                                          SubCompanyID,
                                                          CreateBy,
                                                          CreateProg,
                                                          IsDefault,
                                                          Reverse1)
   SELECT A.SceneNo,
          STUFF
          (
             (SELECT ', ' + CourseName
              FROM Ghre_Course
              WHERE    CourseSceneIds LIKE '%' + CAST (A.Id AS VARCHAR) + '%'
                    OR CourseSceneId = A.Id
              FOR XML PATH(''), TYPE).value ('.', 'NVARCHAR(MAX)'),
             1,
             2,
             ''),
          getdate (),
          'Y',
          0,
          0,
          0,
          '',
          0,
          A.Id
   FROM Ghre_CourseScene A
        LEFT JOIN [120.26.205.42].[GhrUshio].[dbo].Ghre_Course B
           ON B.Reverse1 = A.Id
   WHERE A.IsEnable = 1 AND B.Reverse1 IS NULL;

UPDATE B
SET b.CourseNo = A.CourseNo, b.CourseName = A.CourseName
FROM Ghre_Course A
     JOIN [120.26.205.42].[GhrUshio].[dbo].Ghre_Course B ON B.Reverse1 = A.Id
WHERE b.CourseNo ! = A.CourseNo OR b.CourseName ! = A.CourseName;

UPDATE B
SET b.CourseNo = A.SceneNo, b.CourseName = A.CourseName
FROM (SELECT A.Id,
             A.SceneNo,
             STUFF
             (
                (SELECT ', ' + CourseName
                 FROM Ghre_Course
                 WHERE    CourseSceneIds LIKE
                             '%' + CAST (A.Id AS VARCHAR) + '%'
                       OR CourseSceneId = A.Id
                 FOR XML PATH(''), TYPE).value ('.', 'NVARCHAR(MAX)'),
                1,
                2,
                '') CourseName
      FROM Ghre_CourseScene A) A
     JOIN [120.26.205.42].[GhrUshio].[dbo].Ghre_Course B ON B.Reverse1 = A.Id
WHERE b.CourseNo ! = A.SceneNo OR b.CourseName ! = A.CourseName;";
            await Db.Ado.ExecuteCommandAsync(sql);
            sql = @"INSERT INTO [120.26.205.42].[GhrUshio].[dbo].[Ghre_StaffTraining ] (
               Reverse6,
               StaffId,
               CourseId,
               BeginDate,
               EndDate,
               CreateDate,
               EnableYN,
               CompanyID,
               SubCompanyID,
               CreateBy,
               CreateProg,
               IsDefault,
               Reverse1,
               Reverse2,
               Reverse3,
               ispass)
   SELECT A.Id,
          C.StaffId,
          D.CourseId,
          a.BeginTime,
          a.EndTime,
          getdate (),
          'Y',
          0,
          0,
          0,
          '',
          0,
          A.StandardHour,
          A.Score,
          A.CreditPoints,
          CASE A.IsPass WHEN 'true' THEN 'Y' WHEN 'false' THEN 'N' END IsPass
   FROM (SELECT CAST (A.Id AS VARCHAR) Id,
                a.StaffId,
                a.BeginTime,
                a.EndTime,
                CAST (isnull (CourseSceneId, CourseId) AS VARCHAR) CourseId1,
                StandardHour,
                CreditPoints,
                Score,
                IsPass
         FROM Ghre_StudyRecord_V A
         WHERE A.IsEnable = 1) A
        LEFT JOIN Ghra_Staff B ON a.StaffId = b.StaffID
        LEFT JOIN [120.26.205.42].[GhrUshio].[dbo].Ghra_Staff C
           ON C.StaffNo = b.StaffNo
        LEFT JOIN [120.26.205.42].[GhrUshio].[dbo].Ghre_Course D
           ON A.CourseId1 = D.Reverse1
        LEFT JOIN [120.26.205.42].[GhrUshio].[dbo].[Ghre_StaffTraining ] E
           ON E.Reverse6 = A.Id
   WHERE     a.BeginTime IS NOT NULL
         AND a.EndTime IS NOT NULL
         AND E.Reverse6 IS NULL";
            await Db.Ado.ExecuteCommandAsync(sql);


            sql = @"SELECT A.*
                    FROM [120.26.205.42].[GhrUshio].[dbo].Ghrz_Ushio_TravelReportApply_GHR50_V A
                         LEFT JOIN [120.26.205.42].[GhrUshio].[dbo].[Ghre_StaffTraining ] B
                            ON B.Reverse6 = cast (A.TravelReportApplyId AS VARCHAR (200)) where ExternalTrainApplyNo is not null";

            var dtReportApplys = await Db.Ado.GetDataTableAsync(sql);

            for (int i = 0; i < dtReportApplys.Rows.Count; i++)
            {
                var TravelReportApplyId = dtReportApplys.Rows[i]["TravelReportApplyId"].ObjToString();
                var staffNo = dtReportApplys.Rows[i]["StaffNo"].ObjToString();
                var ExternalTrainApplyNo = dtReportApplys.Rows[i]["ExternalTrainApplyNo"].ObjToString();
                var ExternalTrainApplyNoArray = ExternalTrainApplyNo.Split(',').ToList();

                var staffId = await Db.Ado.GetIntAsync($"select StaffId from [120.26.205.42].[GhrUshio].[dbo].ghra_staff where staffNo='{staffNo}'");


                for (int j = 0; j < ExternalTrainApplyNoArray.Count; j++)
                {
                    long? CourseId = null;
                    string BeginDate = string.Empty;
                    string EndDate = string.Empty;
                    string CourseName = string.Empty;
                    ExternalTrainApplyNo = ExternalTrainApplyNoArray[j];
                    if (ExternalTrainApplyNo.IsNullOrEmpty())
                        continue;

                    sql = @$" select * from [120.26.205.42].[GhrUshio].[dbo].Ghrz_Ushio_ExternalTrainApply 
                        where applyNo='{ExternalTrainApplyNo}'";
                    var dtExternalTrainApplyApplys = await Db.Ado.GetDataTableAsync(sql);
                    if (dtExternalTrainApplyApplys.Rows.Count > 0)
                    {
                        var TrainNeeds = dtExternalTrainApplyApplys.Rows[0]["TrainNeeds"].ObjToString();
                        BeginDate = dtExternalTrainApplyApplys.Rows[0]["BeginDate"].ObjToString();
                        EndDate = dtExternalTrainApplyApplys.Rows[0]["EndDate"].ObjToString();

                        if (TrainNeeds.Contains("*"))
                        {
                            TrainNeeds = TrainNeeds.Replace("*", null);
                            sql = @$"select * from [120.26.205.42].[GhrUshio].[dbo].Ghre_GHR50plan where  planID={TrainNeeds}";
                            var dtTrainRequestApplys = await Db.Ado.GetDataTableAsync(sql);
                            if (dtTrainRequestApplys.Rows.Count > 0)
                            {
                                CourseId = dtTrainRequestApplys.Rows[i]["CourseId"].ObjToLong();
                                CourseName = dtTrainRequestApplys.Rows[i]["CourseName"].ObjToString();
                                //var CourseSource = dtTrainRequestApplys.Rows[i]["CourseSource"].ObjToString();

                            }

                        }
                        else if (TrainNeeds.Contains("-"))
                        {
                            TrainNeeds = TrainNeeds.Replace("-", null);
                            CourseId = TrainNeeds.ObjToLong();
                        }
                        else
                        {
                            sql = @$"SELECT * FROM [120.26.205.42].[GhrUshio].[dbo].Ghrz_Ushio_TrainRequestApply WHERE WorkID = {TrainNeeds}";

                            var dtTrainRequestApplys = await Db.Ado.GetDataTableAsync(sql);
                            if (dtTrainRequestApplys.Rows.Count > 0)
                            {
                                CourseId = dtTrainRequestApplys.Rows[i]["CourseId"].ObjToLong();
                                CourseName = dtTrainRequestApplys.Rows[i]["CourseName"].ObjToString();
                                //var CourseSource = dtTrainRequestApplys.Rows[i]["CourseSource"].ObjToString();
                            }
                        }
                    }

                    if (CourseId == 0 || CourseId is null)
                    {
                        sql = @$"select CourseId from [120.26.205.42].[GhrUshio].[dbo].Ghre_Course 
                                        where courseName ='{CourseName}'";

                        CourseId = await Db.Ado.GetIntAsync(sql);
                        if (CourseId == 0)
                            await Db.Ado.ExecuteCommandAsync(@$"INSERT INTO [120.26.205.42].[GhrUshio].[dbo].Ghre_Course (CourseNo,
                                                          CourseName,
                                                          CreateDate,
                                                          EnableYN,
                                                          CompanyID,
                                                          SubCompanyID,
                                                          CreateBy,
                                                          CreateProg,
                                                          IsDefault,
                                                          Reverse1)
                                           SELECT '{CourseName}',
                                                  '{CourseName}',
                                                  getdate (),
                                                  'Y',
                                                  0,
                                                  0,
                                                  0,
                                                  '',
                                                  0,
                                                  NULL");

                    }

                    sql = @$"select CourseId from [120.26.205.42].[GhrUshio].[dbo].Ghre_Course  
                            where Reverse1='{CourseId}' or courseName ='{CourseName}'";
                    CourseId = await Db.Ado.GetIntAsync(sql);

                    if (CourseId != null)
                    {

                        sql = @$"INSERT INTO [120.26.205.42].[GhrUshio].[dbo].[Ghre_StaffTraining ] (
               Reverse6,
               StaffId,
               CourseId,
               BeginDate,
               EndDate,
               CreateDate,
               EnableYN,
               CompanyID,
               SubCompanyID,
               CreateBy,
               CreateProg,
               IsDefault,
               Reverse1,
               Reverse2,
               Reverse3,
               ispass)
   SELECT '{TravelReportApplyId}',
          {staffId} StaffId,
          {CourseId} CourseId,
          '{BeginDate}' BeginTime,
          '{EndDate}' EndTime,
          getdate (),
          'Y',
          0,
          0,
          0,
          '',
          0,
           0 StandardHour,
          0 Score,
         0  CreditPoints,
          'Y'";
                    }
                }
            }

            #endregion

        }
        catch (Exception E)
        {
            Log.Information($"【牛尾培训需求同步】发生错误：{E.Message}");
            Log.Information($"【牛尾培训需求同步】发生错误行：{E.StackTrace}");
        }
        Log.Information($"【牛尾培训需求同步】结束同步");
    }
    #endregion



    #region Excel导出
    public async Task<ServiceResult<ExcelData>> ExportGroupExcel(QueryExport body, string type)
    {
        QueryBody filter = new QueryBody();
        filter.pageNum = 1;
        filter.pageSize = 1000000;
        filter.jsonParam = body.jsonParam;
        filter.langId = body.langId;
        filter.menuName = body.menuName;

        var condition = "1=1";
        if (body.exportSet.SelectRowKeys != null && body.exportSet.SelectRowKeys.Any())
            condition += $" AND Id IN({string.Join(",", body.exportSet.SelectRowKeys)})";

        var data = await QueryGroup(filter, type);

        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 = DbAccess.QueryList<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 = $"{$"/files/export/{id}/"}";
        if (!Directory.Exists(physicsPath + path))
            Directory.CreateDirectory(physicsPath + path);

        path = path + body.exportSet.TitleName + ".xlsx";
        NPOIHelper.ExportExcel(dt, body.exportSet.TitleName, type == "Year" ? "培训需求统计-年度" : "培训需求统计-月度", physicsPath + path);

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

    public async Task<ServiceResult<ExcelData>> ExportExcel(QueryExport body, string status)
    {
        QueryBody filter = new QueryBody();
        filter.pageNum = 1;
        filter.jsonParam = body.jsonParam;
        filter.pageSize = 1000000;
        filter.langId = body.langId;

        var condition = "1=1";
        if (body.exportSet.SelectRowKeys != null && body.exportSet.SelectRowKeys.Any())
            condition += $" AND Id IN({string.Join(",", body.exportSet.SelectRowKeys)})";

        var data = new ServicePageResult<Ghre_RequestDto>(0, 0, filter.pageSize, null);

        if (status == "Active")
            data = await QueryFilterPage(filter, $"(Status ='Active' OR Status ='Wait' OR (WorkID IS NOT NULL AND WorkState IN (0,1)))");
        else if (status == "Disable")
            data = await QueryFilterPage(filter, null, false);
        else
            data = await QueryFilterPage(filter, $"Status ='{status}' AND WorkID IS NULL");

        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 = DbAccess.QueryList<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))
                {
                    var label = columns.FirstOrDefault(o => o.field == x)?.label;
                    if (!fieldDescs.ContainsKey(x))
                        fieldDescs.Add(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 = "/Advanced" + path;
        result.fileName = body.exportSet.TitleName + ".xlsx";
        return ServiceResult<ExcelData>.OprateSuccess("导出成功", result);
    }
    #endregion

}