namespace Tiobon.Core.Services;

/// <summary>
/// 培训证书规则 (服务)
/// </summary>
public class Ghre_CertificateRuleServices : BaseServices<Ghre_CertificateRule, Ghre_CertificateRuleDto, InsertGhre_CertificateRuleInput, EditGhre_CertificateRuleInput>, IGhre_CertificateRuleServices
{
    private readonly IBaseRepository<Ghre_CertificateRule> _dal;
    private readonly IGhre_CourseServices _ghre_CourseServices;
    private readonly IGhre_CourseSceneServices _ghre_CourseSceneServices;
    public Ghre_CertificateRuleServices(ICaching caching,
        IGhre_CourseServices ghre_CourseServices,
        IGhre_CourseSceneServices ghre_CourseSceneServices,
        IBaseRepository<Ghre_CertificateRule> dal)
    {
        this._dal = dal;
        base.BaseDal = dal;
        base._caching = caching;
        _ghre_CourseServices = ghre_CourseServices;
        _ghre_CourseSceneServices = ghre_CourseSceneServices;
    }

    public override async Task<ServicePageResult<Ghre_CertificateRuleDto>> QueryFilterPage(QueryBody filter, string condition, bool? IsEnable = true)
    {
        string condition1 = string.Empty;
        if (filter.jsonParam != null)
            foreach (JProperty jProperty in filter.jsonParam.Properties())
            {
                var name = jProperty.Name;
                var value = jProperty.Value.ToString();
                if (!string.IsNullOrWhiteSpace(value) && name == "CourseName")
                {
                    var jsonParam = JsonConvert.DeserializeObject<JsonParam>(value);

                    switch (jsonParam.operationKey)
                    {
                        case "Equal":
                            condition1 = $" ( CourseSceneId='{jsonParam.columnValue}' or CourseId='{jsonParam.columnValue}' )";
                            break;
                        case "NotEqual":
                            condition1 = $"( CourseSceneId!='{{jsonParam.columnValue}}' AND CourseId!='{{jsonParam.columnValue}}' )\";";
                            break;
                        default:
                            break;
                    }
                }
            }

        if (condition.IsNull())
            condition = condition1;
        else condition += " AND " + condition1;
        var data = await base.QueryFilterPage(filter, condition, IsEnable);

        var courseIds = new List<long?>();
        var courseSceneIds = new List<long?>();
        data.result.DT_TableDataT1.ForEach(x =>
        {
            if (x.CourseId1.IsNotEmptyOrNull())
            {
                x.CourseIds = JsonHelper.JsonToObj<List<long?>>(x.CourseId1);
                courseIds.AddRange(x.CourseIds);
            }
            else if (x.CourseId != null)
            {
                courseIds.Add(x.CourseId);
                x.CourseIds = [x.CourseId];
            }

            if (x.CourseSceneId1.IsNotEmptyOrNull())
            {
                x.CourseSceneIds = JsonHelper.JsonToObj<List<long?>>(x.CourseSceneId1);
                courseSceneIds.AddRange(x.CourseSceneIds);
            }
            else if (x.CourseSceneId != null)
            {
                courseSceneIds.Add(x.CourseSceneId);
                x.CourseSceneIds = [x.CourseSceneId];
            }
        });


        var courses = await _ghre_CourseServices.Query(x => courseIds.Contains(x.Id));
        var courseScenes = await _ghre_CourseSceneServices.Query(x => courseSceneIds.Contains(x.Id));

        data.result.DT_TableDataT1.ForEach(async x =>
        {
            x.RuleTypeLabel = await GetParaLabel("TrainingCertificateRuleType", x.RuleType);
            x.SendRuleLabel = await GetParaLabel("TrainingCertificateSendRule", x.SendRule);

            string staticType = x.StaticType == "month" ? "月" : (x.StaticType == "year" ? "年" : "天");
            if (x.ValidityType == "StaticDuration")
                x.ValidityLabel = $"自颁发日起 【{x.StaticNum}】{staticType}内有效";
            else
            if (x.ValidityType == "Unlimited")
                x.ValidityLabel = $"自颁发日起终生有效";
            else
            if (x.ValidityType == "Option")
                x.ValidityLabel = $"有效期至【{x.ValidityTime.Value.ToString("yyyy-MM-dd")}】";
            if (x.CourseIds != null && x.CourseIds.Any())
            {
                x.SceneOrCourseName = string.Join("、", courses.Where(o => x.CourseIds.Contains(o.Id)).Select(o => o.CourseName));
            }
            //

            if (x.CourseSceneIds != null && x.CourseSceneIds.Any())
                x.SceneOrCourseName = string.Join("、", courseScenes.Where(o => x.CourseSceneIds.Contains(o.Id)).Select(o => o.SceneName));
        });
        return data;

    }

