
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 Newtonsoft.Json.Linq;
using SqlSugar;
using Newtonsoft.Json;
using MySqlX.XDevAPI.Common;
using System.Data;
using System.Dynamic;
using Tiobon.Core.Common.DB.Dapper.Extensions;
using AgileObjects.AgileMapper;
using Microsoft.AspNetCore.Http;
using Tiobon.Core.Common.UserManager;
using Tiobon.Core.Common.Helper;

namespace Tiobon.Core.Services;

/// <summary>
/// 课程 (服务)
/// </summary>
public class Ghre_CourseServices : BaseServices<Ghre_Course, Ghre_CourseDto, InsertGhre_CourseInput, EditGhre_CourseInput>, IGhre_CourseServices
{
    private readonly IBaseRepository<Ghre_Course> _dal;
    private IGhre_CourseClassServices _ghre_CourseClassServices;
    public Ghre_CourseServices(IBaseRepository<Ghre_Course> dal,
        ICaching caching,
        IGhre_CourseClassServices ghre_CourseClassServices)
    {
        this._dal = dal;
        base.BaseDal = dal;
        _ghre_CourseClassServices = ghre_CourseClassServices;
        base._caching = caching;
    }

    public override async Task<ServicePageResult<Ghre_CourseDto>> QueryFilterPage(QueryBody filter)
    {
        RefAsync<int> totalCount = 0;
        string sql = @"SELECT *
                        FROM (SELECT A.*,
                                     B.ClassName CourseClassName,
                                     C.ClassName CourseClassName2,
                                     D.SceneName CourseSceneName,
                                     E.CourseWareName,
                                     F.StaffName ManagerStaffName,
                                     G.UserName CreateName,
                                     G.UserName UpdateName,
                                     CASE A.InOrOut
                                        WHEN 'In' THEN F.StaffName
                                        WHEN 'Out' THEN J.TeacherName
                                     END TeacherName
                              FROM Ghre_Course A
                                   LEFT JOIN Ghre_CourseClass B ON A.CourseClassId = B.Id
                                   LEFT JOIN Ghre_CourseClass C ON A.CourseClassId2 = C.Id
                                   LEFT JOIN Ghre_CourseScene D ON A.CourseSceneId = D.Id
                                   LEFT JOIN Ghre_CourseWare E ON A.CourseWareId = E.Id
                                   LEFT JOIN Ghra_Staff F ON A.ManagerId = F.StaffID
                                   LEFT JOIN Ghrs_User G ON A.CreateBy = G.UserId
                                   LEFT JOIN Ghrs_User H ON A.UpdateBy = H.UserId
                                   LEFT JOIN Ghra_Staff I ON A.TeacherId = I.StaffID
                                   LEFT JOIN Ghre_Teacher J ON A.SchoolTeacherId = I.StaffID
                              WHERE A.IsEnable = 1) A";

        if (string.IsNullOrWhiteSpace(filter.orderBy))
            filter.orderBy = "CreateTime DESC";

        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))
                {
                    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;
                        default:
                            break;
                    }
                }
            }
        if (filter.pageSize == 0)
            filter.pageSize = 10000;
        var data = await Db.SqlQueryable<Ghre_CourseDto>(sql)
            .OrderBy(filter.orderBy)
            .ToPageListAsync(filter.pageNum, filter.pageSize, totalCount);

        data.ForEach(async x =>
        {
            x.ChargeMethodLabel = await GetParaLabel("CourseChargeMethod", x.ChargeMethod);
            x.InOrOutLabel = await GetParaLabel("CourseInOrOut", x.InOrOut);
            x.IsOPenLabel = x.IsOPen == true ? "是" : "否";
        });

        return new ServicePageResult<Ghre_CourseDto>(filter.pageNum, totalCount, filter.pageSize, data);

    }


    public async Task<ServicePageResult<Ghre_CourseDto>> QueryList(QueryBody filter, string status)
    {
        RefAsync<int> totalCount = 0;
        string sql = @"SELECT *
                        FROM (SELECT A.*,
                                     B.ClassName CourseClassName,
                                     C.ClassName CourseClassName2,
                                     D.SceneName CourseSceneName,
                                     E.CourseWareName,
                                     F.StaffName ManagerStaffName,
                                     G.UserName CreateName,
                                     G.UserName UpdateName,
                                     CASE A.InOrOut
                                        WHEN 'In' THEN F.StaffName
                                        WHEN 'Out' THEN J.TeacherName
                                     END TeacherName
                              FROM Ghre_Course A
                                   LEFT JOIN Ghre_CourseClass B ON A.CourseClassId = B.Id
                                   LEFT JOIN Ghre_CourseClass C ON A.CourseClassId2 = C.Id
                                   LEFT JOIN Ghre_CourseScene D ON A.CourseSceneId = D.Id
                                   LEFT JOIN Ghre_CourseWare E ON A.CourseWareId = E.Id
                                   LEFT JOIN Ghra_Staff F ON A.ManagerId = F.StaffID
                                   LEFT JOIN Ghrs_User G ON A.CreateBy = G.UserId
                                   LEFT JOIN Ghrs_User H ON A.UpdateBy = H.UserId
                                   LEFT JOIN Ghra_Staff I ON A.TeacherId = I.StaffID
                                   LEFT JOIN Ghre_Teacher J ON A.SchoolTeacherId = I.StaffID
                              WHERE A.IsEnable = 1) A";

        if (string.IsNullOrWhiteSpace(filter.orderBy))
            filter.orderBy = "CreateTime DESC";

        string conditions = " WHERE 1=1";


        if (!string.IsNullOrWhiteSpace(status))
            conditions += $" AND Status ='{status}'";

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

                    if (name == "CourseNoOrName")
                    {
                        conditions += $" AND ( CourseNo LIKE '%{jsonParam.columnValue}%' OR CourseName LIKE '%{jsonParam.columnValue}%')";
                        continue;
                    }

                    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;
                        default:
                            break;
                    }
                }
            }
        if (filter.pageSize == 0)
            filter.pageSize = 10000;
        sql += conditions;
        var data = await Db.SqlQueryable<Ghre_CourseDto>(sql)
            .OrderBy(filter.orderBy)
            .ToPageListAsync(filter.pageNum, filter.pageSize, totalCount);

        data.ForEach(async x =>
        {
            x.ChargeMethodLabel = await GetParaLabel("CourseChargeMethod", x.ChargeMethod);
            x.InOrOutLabel = await GetParaLabel("CourseInOrOut", x.InOrOut);
            x.IsOPenLabel = x.IsOPen == true ? "是" : "否";
        });

        return new ServicePageResult<Ghre_CourseDto>(filter.pageNum, totalCount, filter.pageSize, data);
    }

    public async Task<ServiceResult<int>> QueryDeptID(int StaffID)
    {
        string sql = $"SELECT A.DeptID from Ghra_Staff A LEFT JOIN Ghro_Dept B ON A.DeptID = B.DeptID WHERE A.StaffID='{StaffID}'";

        int id = await Db.Ado.GetIntAsync(sql);
        return ServiceResult<int>.OprateSuccess("查询成功！", id);

    }
    public async Task<ServiceResult<CommonSelect>> QueryTeacher(long? linkId)
    {
        var result = new CommonSelect();
        JArray TableColumn = new JArray();
        JArray DT_TablePageInfoT1 = new JArray();
        JArray DT_TableDataT1 = new JArray();
        JObject searchItem = new JObject();
        JObject item;
        DataTable dt;
        string sql;

        searchItem = [
            new JProperty("defaultHidden", true),
            new JProperty("field","value"),
            new JProperty("label","讲师ID"),
        ];
        TableColumn.Add(searchItem);
        searchItem = [
            new JProperty("field","label"),
            new JProperty("label","讲师名称"),
        ];
        TableColumn.Add(searchItem);

        sql = "SELECT Id, TeacherNo , TeacherName FROM Ghre_Teacher WHERE IsEnable=1 ";

        if (linkId != null)
            sql += $"AND SchoolId ='{linkId}'";
        dt = await Db.Ado.GetDataTableAsync(sql);

        for (int i = 0; i < dt.Rows.Count; i++)
        {
            item = [
                new JProperty("value",long.Parse(dt.Rows[i]["Id"].ToString())),
                new JProperty("label",dt.Rows[i]["TeacherNo"].ToString()+"-"+dt.Rows[i]["TeacherName"].ToString())
                ];
            DT_TableDataT1.Add(item);
        }

        item = [
            new JProperty("ListMax",100),
                    new JProperty("ListMin",10),
                    new JProperty("PageNum",1),
                    new JProperty("PageSize",99999),
                    new JProperty("TotalCount",dt.Rows.Count),
                    new JProperty("UIType","Auto")
            ];
        DT_TablePageInfoT1.Add(item);

        result.JM_TableColumnT1.TableColumn = TableColumn;
        result.DT_TableDataT1 = DT_TableDataT1;
        result.DT_TablePageInfoT1 = DT_TablePageInfoT1;
        return new ServiceResult<CommonSelect>() { Success = true, Message = "查询成功", Data = result, };

    }

    public override async Task<ServiceFormResult> QueryForm(QueryForm body)
    {
        var result = new ServiceFormResult();
        string sql = string.Empty;
        var dt = new DataTable();

        if (body.id != null)
        {
            Type entityType = typeof(Ghre_Course);
            sql = @$"DECLARE @langId   INT = '{body.langId}',@ID BIGINT = '{body.id}';

                SELECT *,
                         isnull
                         ((SELECT CASE WHEN @langId = 1 THEN UserName ELSE UserEname END
                           FROM Ghrs_User kk
                           WHERE kk.UserId = a.CreateBy),
                          '')
                       + ' '
                       + [dbo].[FLangKeyToValue] ('GHR_Common_000078', @langId, '于 ')
                       + ' '
                       + CONVERT (NVARCHAR (16), CreateTime, 121)
                       + ' '
                       + [dbo].[FLangKeyToValue] ('GHR_Common_000079', @langId, ' 创建')
                          CreateDataInfo,
                         isnull
                         ((SELECT CASE WHEN @langId = 1 THEN UserName ELSE UserEname END
                           FROM Ghrs_User kk
                           WHERE kk.UserId = a.UpdateBy),
                          '')
                       + ' '
                       + [dbo].[FLangKeyToValue] ('GHR_Common_000078', @langId, '于')
                       + ' '
                       + CONVERT (NVARCHAR (16), UpdateTime, 121)
                       + ' '
                       + [dbo].[FLangKeyToValue]
                         ('GHR_Common_000080', @langId, ' 最后修改')
                          UpdateDataInfo
                FROM {entityType.GetEntityTableName()} a
                WHERE a.Id = @ID";

            var list = await Db.Ado.SqlQueryAsync<Ghre_CourseDto>(sql);

            list.ForEach(x =>
            {
                if (!string.IsNullOrWhiteSpace(x.ExamPaperId))
                    x.ExamPaperIds = JsonHelper.JsonToObj<List<long>>(x.ExamPaperId);
            });
            result.result.DT_TableDataT1 = list;

        }
        else
        {
            var list = new List<Ghre_Course>
            {
                new()
            };

            result.result.DT_TableDataT1 = Mapper.Map(list).ToANew<List<Ghre_CourseDto>>();
        }
        #region JM_PageFormActionsT1
        dynamic JM_PageFormActionsT1 = new ExpandoObject();

        var toolbars = await _caching.GetAsync<List<FormToolbar>>(body.menuName + "FormToolbar");
        if (toolbars == null || (toolbars != null && !toolbars.Any()))
        {
            sql = @$"SELECT field fnKey, [dbo].[FLangKeyToValue] (mkey, {body.langId}, label) fnTitle, icon
                FROM Ghrs_PageSettingEdit
                WHERE IsEnable = 1 AND pageNo = '{body.menuName}' AND elementType = 'FnKey'";
            toolbars = await Db.Ado.SqlQueryAsync<FormToolbar>(sql);
            if (toolbars.Any())
                await _caching.SetAsync(body.menuName + "FormToolbar", toolbars);
        }


        JM_PageFormActionsT1.Toolbar = toolbars;
        #endregion

        #region JM_TableColumnT1
        dynamic JM_TableColumnT1 = new ExpandoObject();
        var tableColumn = new JArray();
        sql = @$"SELECT field,
                       [dbo].[FLangKeyToValue] (mkey, {body.langId}, label)
                          label,
                       required,
                       editable,
                       rowNum,
                       colNum,
                       elementType,
                       dbo.FS_GetdataSourceBySet
                       (dataSource, APIDataSourceType, Ghrs_PageSettingEdit.APIDataSourceID)
                          dataSource,
                       defaultHidden,
                       isPrimaryKey,
                       isSingleColumn,multipleSelect
                FROM Ghrs_PageSettingEdit
                WHERE     IsEnable = 1
                      AND pageNo = '{body.menuName}'
                      AND elementType NOT IN ('FnKey', 'PageGroup');";
        dt = await Db.Ado.GetDataTableAsync(sql);

        for (int i = 0; i < dt.Rows.Count; i++)
        {
            string dataSource = dt.Rows[i]["dataSource"].ToString();
            string field = dt.Rows[i]["field"].ToString();
            if (field == "SchoolTeacherId")
                dataSource = "api/Ghre_Course/GetSelect?FW=DOTNETCORE&linkId=";
            JObject item =
                [
                new JProperty("field",field),
                new JProperty("label", dt.Rows[i]["label"].ToString()),
                new JProperty("required",!string.IsNullOrWhiteSpace(dt.Rows[i]["required"].ToString())? Convert.ToBoolean(dt.Rows[i]["required"]):null),
                new JProperty("editable",!string.IsNullOrWhiteSpace(dt.Rows[i]["editable"].ToString())? Convert.ToBoolean(dt.Rows[i]["editable"]):null),
                new JProperty("rowNum",!string.IsNullOrWhiteSpace(dt.Rows[i]["rowNum"].ToString())? Convert.ToInt32(dt.Rows[i]["rowNum"]):null),
                new JProperty("colNum",!string.IsNullOrWhiteSpace(dt.Rows[i]["colNum"].ToString())? Convert.ToInt32(dt.Rows[i]["colNum"]):null),
                new JProperty("elementType", dt.Rows[i]["elementType"].ToString()),
                new JProperty("dataSource", dataSource),
                new JProperty("defaultHidden", dt.Rows[i]["defaultHidden"].ToString()),
                new JProperty("isPrimaryKey", !string.IsNullOrWhiteSpace(dt.Rows[i]["isPrimaryKey"].ToString())? Convert.ToBoolean(dt.Rows[i]["isPrimaryKey"]):null),
                new JProperty("isSingleColumn",!string.IsNullOrWhiteSpace(dt.Rows[i]["isSingleColumn"].ToString())? Convert.ToInt32(dt.Rows[i]["isSingleColumn"]):null),
                new JProperty("multipleSelect",!string.IsNullOrWhiteSpace(dt.Rows[i]["multipleSelect"].ToString())? Convert.ToBoolean(dt.Rows[i]["multipleSelect"]):null),
                ];
            tableColumn.Add(item);
        }
        JM_TableColumnT1.TableColumn = tableColumn;
        #endregion

        #region JM_PageFormT1
        dynamic JM_PageFormT1 = new ExpandoObject();
        var pageForm = new JArray();
        JObject pageFormItem =
            [
            new JProperty("disabled", false),
            new JProperty("labelAlign", "right"),
            new JProperty("labelCol", "{span: 6}"),
            new JProperty("labelWidth",120),
            new JProperty("layout", "horizontal")
            ];

        sql = $@"SELECT [dbo].[FLangKeyToValue] (MKey, {body.langId}, MenuName) pageTitle,
                       IUDProcedure apiName
                FROM Ghrs_Menu
                WHERE MenuNo = '{body.menuName}' AND IsEnable = 1";
        dt = await Db.Ado.GetDataTableAsync(sql);
        if (dt.Rows.Count > 0)
        {
            pageFormItem.Add(new JProperty("pageTitle", dt.Rows[0]["pageTitle"].ToString()));
            pageFormItem.Add(new JProperty("apiName", dt.Rows[0]["apiName"].ToString()));
        }
        pageForm.Add(pageFormItem);
        JM_PageFormT1.PageForm = pageForm;
        #endregion

        #region DT_PageMutiMsg
        var DT_PageMutiMsg = await _caching.GetAsync<List<DT_PageMutiMsg>>("DT_PageMutiMsg");
        if (DT_PageMutiMsg == null || (DT_PageMutiMsg != null && !DT_PageMutiMsg.Any()))
        {
            sql = $@"SELECT Langkey field,
                       CASE {body.langId}
                          WHEN 1 THEN isnull (Value01, LangValue)
                          WHEN 2 THEN isnull (Value02, LangValue)
                          WHEN 3 THEN isnull (Value03, LangValue)
                          WHEN 4 THEN isnull (Value04, LangValue)
                          WHEN 5 THEN isnull (Value05, LangValue)
                          WHEN 6 THEN isnull (Value06, LangValue)
                          WHEN 7 THEN isnull (Value07, LangValue)
                          WHEN 8 THEN isnull (Value08, LangValue)
                          WHEN 9 THEN isnull (Value09, LangValue)
                          WHEN 10 THEN isnull (Value10, LangValue)
                       END label
                FROM Ghrs_LangKey
                WHERE     (LangKey LIKE 'GHR_Page%' OR LangKey LIKE 'GHR_Common%')
                      AND IsEnable = 1";
            DT_PageMutiMsg = Db.Ado.SqlQuery<DT_PageMutiMsg>(sql);
            if (DT_PageMutiMsg.Any())
                await _caching.SetAsync("DT_PageMutiMsg", DT_PageMutiMsg);
        }
        #endregion

        result.result.JM_PageFormActionsT1 = JM_PageFormActionsT1;
        result.result.JM_TableColumnT1 = JM_TableColumnT1;
        result.result.JM_PageFormT1 = JM_PageFormT1;
        result.result.DT_PageMutiMsg = DT_PageMutiMsg;
        return result;
    }


    public async Task<ServiceResult> UpdateStatus(long[] ids, string status)
    {
        if (status != "Released" && status != "Disabled" && status != "Draft")
            throw new Exception("无效的状态");

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

        var entities = new List<Ghre_Course>();
        foreach (var id in ids)
        {
            if (id == null || !BaseDal.Any(id))
                continue;

            var entity = await BaseDal.QueryById(id);

            BasePoco ent = entity;
            ent.UpdateIP = ip;
            ent.UpdateProg = api;
            if (status == "Released" || status == "Disabled" || status == "Draft")
            {
                entity.Status = status;
                entities.Add(entity);
            }
        }

        var result = await BaseDal.Update(entities);
        if (status == "Released")
            return ServiceResult.OprateSuccess("发布成功！");
        else if (status == "Draft")
            return ServiceResult.OprateSuccess("取消发布成功！");
        else
            return ServiceResult.OprateSuccess("停用成功！");

    }

    public override async Task<long> Add(InsertGhre_CourseInput entity)
    {
        entity.ExamPaperId = JsonHelper.ObjToJson(entity.ExamPaperIds);
        entity.Status = "Draft";
        return await base.Add(entity);
    }

    public override async Task<bool> Update(long Id, EditGhre_CourseInput editModel)
    {

        editModel.ExamPaperId = JsonHelper.ObjToJson(editModel.ExamPaperIds);
        return await base.Update(Id, editModel);
    }
}