using static Tiobon.Core.Model.Consts;

namespace Tiobon.Core.Services;

/// <summary>
/// 培训讲师异动 (服务)
/// </summary>
public class Ghre_TeacherChangeServices : BaseServices<Ghre_TeacherChange, Ghre_TeacherChangeDto, InsertGhre_TeacherChangeInput, EditGhre_TeacherChangeInput>, IGhre_TeacherChangeServices
{
    private readonly IBaseRepository<Ghre_TeacherChange> _dal;
    private IGhre_AttachmentServices _ghre_AttachmentServices;
    private IGhre_TeacherChangeAttachmentServices _ghre_TeacherChangeAttachmentServices;
    private IGhre_TeacherAttachmentServices _ghre_TeacherAttachmentServices;
    public Ghre_TeacherChangeServices(ICaching caching,
    IGhre_AttachmentServices ghre_AttachmentServices,
    IGhre_TeacherChangeAttachmentServices ghre_TeacherChangeAttachmentServices,
    IGhre_TeacherAttachmentServices ghre_TeacherAttachmentServices,
    IBaseRepository<Ghre_TeacherChange> dal)
    {
        this._dal = dal;
        base.BaseDal = dal;
        base._caching = caching;
        _ghre_AttachmentServices = ghre_AttachmentServices;
        _ghre_TeacherChangeAttachmentServices = ghre_TeacherChangeAttachmentServices;
        _ghre_TeacherAttachmentServices = ghre_TeacherAttachmentServices;
    }

