using APT.BaseData.Domain.ApiModel.EX;
using APT.BaseData.Domain.Entities.FM;
using APT.BaseData.Domain.Enums;
using APT.BaseData.Domain.IServices.FM;
using APT.Infrastructure.Api;
using APT.Infrastructure.Core;
using APT.Migrations;
using System;
using System.Collections.Generic;
using System.Linq;
using static APT.BaseData.Domain.ApiModel.SocketInfo;

namespace APT.BaseData.Services.Services.FM
{
    public class NotificationService : CommonService, IFMNotificatoinService
    {
        public NotificationService(IRepository repository)
            : base(repository)
        {

        }

        private T_FM_NOTIFICATION AddNotification(SendNotificationModel model, List<T_FM_NOTIFICATION> addNotifications,
                List<T_FM_NOTIFICATION_PERMIT> addNotificationPermits)
        {

            if (model == null) return null;
            T_FM_NOTIFICATION notification = new T_FM_NOTIFICATION();
            notification.TITLE = model.Title;
            notification.ECMSAGE = model.Message;
            notification.NOTIFICATION_SHOW_TYPE = model.ShowInfoType;
            notification.NOTIFICATION_CLIENT_TYPE = model.ClientType;
            notification.ORG_ID = model.OrgId;
            notification.USER_ID = model.UserId;
            addNotifications.Add(notification);

            SysPermission sysPermission = Infrastructure.Api.AppContext.SysPermission;
            if (model.CheckOrgType == (int)FMNotificationOrgTypeEnum.本组织)
            {
                T_FM_NOTIFICATION_PERMIT permit = new T_FM_NOTIFICATION_PERMIT();
                permit.ORG_ID = notification.ORG_ID;
                permit.NOTIFICATION_ID = notification.ID;
                permit.PERMIT_TYPE = (int)FMNotificationPermitTypeEnum.组织;
                permit.PERMIT_KEY_ID = notification.ORG_ID;
                addNotificationPermits.Add(permit);
            }
            else if (model.CheckOrgType == (int)FMNotificationOrgTypeEnum.本组织及下级组织)
            {
                List<Guid> orgIds = new List<Guid>();
                orgIds.Add(notification.ORG_ID.Value);

                OrgCache orgCache = null;
                if (notification.ORG_ID != null &&
                        sysPermission.OrgCaches.TryGetValue(notification.ORG_ID.Value, out orgCache))
                    orgIds.AddRange(orgCache.AllChildrenIds);
                foreach (var item in orgIds)
                {
                    T_FM_NOTIFICATION_PERMIT permit = new T_FM_NOTIFICATION_PERMIT();
                    permit.ORG_ID = notification.ORG_ID;
                    permit.NOTIFICATION_ID = notification.ID;
                    permit.PERMIT_TYPE = (int)FMNotificationPermitTypeEnum.组织;
                    permit.PERMIT_KEY_ID = item;
                    addNotificationPermits.Add(permit);
                }
            }
            else if (model.CheckOrgType == (int)FMNotificationOrgTypeEnum.忽略组织)
            {
                T_FM_NOTIFICATION_PERMIT permit = new T_FM_NOTIFICATION_PERMIT();
                permit.ORG_ID = notification.ORG_ID;
                permit.NOTIFICATION_ID = notification.ID;
                permit.PERMIT_TYPE = (int)FMNotificationPermitTypeEnum.所有人;
                addNotificationPermits.Add(permit);
            }
            return notification;

        }