    public override async Task<long> Add(InsertGhre_CertificateRuleInput entity)
    {
        if (entity.CourseSceneIds != null)
            entity.CourseSceneId1 = JsonHelper.ObjToJson(entity.CourseSceneIds);
        if (entity.CourseIds != null)
            entity.CourseId1 = JsonHelper.ObjToJson(entity.CourseIds);
        var result = await base.Add(entity);

        var design = Mapper.Map(entity.CertificateDesignerData).ToANew<Ghre_CertificateDesign>();
        design.CertificateRuleId = result;
        var items = new List<Ghre_CertificateDesignItem>();
        var designId = await Db.Insertable(design).ExecuteReturnSnowflakeIdAsync();
        if (entity.CertificateDesignerData.containerItems != null)
            for (int i = 0; i < entity.CertificateDesignerData.containerItems.Count; i++)
            {
                var item = Mapper.Map(entity.CertificateDesignerData.containerItems[i]).ToANew<Ghre_CertificateDesignItem>();
                item.id1 = entity.CertificateDesignerData.containerItems[i].id;
                item.CertificateRuleId = result;
                item.CertificateDesignId = designId;
                item.Id = UtilHelper.GetSysId();
                await Db.Insertable(item).ExecuteReturnSnowflakeIdAsync();
            }

        return result;
    }

    public override async Task<bool> Update(long Id, EditGhre_CertificateRuleInput editModel)
    {
        if (editModel.CourseSceneIds != null)
            editModel.CourseSceneId1 = JsonHelper.ObjToJson(editModel.CourseSceneIds);
        if (editModel.CourseIds != null)
            editModel.CourseId1 = JsonHelper.ObjToJson(editModel.CourseIds);

        await Db.Deleteable<Ghre_CertificateDesign>().Where(x => x.CertificateRuleId == Id).ExecuteCommandAsync();
        await Db.Deleteable<Ghre_CertificateDesignItem>().Where(x => x.CertificateRuleId == Id).ExecuteCommandAsync();

        var design = Mapper.Map(editModel.CertificateDesignerData).ToANew<Ghre_CertificateDesign>();
        design.CertificateRuleId = Id;
        var items = new List<Ghre_CertificateDesignItem>();
        var designId = await Db.Insertable(design).ExecuteReturnSnowflakeIdAsync();
        if (editModel.CertificateDesignerData.containerItems != null)
            for (int i = 0; i < editModel.CertificateDesignerData.containerItems.Count; i++)
            {
                var item = Mapper.Map(editModel.CertificateDesignerData.containerItems[i]).ToANew<Ghre_CertificateDesignItem>();
                item.id1 = editModel.CertificateDesignerData.containerItems[i].id;
                item.CertificateRuleId = Id;
                item.CertificateDesignId = designId;
                item.Id = UtilHelper.GetSysId();
                await Db.Insertable(item).ExecuteReturnSnowflakeIdAsync();
            }

        var result = await base.Update(Id, editModel);
        return result;
    }


    public override async Task<ServiceFormResult<Ghre_CertificateRuleDto>> QueryForm(QueryForm body)
    {
        var result = await base.QueryForm(body);
        string CourseId1 = result.result.DT_TableDataT1[0].CourseId1;
        if (!string.IsNullOrWhiteSpace(CourseId1))
            result.result.DT_TableDataT1[0].CourseIds = JsonConvert.DeserializeObject<List<long?>>(CourseId1);
        string CourseSceneId1 = result.result.DT_TableDataT1[0].CourseSceneId1;
        if (!string.IsNullOrWhiteSpace(CourseSceneId1))
            result.result.DT_TableDataT1[0].CourseSceneIds = JsonConvert.DeserializeObject<List<long?>>(CourseSceneId1);

        var design = await Db.Queryable<Ghre_CertificateDesign>().Where(x => x.CertificateRuleId == body.id).FirstAsync();
        if (design != null)
        {
            var design1 = Mapper.Map(design).ToANew<CertificateDesignerData>();
            var items = new List<CertificateDesignerItem>();
            var designItems = await Db.Queryable<Ghre_CertificateDesignItem>().Where(x => x.CertificateRuleId == body.id).ToListAsync();
            designItems.ForEach(x =>
            {
                var item = Mapper.Map(x).ToANew<CertificateDesignerItem>();
                item.id = x.id1;
                items.Add(item);
            });

            design1.containerItems = items;
            result.result.DT_TableDataT1[0].CertificateDesignerData = design1;

        }


        return result;

    }

