
using Tiobon.Core.IServices;
using Tiobon.Core.Model.Models;
using Tiobon.Core.Services.BASE;
using Tiobon.Core.IRepository.Base;
using Tiobon.Core.Common.Caches;
using Tiobon.Core.Common;
using Tiobon.Core.Model;
using AgileObjects.AgileMapper;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

namespace Tiobon.Core.Services;

/// <summary>
/// Ghre_Teacher (服务)
/// </summary>
public class Ghre_TeacherServices : BaseServices<Ghre_Teacher, Ghre_TeacherDto, InsertGhre_TeacherInput, EditGhre_TeacherInput>, IGhre_TeacherServices
{
    private readonly IBaseRepository<Ghre_Teacher> _dal;
    private IGhre_AttachmentServices _ghre_AttachmentServices;
    private IGhre_TeacherAttachmentServices _ghre_TeacherAttachmentServices;
    public Ghre_TeacherServices(ICaching caching,
    IGhre_AttachmentServices ghre_AttachmentServices,
    IGhre_TeacherAttachmentServices ghre_TeacherAttachmentServices,
    IBaseRepository<Ghre_Teacher> dal)
    {
        this._dal = dal;
        base.BaseDal = dal;
        base._caching = caching;
        _ghre_AttachmentServices = ghre_AttachmentServices;
        _ghre_TeacherAttachmentServices = ghre_TeacherAttachmentServices;
    }

    public override async Task<ServicePageResult<Ghre_TeacherDto>> 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 (SELECT A.*,
             A.TeacherNo + A.TeacherName TeacherName1,
             CASE A.TeacherType
                WHEN 'In' THEN B.DeptName
                WHEN 'Out' THEN C.SchoolName
                ELSE NULL
             END 'DeptOrSchoolName1'
      FROM Ghre_Teacher A
           LEFT JOIN Ghro_Dept B ON A.DeptID = B.DeptID
           LEFT JOIN Ghre_School C ON A.SchoolId = C.Id) A";
        var sql1 = @$"DECLARE @langId   INT = {filter.langId};";
        var sql = @$"SELECT *
                        FROM (SELECT A.*,
                                     ISNULL
                                     ((SELECT CASE WHEN @langId = 1 THEN UserName ELSE UserEname END
                                       FROM Ghrs_User B
                                       WHERE B.UserId = A.CreateBy),
                                      '') CreateDataInfo,
                                     ISNULL
                                     ((SELECT CASE WHEN @langId = 1 THEN UserName ELSE UserEname END
                                       FROM Ghrs_User B
                                       WHERE B.UserId = A.UpdateBy),
                                      '') UpdateDataInfo,
                                     ISNULL (A.UpdateTime, A.CreateTime) CreateTime1,
                                     A.TeacherNo + A.TeacherName TeacherName1,
                                     CASE A.TeacherType
                                        WHEN 'In' THEN B.DeptName
                                        WHEN 'Out' THEN C.SchoolName
                                        ELSE NULL
                                     END 'DeptOrSchoolName1'
                              FROM Ghre_Teacher A
                                   LEFT JOIN Ghro_Dept B ON A.DeptID = B.DeptID
                                   LEFT JOIN Ghre_School C ON A.SchoolId = C.Id) A";

        string conditions = " WHERE 1=1 ";
        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 (!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;
        sql = sql1 + sql;
        var entitys = await Db.Ado.SqlQueryAsync<Ghre_TeacherDto>(sql);

        var data = new ServicePageResult<Ghre_TeacherDto>(filter.pageNum, total, filter.pageSize, entitys);
        //});

        var schoolIds = data.result.DT_TableDataT1.Where(x => x.SchoolId != null).Select(x => x.SchoolId.Value).Distinct().ToList();
        var deptIDs = data.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)).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.result.DT_TableDataT1.ForEach(async x =>
        {
            x.GenderLabel = await GetParaLabel("Gender", x.Gender);
            x.TeacherTypeLabel = await GetParaLabel("TrainingTeacherType", x.TeacherType);
            x.TeacherLevelLabel = await GetParaLabel("TrainingTeacherLevel", x.TeacherLevel);
            x.DeptOrSchoolName = x.TeacherType == "Out" ? schools.FirstOrDefault(o => o.Id == x.SchoolId)?.SchoolName : depts.FirstOrDefault(o => o.DeptID == x.DeptID)?.DeptName;

        });
        return data;
    }


    public override async Task<ServiceFormResult<Ghre_TeacherDto>> 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_TeacherAttachmentServices.QueryDto(x => ids.Contains(x.TeacherId.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.TeacherId == x.Id).ToList();
        });

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

    public override async Task<long> Add(InsertGhre_TeacherInput entity)
    {

        if (entity.TeacherType == "In")
        {
            entity.SchoolId = null;
            var staff = await Db.Queryable<Ghra_Staff>().FirstAsync(x => x.StaffID == entity.StaffId);
            if (staff != null)
            {
                entity.TeacherNo = staff.StaffNo;
                entity.TeacherName = staff.StaffName;
            }
        }
        else
        {
            entity.DeptID = null;
            entity.StaffId = null;
        }


        var id = await base.Add(entity);

        if (entity.TeacherAttachments != null && entity.TeacherAttachments.Any())
        {
            for (int i = 0; i < entity.TeacherAttachments.Count; i++)
            {
                var insert = entity.TeacherAttachments[i];
                insert.TeacherId = id;
                var teacherAttachmentId = await _ghre_TeacherAttachmentServices.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_TeacherInput 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);
        await _ghre_TeacherAttachmentServices.Delete(x => x.TeacherId == 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_TeacherAttachmentServices.Add(Mapper.Map(insert).ToANew<InsertGhre_TeacherAttachmentInput>());
                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 result;
    }
}