    public override async Task<ServicePageResult<Ghre_TeacherChangeDto>> 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 sql = @$"SELECT * FROM (SELECT A.*,
                       ISNULL ((SELECT CASE WHEN {filter.langId} = 1 THEN UserName ELSE UserEname END
                                FROM Ghrs_User B
                                WHERE B.UserId = A.CreateBy),
                               '') CreateDataInfo,
                       ISNULL ((SELECT CASE WHEN {filter.langId} = 1 THEN UserName ELSE UserEname END
                                FROM Ghrs_User B
                                WHERE B.UserId = A.UpdateBy),
                               '') UpdateDataInfo,
                       ISNULL (A.UpdateTime, A.CreateTime) CreateTime1,
                       ISNULL (C.SchoolName, D.DeptName) DeptOrSchoolName
                FROM Ghre_TeacherChange A
                     LEFT JOIN Ghre_Teacher B ON A.TeacherId = B.Id
                     LEFT JOIN Ghre_School C ON B.SchoolId = C.Id
                     LEFT JOIN Ghro_Dept D ON B.DeptID = D.DeptID) A";

        string conditions = " 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))
                    conditions = DealConditions(condition, name, value);
            }

        if (IsEnable == true)
            sql += " WHERE IsEnable = 1";
        else if (IsEnable == false)
            sql += " WHERE IsEnable = 0";

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

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

        int total = 0;
        var data = Db.SqlQueryable<Ghre_TeacherChangeDto>(sql)
            .Where(conditions)
            .OrderBy(filter.orderBy)
            .ToPageList(filter.pageNum, filter.pageSize, ref total);

        var teacherIds = data.Where(x => x.TeacherId != null).Select(x => x.TeacherId).Distinct().ToList();
        var teachers = await Db.Queryable<Ghre_Teacher>().Where(x => teacherIds.Contains(x.Id)).Select(x => new { x.Id, x.SchoolId, x.DeptID, x.TeacherType, TeacherName = x.TeacherName + " (" + x.TeacherNo + ")" }).ToListAsync();
        //var schoolIds = teachers.Where(x => x.SchoolId != null).Select(x => x.SchoolId.Value).Distinct().ToList();
        //var deptIDs = teachers.Where(x => x.DeptID != null).Select(x => x.DeptID).Distinct().ToList();

        //var depts = await Db.Queryable<Ghro_Dept>().Where(x => deptIDs.Contains(x.DeptID)).Select(x => new { x.DeptID, x.DeptName }).ToListAsync();
        //var schools = await Db.Queryable<Ghre_School>().Where(x => schoolIds.Contains(x.Id)).Select(x => new { x.Id, x.SchoolName }).ToListAsync();

        data.ForEach(async x =>
        {
            var teacher = teachers.FirstOrDefault(o => o.Id == x.TeacherId);
            x.TeacherTypeLabel = await GetParaLabel("TrainingTeacherType", x.TeacherType);
            x.TeacherLevelLabel = await GetParaLabel("TrainingTeacherLevel", x.TeacherLevel);
            x.OriginTeacherLevelLabel = await GetParaLabel("TrainingTeacherLevel", x.OriginTeacherLevel);
            x.ChangeTypeLabel = await GetParaLabel("TrainingTeacherChangeType", x.ChangeType);
            x.OriginChangeTypeLabel = await GetParaLabel("TrainingTeacherChangeType", x.OriginChangeType);
            //x.DeptOrSchoolName = x.TeacherType == "Out" ? schools.FirstOrDefault(o => o.Id == teacher?.SchoolId)?.SchoolName : depts.FirstOrDefault(o => o.DeptID == teacher?.DeptID)?.DeptName;
            x.TeacherName = teacher?.TeacherName;
            x.OriginChangeDate1 = DateTimeHelper.ConvertToDayString(x.OriginChangeDate);
            x.ChangeDate1 = DateTimeHelper.ConvertToDayString(x.ChangeDate);
            x.DataBelongName = await GetDataBelongName(x.DataBelongID);
        });

        return new ServicePageResult<Ghre_TeacherChangeDto>(filter.pageNum, total, filter.pageSize, data);
    }

    public override async Task<ServiceFormResult<Ghre_TeacherChangeDto>> QueryForm(QueryForm body)
    {
        var data = await base.QueryForm(body);
        var entitys = data.result.DT_TableDataT1;
        var ids = entitys.Select(x => x.Id).ToList();
        var teacherAttachments = await _ghre_TeacherChangeAttachmentServices.QueryDto(x => ids.Contains(x.TeacherChangeId.Value));
        var ids1 = teacherAttachments.Select(x => x.Id.ToString()).ToList();
        var attachments = await _ghre_AttachmentServices.QueryDto(x => ids1.Contains(x.TableName));

        teacherAttachments.ForEach(x =>
        {
            x.Attachments = attachments.Where(o => o.TableName == x.Id.ToString()).ToList();
        });
        entitys.ForEach(x =>
        {
            x.TeacherAttachments = teacherAttachments.Where(o => o.TeacherChangeId == x.Id).ToList();
        });

        data.result.DT_TableDataT1 = entitys;
        return data;
    }

    public override async Task<long> Add(InsertGhre_TeacherChangeInput entity)
    {
        #region 校验 当天是否能发起
        if (await Db.Queryable<Ghre_TeacherChange>().AnyAsync(x => x.TeacherId == entity.TeacherId && ((x.Status == "Wait") || (x.Status != "Wait" && x.WorkState != 2))))
            throw new Exception("讲师当天只能发起一笔有效异动！");
        #endregion

        var teacher = await Db.Queryable<Ghre_Teacher>().FirstAsync(x => x.Id == entity.TeacherId);

        entity.SchoolId = teacher.SchoolId;
        entity.DeptID = teacher.DeptID;
        entity.SponsorId = GetStaffId();
        var id = await base.Add(entity);
        var sql = $"SELECT ISNULL(MAX(id)+1,1) FROM Ghre_TeacherChange WHERE Id !='{id}'";
        var id1 = await Db.Ado.GetLongAsync(sql);
        sql = $"UPDATE Ghre_TeacherChange SET Id={id1} WHERE  Id ='{id}'";
        await Db.Ado.ExecuteCommandAsync(sql);
        id = id1;

        if (entity.TeacherAttachments != null && entity.TeacherAttachments.Any())
        {
            for (int i = 0; i < entity.TeacherAttachments.Count; i++)
            {
                var insert = entity.TeacherAttachments[i];
                insert.TeacherChangeId = id;
                var teacherAttachmentId = await _ghre_TeacherChangeAttachmentServices.Add(insert);
                if (insert.Attachments != null && insert.Attachments.Any())
                    for (int j = 0; j < insert.Attachments.Count; j++)
                    {
                        await Db.Updateable<Ghre_Attachment>()
                              .SetColumns(it => new Ghre_Attachment() { TableName = teacherAttachmentId.ToString(), UpdateTime = DateTime.Now })
                              .Where(it => it.RelativePath == insert.Attachments[j].RelativePath)
                              .ExecuteCommandAsync();
                    }
            }
        }

        return id;
    }

    public override async Task<bool> Update(long Id, EditGhre_TeacherChangeInput editModel)
    {
        if (editModel.TeacherType == "In")
        {
            editModel.SchoolId = null;
            var staff = await Db.Queryable<Ghra_Staff>().FirstAsync(x => x.StaffID == editModel.StaffId);
            if (staff != null)
            {
                editModel.TeacherNo = staff.StaffNo;
                editModel.TeacherName = staff.StaffName;
            }
        }
        else
        {
            editModel.DeptID = null;
            editModel.StaffId = null;
        }
        var result = await base.Update(Id, editModel, null, ["Status"]);
        await _ghre_TeacherChangeAttachmentServices.Delete(x => x.TeacherChangeId == Id);
        if (editModel.TeacherAttachments != null && editModel.TeacherAttachments.Any())
        {
            for (int i = 0; i < editModel.TeacherAttachments.Count; i++)
            {
                var insert = editModel.TeacherAttachments[i];
                insert.TeacherId = Id;
                var TeacherAttachmentId = await _ghre_TeacherChangeAttachmentServices.Add(Mapper.Map(insert).ToANew<InsertGhre_TeacherChangeAttachmentInput>());
                if (insert.Attachments != null && insert.Attachments.Any())
                    for (int j = 0; j < insert.Attachments.Count; j++)
                    {
                        await Db.Updateable<Ghre_Attachment>()
                              .SetColumns(it => new Ghre_Attachment() { TableName = TeacherAttachmentId.ToString(), UpdateTime = DateTime.Now })
                              .Where(it => it.RelativePath == insert.Attachments[j].RelativePath)
                              .ExecuteCommandAsync();
                    }
            }
        }


        #region 状态是Wait 直接会写至主数据
        var change = await base.QueryById(Id);
        if (change.Status == "Wait")
        {
            var teacher = Mapper.Map(editModel).ToANew<Ghre_Teacher>();
            teacher.Id = editModel.TeacherId.Value;
            await Db.Updateable(teacher).UpdateColumns(it => new { it.TeacherLevel, it.Price, it.SkillPoints }).ExecuteCommandAsync();

            var teacherAttachmentIds = await Db.Queryable<Ghre_TeacherAttachment>().Where(x => x.TeacherId == editModel.TeacherId).Select(x => x.Id).ToListAsync();
            if (teacherAttachmentIds.Any())
                await Db.Updateable<Ghre_TeacherAttachment>()
                    .SetColumns(it => new Ghre_TeacherAttachment()
                    {
                        IsEnable = 0
                    })
                    .Where(it => teacherAttachmentIds.Contains(it.Id))
                    .ExecuteCommandAsync();

            if (editModel.TeacherAttachments != null && editModel.TeacherAttachments.Any())
            {
                for (int i = 0; i < editModel.TeacherAttachments.Count; i++)
                {
                    var insert = Mapper.Map(editModel.TeacherAttachments[i]).ToANew<InsertGhre_TeacherAttachmentInput>(); ;
                    insert.TeacherId = teacher.Id;
                    var teacherAttachmentId = await _ghre_TeacherAttachmentServices.Add(insert);
                    if (editModel.TeacherAttachments[i].Attachments != null && editModel.TeacherAttachments[i].Attachments.Any())
                        for (int j = 0; j < editModel.TeacherAttachments[i].Attachments.Count; j++)
                        {
                            var attachment = await Db.Queryable<Ghre_Attachment>().FirstAsync(x => x.RelativePath == insert.Attachments[j].RelativePath);
                            attachment.TableName = teacherAttachmentId.ToString();
                            await Db.Insertable(attachment).ExecuteReturnSnowflakeIdAsync();
                        }
                }
            }
        }
        #endregion

        return result;
    }
    public async Task<ServiceResult<long>> InsertByStatus(InsertGhre_TeacherChangeInput 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;
            #region 状态是Wait 直接会写至主数据
            if (status == "Wait")
            {
                var teacher = Mapper.Map(insertModel).ToANew<Ghre_Teacher>();
                teacher.Id = insertModel.TeacherId.Value;
                await Db.Updateable(teacher).UpdateColumns(it => new { it.TeacherLevel, it.Price, it.SkillPoints }).ExecuteCommandAsync();

                var teacherAttachmentIds = await Db.Queryable<Ghre_TeacherAttachment>().Where(x => x.TeacherId == insertModel.TeacherId).Select(x => x.Id).ToListAsync();
                if (teacherAttachmentIds.Any())
                    await Db.Updateable<Ghre_TeacherAttachment>()
                        .SetColumns(it => new Ghre_TeacherAttachment()
                        {
                            IsEnable = 0
                        })
                        .Where(it => teacherAttachmentIds.Contains(it.Id))
                        .ExecuteCommandAsync();

                if (insertModel.TeacherAttachments != null && insertModel.TeacherAttachments.Any())
                {
                    for (int i = 0; i < insertModel.TeacherAttachments.Count; i++)
                    {
                        var insert = Mapper.Map(insertModel.TeacherAttachments[i]).ToANew<InsertGhre_TeacherAttachmentInput>(); ;
                        insert.TeacherId = teacher.Id;
                        var teacherAttachmentId = await _ghre_TeacherAttachmentServices.Add(insert);
                        if (insertModel.TeacherAttachments[i].Attachments != null && insertModel.TeacherAttachments[i].Attachments.Any())
                            for (int j = 0; j < insertModel.TeacherAttachments[i].Attachments.Count; j++)
                            {
                                var attachment = await Db.Queryable<Ghre_Attachment>().FirstAsync(x => x.RelativePath == insert.Attachments[j].RelativePath);
                                attachment.TableName = teacherAttachmentId.ToString();
                                await Db.Insertable(attachment).ExecuteReturnSnowflakeIdAsync();
                            }
                    }
                }
            }
            #endregion
        }
        else
            return ServiceResult<long>.OprateFailed("发布成功！");

        return data;
    }

    public async Task<ServiceResult> UpdateStatus(InsertGhre_TeacherChangeInput 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_TeacherChange>();
        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("执行成功！");

    }


    public async Task<ServiceResult<Ghre_TeacherChangeDto>> QueryLast(int teacherId)
    {
        var change = new Ghre_TeacherChangeDto();
        var change1 = await Db.Queryable<Ghre_TeacherChange>().OrderByDescending(x => x.CreateTime).FirstAsync(x => x.TeacherId == teacherId && (x.Status == "Active" || x.Status == "Wait"));
        if (change1 != null)
        {
            change = Mapper.Map(change1).ToANew<Ghre_TeacherChangeDto>();
            change.OriginChangeDate = change.ChangeDate;
            change.OriginChangeType = change.ChangeType;
            change.OriginPrice = change.Price;
            change.OriginSkillPoints = change.SkillPoints;
            change.OriginTeacherLevel = change.TeacherLevel;

            change.ChangeDate = null;
            change.ChangeType = null;
            change.Price = null;
            change.SkillPoints = null;
            change.TeacherLevel = null;
            change.RemarkSz = null;
            change.DeptOrSchoolName = change.TeacherType == "Out" ? (await Db.Queryable<Ghre_School>().FirstAsync(o => o.Id == change.SchoolId))?.SchoolName : (await Db.Queryable<Ghro_Dept>().FirstAsync(o => o.DeptID == change.DeptID))?.DeptName;

            var teacherAttachments = await Db.Queryable<Ghre_TeacherChangeAttachment>().Where(x => x.TeacherChangeId == change.Id).ToListAsync();

            change.TeacherAttachments = Mapper.Map(teacherAttachments).ToANew<List<Ghre_TeacherChangeAttachmentDto>>();
            var ids1 = teacherAttachments.Select(x => x.Id.ToString()).ToList();
            var attachments = await _ghre_AttachmentServices.QueryDto(x => ids1.Contains(x.TableName));
            change.TeacherAttachments.ForEach(x =>
            {
                x.Attachments = attachments.Where(o => o.TableName == x.Id.ToString()).ToList();
            });
        }
        else
        {
            var teacher = await Db.Queryable<Ghre_Teacher>().FirstAsync(x => x.Id == teacherId);
            if (teacher != null)
            {
                change.TeacherType = teacher.TeacherType;
                change.OriginTeacherLevel = teacher.TeacherLevel;
                change.OriginPrice = teacher.Price;
                change.OriginSkillPoints = teacher.SkillPoints;
                change.SchoolId = teacher.SchoolId;
                change.DeptID = teacher.DeptID;
                change.DeptOrSchoolName = change.OriginTeacherLevel == "Out" ? (await Db.Queryable<Ghre_School>().FirstAsync(o => o.Id == change.SchoolId))?.SchoolName : (await Db.Queryable<Ghro_Dept>().FirstAsync(o => o.DeptID == change.DeptID))?.DeptName;
                change.PhotoUrl = teacher.PhotoUrl;

                var teacherAttachments = await Db.Queryable<Ghre_TeacherAttachment>().Where(x => x.TeacherId == teacher.Id).ToListAsync();

                change.TeacherAttachments = Mapper.Map(teacherAttachments).ToANew<List<Ghre_TeacherChangeAttachmentDto>>();
                var ids1 = teacherAttachments.Select(x => x.Id.ToString()).ToList();
                var attachments = await _ghre_AttachmentServices.QueryDto(x => ids1.Contains(x.TableName));
                change.TeacherAttachments.ForEach(x =>
                {
                    x.Attachments = attachments.Where(o => o.TableName == x.Id.ToString()).ToList();
                });
            }
        }
        return ServiceResult<Ghre_TeacherChangeDto>.OprateSuccess("执行成功！", change);

    }
}