        /// <summary>
        /// 发送通知公告
        /// </summary>
        /// <param name="notificationType"></param>
        /// <param name="title"></param>
        /// <param name="message"></param>
        public void SendNotification(FMNotificationTypeEnum notificationType, FMNotificationClientTypeEnum clientType,
                string title, string message)
        {

            SendNotificationModel sendNotificationModel = new SendNotificationModel();
            sendNotificationModel.CheckOrgType = (int)FMNotificationOrgTypeEnum.本组织;
            sendNotificationModel.ShowInfoType = (int)FMNotificationShowTypeEnum.弹窗;
            sendNotificationModel.Title = title;
            sendNotificationModel.ClientType = (int)clientType;
            sendNotificationModel.Message = message;
            sendNotificationModel.NotificatoinType = (int)notificationType;
            if (Infrastructure.Api.AppContext.CurrentSession != null)
            {
                sendNotificationModel.UserId = Infrastructure.Api.AppContext.CurrentSession.UserID;
                sendNotificationModel.OrgId = Infrastructure.Api.AppContext.CurrentSession.OrgId;
            }
            List<WebSocketClientInfo> clientInfos = null;
            if (sendNotificationModel.UserId != null)
                clientInfos = WebSocketServiceHelper.ClintInfos.Where(t => t.UserId == sendNotificationModel.UserId).ToList();
            SendNotification(sendNotificationModel, clientInfos);

        }



        /// <summary>
        /// 发送通知公告
        /// </summary>
        /// <param name="sendNotificationModel"></param>
        /// <param name="ingoreClientInfos"></param>
        public void SendNotification(SendNotificationModel sendNotificationModel, List<WebSocketClientInfo> clientInfos)
        {
            if (clientInfos.Count == 0)
                return;
            var defClient = clientInfos.FirstOrDefault();
            if (string.IsNullOrEmpty(defClient.DbConn))
                return;
            using (var context = new MigrationContext(defClient.DbConn))
            {
                if (sendNotificationModel == null) return;
                SysPermission sysPermission = Infrastructure.Api.AppContext.SysPermission;
                var orgId = sendNotificationModel.OrgId != null ? sendNotificationModel.OrgId :
                    (defClient.OrgId);
                List<T_FM_NOTIFICATION> addNotifications = new List<T_FM_NOTIFICATION>();
                List<T_FM_NOTIFICATION_PERMIT> addNotificationPermits = new List<T_FM_NOTIFICATION_PERMIT>();
                List<T_FM_NOTIFICATION_ACCEPTED> addNotificationAccepts = new List<T_FM_NOTIFICATION_ACCEPTED>();
                var notification = this.AddNotification(sendNotificationModel, addNotifications, addNotificationPermits);

                NotificationModel notificationModel = new NotificationModel();
                notificationModel.NotificationId = notification.ID;
                notificationModel.Title = sendNotificationModel.Title;
                notificationModel.Message = sendNotificationModel.Message;
                notificationModel.ShowInfoType = sendNotificationModel.ShowInfoType;
                notificationModel.Time = DateTime.Now;
                notificationModel.NotificatoinType = sendNotificationModel.NotificatoinType;


                clientInfos.ForEach(t =>
                        {
                            if (t.UserId != null)
                            {
                                T_FM_NOTIFICATION_ACCEPTED accept = new T_FM_NOTIFICATION_ACCEPTED();
                                accept.ORG_ID = notification.ORG_ID;
                                accept.NOTIFICATION_ID = notification.ID;
                                accept.USER_ID = t.UserId.Value;
                                addNotificationAccepts.Add(accept);
                            }
                        });

                //var commonService = ServiceLocator.Instance.GetService<ICommonService>();
                if (sendNotificationModel.UserId != null)
                {
                    notificationModel.UserId = sendNotificationModel.UserId;

                    var user = context.GetEntity<T_FM_USER>(i => i.ID == sendNotificationModel.UserId, null);
                    if (user != null)
                        notificationModel.UserName = user.NAME;
                }
                WebSocketServiceHelper.SendToAll(new WebSocketResponseInfo()
                {
                    TypeCode = "M001",
                    Data = notificationModel
                }, (t) =>
                {
                    bool ret = false;
                    if (t.ClientType != WebSocketClientTypeEnum.默认 &&
                         sendNotificationModel.ClientType != (int)FMNotificationClientTypeEnum.默认 &&
                             t.ClientType != (WebSocketClientTypeEnum)sendNotificationModel.ClientType)
                        ret = false;
                    if (clientInfos.Any(t1 => t1 == t))
                        ret = false;
                    else if (sendNotificationModel.CheckOrgType == (int)FMNotificationOrgTypeEnum.本组织)
                    {
                        ret = t.OrgId != null && orgId != null && t.OrgId == orgId;
                    }
                    else if (sendNotificationModel.CheckOrgType == (int)FMNotificationOrgTypeEnum.本组织及下级组织)
                    {
                        if (t.OrgId != null && orgId != null && t.OrgId == orgId) ret = true;
                        if (sysPermission != null)
                        {
                            OrgCache orgCache = null;
                            if (orgId != null && sysPermission.OrgCaches.TryGetValue(orgId.Value, out orgCache))
                                ret = t.OrgId != null && orgCache.AllChildrenIds.Contains(t.OrgId.Value);
                        }
                    }
                    else if (sendNotificationModel.CheckOrgType == (int)FMNotificationOrgTypeEnum.忽略组织)
                    {
                        ret = true;
                    }
                    return ret;
                });
                context.Add(addNotifications);
                context.Add(addNotificationPermits);
                context.Add(addNotificationAccepts);
                context.SaveChanges();
            }
        }

