using APT.BaseData.Domain.Enums;
using APT.BaseData.Domain.IServices;
using APT.Infrastructure.Core;
using APT.BaseData.Domain.ApiModel.EX;
using APT.BaseData.Domain.ApiModel.FM;
using APT.BaseData.Domain.IServices.FM;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using APT.BaseData.Domain.Enums.PF;
using APT.BaseData.Domain.Entities;
using APT.Utility;
using APT.Infrastructure.Api;

namespace APT.PF.WebApi.Controllers.Api.EX
{
    [Route("api/PF/Extend")]
    public class ExtendController : CommonApiController
    {
        /// <summary>
        /// 根据ID获得实体数据
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpGet, Route("Enum")]
        public JsonActionResult<string> Enum(string name)
        {
            return SafeExecute<string>(() =>
            {
                return APT.Utility.DataHelper.EnumToString(name);
            });
        }

        /// <summary>
        /// 根据枚举名称 获取 某个枚举
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpGet, Route("GetEnum")]
        public JsonActionResult<dynamic> GetEnum(string name)
        {
            return SafeExecute<dynamic>(() =>
            {
                return APT.Utility.DataHelper.GetEnum(name);
            });
        }

        /// <summary>
        /// 获取所有枚举信息
        /// </summary>
        /// <returns></returns>
        [HttpGet, Route("GetAllEnum")]
        public JsonActionResult<IEnumerable<APT.Utility.EnumInfo>> GetAllEnum()
        {
            return SafeExecute<IEnumerable<APT.Utility.EnumInfo>>(() =>
            {
                return APT.Utility.DataHelper.GetAllEnums();
            });
        }

        [HttpPost, Route("EntityOrderPaged")]
        public PagedActionResult<EntityModel> EntityOrderPaged([FromBody] KeywordPageFilter pageFilter)
        {
            return SafeGetPagedData<EntityModel>(ret =>
            {
                var formService = APT.Infrastructure.Api.ServiceLocator.Instance.GetService<IPFFormService>();
                var files = System.IO.Directory.GetFiles(System.AppContext.BaseDirectory, "*.Domain.dll");
                var tempFiles = System.IO.Directory.GetFiles(System.AppContext.BaseDirectory, "APT.Infrastructure.Core.dll");
                if (files == null)
                    files = tempFiles;
                else if (tempFiles != null)
                {
                    var temps = files.ToList();
                    temps.AddRange(tempFiles);
                    files = temps.ToArray();
                }
                if (files == null || !files.Any()) return;
                List<EntityModel> list = new List<EntityModel>();
                foreach (var file in files)
                {
                    var assembly = Assembly.LoadFrom(file);
                    if (assembly == null) continue;
                    foreach (var t in assembly.ExportedTypes)
                    {
                        var baseType = t.BaseType;
                        if (baseType == typeof(MesEntityBase) || baseType == typeof(MesTreeEntityBase))
                        {
                            EntityModel entityModel = new EntityModel();
                            string entityName = t.Name;
                            entityModel.EntityName = entityName;
                            entityModel.Label = t.Name;

                            var attrs = t.GetCustomAttributes(typeof(DescriptionAttribute), false);
                            if (attrs != null && attrs.Any())
                            {
                                var descAttr = attrs[0] as DescriptionAttribute;
                                entityModel.Label = descAttr.Description;
                            }
                            #region  设置模块
                            entityModel.ModuleType = (int)formService.GetModelTypeByName(entityName);
                            #endregion

                            list.Add(entityModel);
                        }
                    }
                }
                Expression<Func<EntityModel, bool>> predicate = t => true;
                predicate = predicate.And(FilterHelper.GetExpression<EntityModel>(pageFilter.FilterGroup, null));
                list = list.Where(predicate.Compile()).OrderBy(t => t.EntityName).ToList();
                ret.TotalCount = list.Count;
                ret.Data = list.Skip(pageFilter.Start).Take(pageFilter.Limit).ToArray();
            });
        }


        [HttpPost, Route("EntityFieldOrderPaged")]
        public PagedActionResult<EntityFieldModel> EntityFieldOrderPaged([FromBody] KeywordPageFilter pageFilter)
        {
            return SafeGetPagedData<EntityFieldModel>(ret =>
            {
                var list = GetTableField(pageFilter);
                ret.TotalCount = list.Count;
                ret.Data = list.Skip(pageFilter.Start).Take(pageFilter.Limit).ToArray();
            });
        }
        private List<EntityFieldModel> GetTableField(KeywordPageFilter pageFilter, string parentName = "")
        {
            List<EntityFieldModel> list = new List<EntityFieldModel>();
            if (string.IsNullOrEmpty(pageFilter.Keyword)) return list;
            var entityType = APT.Utility.DataHelper.GetTypeByEntityName(pageFilter.Keyword);
            if (entityType == null) return list;
            foreach (var property in entityType.GetProperties())
            {
                var propertyType = property.PropertyType;
                EntityFieldModel entityField = new EntityFieldModel();
                entityField.ID = property.Name + "." + propertyType.Name;
                entityField.Field = property.Name;
                entityField.NavField = property.Name;
                if (!string.IsNullOrEmpty(parentName))
                {
                    entityField.ID = parentName + "." + entityField.ID;
                    entityField.NavField = parentName + "." + entityField.NavField;
                }
                entityField.FieldTypeName = propertyType.Name;
                entityField.Label = entityField.Field;
                var attrs = property.GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (attrs != null && attrs.Any())
                {
                    var descAttr = attrs[0] as DescriptionAttribute;
                    entityField.Label = descAttr.Description;
                }
                if (entityField.Field.StartsWith("VIR_", StringComparison.OrdinalIgnoreCase) ||
                    entityField.Field.StartsWith("VIRTUAL_", StringComparison.OrdinalIgnoreCase) ||
                     entityField.Field.ToUpper() != entityField.Field)
                    entityField.FieldType = (int)EntityFieldTypeEnum.虚字段;

                //判断是否为泛型
                if (propertyType.IsGenericType)
                {
                    #region 泛型类型
                    var types = propertyType.GetGenericArguments();
                    Type realType = null;
                    if (types != null && types.Any())
                        realType = types[0];
                    var genericType = propertyType.GetGenericTypeDefinition();
                    var genericTypeName = genericType.Name.Substring(0, genericType.Name.Length - 2);
                    if (genericTypeName.Contains("Nullable"))
                        entityField.FieldTypeName = realType.Name + " ?";
                    else
                        entityField.FieldTypeName = genericTypeName + "<" + realType.Name + ">";
                    if (realType.IsClass)
                    {
                        var baseType = realType.BaseType;
                        if (baseType == typeof(MesEntityBase) || baseType == typeof(MesTreeEntityBase))
                        {
                            entityField.FieldEntityName = realType.Name;
                            entityField.FieldType = (int)EntityFieldTypeEnum.导航字段;
                        }
                    }
                    #endregion
                }
                else if (propertyType.IsClass) //如果属性类型为Class并且继承至系统基类 则为导航属性
                {
                    var baseType = propertyType.BaseType;
                    if (baseType == typeof(MesEntityBase) || baseType == typeof(MesTreeEntityBase))
                    {
                        entityField.FieldEntityName = propertyType.Name;
                        entityField.FieldType = (int)EntityFieldTypeEnum.导航字段;
                    }
                }


                #region 添加字段额外信息
                StringBuilder stringBuilder = new StringBuilder();
                attrs = property.GetCustomAttributes(typeof(EnumNameAttribute), false);
                if (attrs != null && attrs.Any())
                {
                    var enumAttr = attrs[0] as EnumNameAttribute;
                    stringBuilder.Append("枚举:" + enumAttr.EnumName);
                    stringBuilder.Append(";");
                }
                attrs = property.GetCustomAttributes(typeof(CUniqueAttribute), false);
                if (attrs != null && attrs.Any())
                {
                    stringBuilder.Append("字段唯一");
                    stringBuilder.Append(";");
                }
                attrs = property.GetCustomAttributes(typeof(CodeRuleAttribute), false);
                if (attrs != null && attrs.Any())
                {
                    var codeRuleAttr = attrs[0] as CodeRuleAttribute;
                    if (codeRuleAttr.CodeRuleTypes != null && codeRuleAttr.CodeRuleTypes.Any())
                    {
                        stringBuilder.Append("编码类型:");
                        foreach (var ct in codeRuleAttr.CodeRuleTypes)
                            stringBuilder.Append(System.Enum.GetName(typeof(PFCodeRuleType), ct) + "(" + ct + "),");
                        stringBuilder.Append(";");
                    }
                }
                if (stringBuilder.Length > 0)
                {
                    stringBuilder.Length--;
                    entityField.FieldInfo = stringBuilder.ToString();
                }
                #endregion


                list.Add(entityField);
            }
            Expression<Func<EntityFieldModel, bool>> predicate = t => true;
            predicate = predicate.And(FilterHelper.GetExpression<EntityFieldModel>(pageFilter.FilterGroup, null));
            list = list.Where(predicate.Compile()).OrderBy(t => t.Field).ToList();
            return list;
        }


        [HttpPost, Route("TreeEntityField")]
        public PagedActionResult<EntityFieldModel> TreeEntityField([FromBody] KeywordPageFilter pageFilter)
        {

            return SafeGetPagedData<EntityFieldModel>((result) =>
            {

                List<EntityFieldModel> list = new List<EntityFieldModel>();
                //var filedType = (int)PFFieldTypeEnum.表字段;
                //if (!string.IsNullOrEmpty(pageFilter.Parameter1))
                //    filedType = int.Parse(pageFilter.Parameter1);
                //if (string.IsNullOrEmpty(pageFilter.Keyword))
                //    return list;
                //if (filedType == (int)PFFieldTypeEnum.表字段)
                //{
                //    var parentField = pageFilter.FilterGroup.Rules.FirstOrDefault(x => x.Field == "PARENT_ID");
                //    var parentName = "";
                //    if (parentField == null)
                //    {
                //        var form = this.GetEntityByRedis<T_PF_FORM>(pageFilter.Keyword, pageFilter.GetOrgId());
                //        if (form == null)
                //            this.ThrowError("020015");
                //        if (string.IsNullOrEmpty(form.TABLE_NAME))
                //            this.ThrowError("020016");
                //        pageFilter.Keyword = form.TABLE_NAME;
                //    }
                //    else
                //    {
                //        var infos = parentField.Value.ToString().Split(new char[] { '.' });
                //        pageFilter.Keyword = infos[infos.Length - 1];
                //        parentName = string.Join('.', infos.Take(infos.Length - 1));
                //        parentName = parentName.Trim('.');
                //        pageFilter.FilterGroup.Rules.Clear();
                //    }
                //    var pagelist = GetTableField(pageFilter, parentName);
                //    foreach (var d in pagelist)
                //    {
                //        var treeNode = new TreeNode<EntityFieldModel>();
                //        treeNode.Node = d;
                //        treeNode.IsLeaf = true;
                //        treeNode.Level = 0;
                //        if (d.FieldType == (int)EntityFieldTypeEnum.导航字段|| d.FieldType == (int)EntityFieldTypeEnum.虚字段)
                //        {
                //            treeNode.IsLeaf = false;
                //        }
                //        list.Add(treeNode);
                //    }
                //}
                //else
                //{
                Dictionary<string, string> dicTree = new Dictionary<string, string>();
                dicTree.Add("层级", "Level");
                dicTree.Add("是否叶子", "IsLeaf");
                foreach (var key in dicTree.Keys)
                {
                    var model = new EntityFieldModel()
                    {
                        NavField = dicTree[key],
                        Label = key,
                        FIELD_TYPE = (int)PFFieldTypeEnum.树字段,
                        ID = Guid.NewGuid().ToString(),
                    };
                    list.Add(model);
                }
                //}
                result.Data = list.Skip(pageFilter.Start).Take(pageFilter.Limit);
                result.TotalCount = list.Count;
            });


        }

        [HttpPost, Route("EntityField")]
        public JsonActionResult<IEnumerable<TreeNode<EntityFieldModel>>> EntityField([FromBody] KeywordPageFilter pageFilter)
        {

            return SafeExecute<IEnumerable<TreeNode<EntityFieldModel>>>(() =>
            {

                List<TreeNode<EntityFieldModel>> list = new List<TreeNode<EntityFieldModel>>();
                //var filedType = (int)PFFieldTypeEnum.表字段;
                //if (!string.IsNullOrEmpty(pageFilter.Parameter1))
                //    filedType = int.Parse(pageFilter.Parameter1);
                if (string.IsNullOrEmpty(pageFilter.Keyword))
                    return list;
                //if (filedType == (int)PFFieldTypeEnum.表字段)
                //{
                //导航属性格式：Nav_Appliance.T_BD_APPLIANCE ，字段名称+.+字段累类型
                var parentField = pageFilter.FilterGroup.Rules.FirstOrDefault(x => x.Field == "PARENT_ID");
                var parentName = "";
                if (parentField == null)
                {
                    var form = this.GetEntityByRedis<T_PF_FORM>(pageFilter.Keyword, pageFilter.GetOrgId());
                    if (form == null)
                        this.ThrowError("020015");
                    if (string.IsNullOrEmpty(form.TABLE_NAME))
                        this.ThrowError("020016");
                    pageFilter.Keyword = form.TABLE_NAME;
                }
                else
                {
                    var infos = parentField.Value.ToString().Split(new char[] { '.' });
                    pageFilter.Keyword = infos[infos.Length - 1];
                    parentName = string.Join('.', infos.Take(infos.Length - 1));
                    parentName = parentName.Trim('.');
                    pageFilter.FilterGroup.Rules.Clear();
                }
                var pagelist = GetTableField(pageFilter, parentName);
                foreach (var d in pagelist)
                {
                    d.FIELD_TYPE = (int)PFFieldTypeEnum.表字段;
                    var treeNode = new TreeNode<EntityFieldModel>();
                    treeNode.Node = d;
                    treeNode.IsLeaf = true;
                    treeNode.Level = 0;
                    if (d.FieldType == (int)EntityFieldTypeEnum.导航字段 || d.FieldType == (int)EntityFieldTypeEnum.虚字段)
                    {
                        treeNode.IsLeaf = false;
                    }
                    list.Add(treeNode);
                }
     
                //}
                //else
                //{
                //    Dictionary<string, string> dicTree = new Dictionary<string, string>();
                //    dicTree.Add("层级", "Level");
                //    dicTree.Add("是否叶子", "IsLeaf");
                //    foreach (var key in dicTree.Keys)
                //    {
                //        var model = new EntityFieldModel()
                //        {
                //            NavField = dicTree[key],
                //            Label = key,
                //        };
                //        var treeNode = new TreeNode<EntityFieldModel>();
                //        treeNode.Node = model;
                //        treeNode.IsLeaf = true;
                //        treeNode.Level = 0;
                //        list.Add(treeNode);
                //    }
                //}
                return list;
            });


        }
        /// <summary>
        /// 向web客户端发送消息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, Route("SendInfo")]
        public JsonActionResult<bool> SendInfo([FromBody] SendNotificationModel model)
        {
            return SafeExecute<bool>(() =>
            {
                List<WebSocketClientInfo> clientInfos = null;
                if (model.UserId != null)
                    clientInfos = WebSocketServiceHelper.ClintInfos.Where(t => t.UserId == model.UserId).ToList();
                var notificatoinService = APT.Infrastructure.Api.ServiceLocator.Instance.GetService<IFMNotificatoinService>();
                notificatoinService.SendNotification(model, clientInfos);
                return true;
            });
        }

        /// <summary>
        /// 向web客户端发送报警消息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, Route("SendAlarmInfo")]
        public JsonActionResult<bool> SendAlarmInfo([FromBody] SendNotificationModel model)
        {
            return SafeExecute<bool>(() =>
            {
                List<WebSocketClientInfo> clientInfos = null;
                if (model.UserIds.Count > 0)
                    clientInfos = WebSocketServiceHelper.ClintInfos.Where(t => model.UserIds.Contains(t.UserId ?? Guid.Empty)).Distinct(x=>x.UserId).ToList();
                var notificatoinService = ServiceLocator.Instance.GetService<IFMNotificatoinService>();
                notificatoinService.SendAlarmNotification(model, clientInfos);
                return true;
            });
        }
    }
}