    public async Task<ServiceResult<Ghre_CertificateRuleDto>> Preview(long id)
    {
        var result = await base.QueryById(id);

        int? staffId = App.User.StaffId;
        long? studyRecordId = null;
        Ghre_Certificate certificate = null;
        if (result is null)
        {
            certificate = await Db.Queryable<Ghre_Certificate>().Where(x => x.Id == id).FirstAsync();
            staffId = certificate.StaffId;
            studyRecordId = certificate.Reverse1.IsNotEmptyOrNull() ? certificate.Reverse1.ObjToLong() : null;
            result = await base.QueryById(certificate.CertificateRuleId);
        }

        string CourseId1 = result.CourseId1;
        if (!string.IsNullOrWhiteSpace(CourseId1))
            result.CourseIds = JsonConvert.DeserializeObject<List<long?>>(CourseId1);
        string CourseSceneId1 = result.CourseSceneId1;
        if (!string.IsNullOrWhiteSpace(CourseSceneId1))
            result.CourseSceneIds = JsonConvert.DeserializeObject<List<long?>>(CourseSceneId1);

        var design = await Db.Queryable<Ghre_CertificateDesign>().Where(x => x.CertificateRuleId == result.Id).FirstAsync();
        if (design != null)
        {
            var staff = await Db.Queryable<Ghra_Staff>().Where(x => x.StaffID == staffId).FirstAsync();
            var dept = await Db.Queryable<Ghro_Dept>().Where(x => x.DeptID == staff.DeptID).FirstAsync();
            var title = await Db.Queryable<Ghra_Title>().Where(x => x.TitleID == staff.TitleID).FirstAsync();

            var examRecord = await Db.Queryable<Ghre_ExamRecord>()
                .WhereIF(studyRecordId != null, x => x.Id == studyRecordId)
                .OrderByDescending(x => x.CreateTime)
                .FirstAsync();
            var exam = await Db.Queryable<Ghre_Exam>().FirstAsync();
            var studyRecord = await Db.Queryable<Ghre_StudyRecord>()
                .WhereIF(examRecord != null, x => x.Id == examRecord.StudyRecordId)
                .WhereIF(studyRecordId != null, x => x.Id == studyRecordId)
                .FirstAsync();

            var course = await Db.Queryable<Ghre_Course>().FirstAsync();
            //var courseScene = await Db.Queryable<Ghre_CourseScene>().Where(x => x.Id == course.sc).FirstAsync();

            var design1 = Mapper.Map(design).ToANew<CertificateDesignerData>();
            var items = new List<CertificateDesignerItem>();
            var designItems = await Db.Queryable<Ghre_CertificateDesignItem>().Where(x => x.CertificateRuleId == result.Id).ToListAsync();
            designItems.ForEach(x =>
            {
                var item = Mapper.Map(x).ToANew<CertificateDesignerItem>();
                item.id = x.id1;

                if (item.type == "fieldText" || item.type == "fieldImage")
                {
                    switch (item.field)
                    {
                        case "CertificateNo"://证书编号

                            if (item.certNoRule == "random")
                                item.text = SnowFlakeSingle.Instance.NextId().ObjToString();

                            if (certificate != null) item.text = certificate.CertificateNo;

                            break;
                        case "AwardDate"://发证日期
                            if (item.dateFormat == "YYYY年MM月DD日")
                                item.text = DateTimeHelper.ConvertToDayString(DateTime.Now);

                            if (certificate != null) item.text = DateTimeHelper.ConvertToDayString(certificate.CreateTime);
                            break;
                        case "CertificationBody"://颁发机构 
                            item.text = result.IssueOrgName;

                            break;
                        case "ValidityPeriod"://有效期至

                            if (result.ValidityType == "Option")
                                item.text = DateTimeHelper.ConvertToDayString(result.ValidityTime);

                            break;
                        case "StaffName"://员工姓名
                            item.text = staff.StaffName;
                            break;
                        case "DeptName"://部门
                            item.text = dept.DeptName;
                            break;
                        case "TitleName"://岗位
                            item.text = title.TitleName;

                            break;
                        case "PhotoUrl"://照片
                            item.imageUrl = staff.PhotoUrl;
                            break;
                        case "CourseName"://课程名称
                            item.text = course.CourseName;
                            break;
                        case "CourseSceneName"://课程场景
                            item.text = "";

                            break;
                        case "StudyTime"://学习时间
                            item.text = $"{studyRecord?.BeginTime}~{studyRecord?.EndTime}";

                            break;
                        case "ExamName"://考试名称
                            item.text = exam?.ExamName;
                            break;
                        case "ExamNo"://考试编号
                            item.text = exam?.ExamNo;
                            break;
                        case "ExamScore"://考试分数
                            item.text = examRecord?.FinallyScore.ObjToString();
                            break;
                        case "ExamResult"://考试结果
                            item.text = examRecord?.FinallyIsPass == true ? "通过" : "未通过";
                            break;
                        case "ExamComment"://考试评语
                            item.text = examRecord?.Comment;
                            break;
                        default:
                            break;
                    }
                }

                items.Add(item);
            });

            design1.containerItems = items;



            result.CertificateDesignerData = design1;

        }


        return ServiceResult<Ghre_CertificateRuleDto>.OprateSuccess("查询成功！", result);

    }
}