        /// <summary>
        /// 发送报警通知公告
        /// </summary>
        /// <param name="sendNotificationModel"></param>
        /// <param name="ingoreClientInfos"></param>
        public void SendAlarmNotification(SendNotificationModel sendNotificationModel, List<WebSocketClientInfo> clientInfos)
        {
            if (clientInfos.Count == 0)
                return;
            var defClient = clientInfos.FirstOrDefault();
            if (string.IsNullOrEmpty(defClient.DbConn))
                return;
            using (var context = new MigrationContext(defClient.DbConn))
            {
                if (sendNotificationModel.AlarmId != null)
                {
                    //var alarm = context.GetEntity<T_KR_ALARM_NOTIFICATION>(i => i.ID == sendNotificationModel.AlarmId, null);
                    //alarm.STATUS = (int)KRMessagStatus.已读;
                    //context.UpdateEntity(alarm);
                    //context.SaveChanges();
                }
                SysPermission sysPermission = Infrastructure.Api.AppContext.SysPermission;
                var orgId = sendNotificationModel.OrgId != null ? sendNotificationModel.OrgId :
                    (defClient.OrgId);
                var commonService = ServiceLocator.Instance.GetService<ICommonService>();
                foreach (var item in clientInfos)
                {
                    var userId = item.UserId ?? Guid.Empty;

                    var orders = new Dictionary<string, DbOrder>();
                    orders.Add("CREATE_TIME", DbOrder.DESC);
                    var selectField = new string[] { "ID", "USER_ID", "STATUS", "CREATE_TIME", "Nav_AlarmLog.DESCRIBE", "Nav_AlarmLog.Nav_Equipment.NAME", "Nav_AlarmLog.Nav_Appliance.NAME" };
                    //var alarms = context.GetOrderPageEntities<T_KR_ALARM_NOTIFICATION>(x => x.USER_ID == userId && x.STATUS == (int)KRMessagStatus.未读, orders, null, 1, 0,
                    //    "Nav_AlarmLog.Nav_Equipment", "Nav_AlarmLog.Nav_Appliance");
                    //var lastAlarm = alarms.Items.FirstOrDefault();
                    //var total = 0;
                    //if (lastAlarm != null)
                    //{
                    //    total = alarms.TotalCount;
                    //}
                    //var model = new AlarmNotificationModel
                    //{
                    //    AlarmId = lastAlarm?.ID,
                    //    Message = lastAlarm == null ? ""
                    //    : "[" + lastAlarm?.Nav_AlarmLog?.Nav_Equipment?.NAME + lastAlarm?.Nav_AlarmLog?.Nav_Appliance?.NAME + "]" + lastAlarm?.Nav_AlarmLog?.DESCRIBE,
                    //    TotalCount = total
                    //};
                    //WebSocketServiceHelper.SendToUser(userId, new WebSocketResponseInfo()
                    //{
                    //    TypeCode = "M0003",
                    //    Data = model
                    //});
                }
            }
        }

        public void SendNotification(Guid userId, SocketData socketData)
        {
            WebSocketServiceHelper.SendToUser(userId, new WebSocketResponseInfo()
            {
                TypeCode = "MQ01",
                Data = socketData
            });
        }
    }
}
