using CrazyStudio.Core.Common.Redis;
using CrazyStudio.Core.Common.Redis.Dto;
using CrazyStudio.Core.Common.Status.Eitities;
using CrazyStudio.Core.Common.Status.Interfaces;
using Fleck;
using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Crypto.Tls;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.PerformanceData;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace CrazyStudio.Core.Common.Status
{
    public class OnlineUsers : IOnlineUser
    {
        /// <summary>
        /// 用户名对应的用户信息，可能为一对一，也可能为一对多
        /// </summary>
        public ConcurrentDictionary<string, List<OnlineUserInfo>> Users { get; set; } = new ConcurrentDictionary<string, List<OnlineUserInfo>>();

        /// <summary>
        /// 链接ID对应的用户信息，一对一
        /// </summary>
        public ConcurrentDictionary<string, OnlineUserInfo> SocketUsers { get; set; } = new ConcurrentDictionary<string, OnlineUserInfo>();

        private RedisHelper _redisHelper;

        private string _serverCLusterTag = string.Empty;
        public OnlineUsers(RedisHelper redisHelper, string serverClusterTag)
        {
            this._redisHelper = redisHelper;
            _serverCLusterTag = serverClusterTag;
        }

        /// <summary>
        /// 添加或者更新用户信息
        /// </summary>
        /// <param name="connectionId">链接ID，唯一</param>
        /// <param name="user">在线用户信息类</param>
        public Task AddOrUpdateUser(string connectionId, OnlineUserInfo user)
        {
            OnlineUserInfo? existUser = null;
            if (!SocketUsers.TryGetValue(connectionId, out existUser))
            {
                existUser = user;
                SocketUsers.TryAdd(connectionId, existUser);
            }

            if (!string.IsNullOrEmpty(existUser.UserName))
            {
                if (Users.TryGetValue(existUser.UserName, out var sameNameUsers))
                {
                    sameNameUsers.Add(user);
                }
                else
                {
                    sameNameUsers = new List<OnlineUserInfo>() { user };
                    Users.TryAdd(existUser.UserName, sameNameUsers);
                }
            }
            return Task.CompletedTask;
        }

        /// <summary>
        /// 根据链接ID移除集合相关用户信息
        /// </summary>
        /// <param name="connectionId">链接ID</param>
        public Task RemoveUserFromId(string connectionId)
        {
            if (SocketUsers.TryRemove(connectionId, out var removeUser))
            {
                if (removeUser != null && Users.TryGetValue(removeUser.UserName, out var existUsers))
                {
                    foreach (var user in existUsers)
                    {
                        if (removeUser.ConnectionId == user.ConnectionId)
                        {
                            existUsers.Remove(user);
                            break;
                        }
                    }
                    if (!existUsers.Any())
                    {
                        Users.TryRemove(removeUser.UserName, out var _);
                    }
                }
            }
            return Task.CompletedTask;
        }

        /// <summary>
        /// 根据用户名移除集合相关用户信息
        /// </summary>
        /// <param name="connectionId">链接ID</param>
        public Task RemoveUserFromName(string userName)
        {
            if (Users.TryRemove(userName, out var removeUsers))
            {
                for (int i = 0; i < removeUsers.Count; i++)
                {
                    SocketUsers.TryRemove(removeUsers[i].ConnectionId, out var _);
                }
            }
            return Task.CompletedTask;
        }

        /// <summary>
        /// 根据用户名获取对应用户名在线用户（可能有多个）
        /// </summary>
        /// <param name="userName"></param>
        /// <returns>对应用户名在线用户信息，找不到就返回空列表</returns>
        public List<OnlineUserInfo> GetUsers(string userName)
        {
            if (!string.IsNullOrEmpty(userName))
            {
                if (Users.TryGetValue(userName, out var sameUsers))
                {
                    return sameUsers;
                }
            }
            return new List<OnlineUserInfo>();
        }


        /// <summary>
        /// 根据链接ID获取对应用户名在线用户（唯一）
        /// </summary>
        /// <param name="connectionId">链接ID</param>
        /// <returns>查询到的在线用户信息，找不到就返回空值</returns>
        public OnlineUserInfo? GetUsersFromConnectionId(string connectionId)
        {
            if (!string.IsNullOrEmpty(connectionId))
            {
                if (SocketUsers.TryGetValue(connectionId, out var user))
                {
                    return user;
                }
            }
            return null;
        }



        /// <summary>
        /// 发送数据给用户名对应的所有链接
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <param name="packet">要发送的字节数组</param>
        /// <returns></returns>
        public async Task SendMessageToUser(string userName, byte[] packet)
        {
            if (!string.IsNullOrEmpty(userName))
            {
                if (Users.TryGetValue(userName, out var sameUsers))
                {
                    foreach (var user in sameUsers)
                    {
                        try
                        {
                            await user.Socket.Send(packet);
                        }

                        catch (IOException)
                        {
                        }
                        catch (SocketException)
                        {
                        }
                    }
                }
            }
        }


        /// <summary>
        /// 发送数据给链接ID对应的链接
        /// </summary>
        /// <param name="connectionId">链接ID</param>
        /// <param name="packet">要发送的字节数组</param>
        /// <returns></returns>
        public async Task<bool> SendMessageToConnection(string connectionId, byte[] packet)
        {
            if (!string.IsNullOrEmpty(connectionId))
            {
                if (SocketUsers.TryGetValue(connectionId, out var user))
                {
                    if (user != null)
                    {
                        try
                        {
                            await user.Socket.Send(packet);
                            return true;
                        }

                        catch (IOException)
                        {
                            return false;
                        }
                        catch (SocketException)
                        {
                            return false;
                        }
                        catch (ConnectionNotAvailableException)
                        {
                            return false;
                        }
                        catch (AggregateException)
                        {
                            return false;
                        }
                    }
                }
            }
            return false;
        }



        /// <summary>
        /// 发送集群数据给链接ID对应的链接
        /// </summary>
        /// <param name="packet">接收到要发送的集群数据</param>
        /// <returns></returns>
        public async Task SendMessageToConnection(ClusterMessage clusterData)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 这里需用ClusterOnlineUsers实例化接口，OnlineUser调用的话只做本地发送
        /// </summary>
        /// <param name="onlineUser">在线用户对象</param>
        /// <param name="packet">要发送的字节数组</param>
        /// <returns></returns>
        public async Task SendMessageToUser(OnlineUserInfo onlineUser, byte[] packet)
        {
            await SendMessageToConnection(onlineUser.ConnectionId, packet);
        }

        /// <summary>
        /// 这里需用ClusterOnlineUsers实例化接口，OnlineUser调用的话只做本地发送
        /// </summary>
        /// <param name="connectionId">链接ID</param>
        /// <param name="userName">用户名</param>
        /// <param name="packet">要发送的字节数组</param>
        /// <returns></returns>
        public async Task SendMessageToUser(string connectionId, string userName, byte[] packet)
        {
            await SendMessageToConnection(connectionId, packet);
        }

        /// <summary>
        /// 发送消息给组成员或者某个用户，这个类未实现
        /// </summary>
        /// <param name="groupOrUserName">组ID或者用户名</param>
        /// <param name="packet">要发送的字节数组</param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public Task SendMessageToGroupOrUser(string groupOrUserName, byte[] packet)
        {
            throw new NotImplementedException();
        }

        public Task SendMessageToGroupOrUserExceptIds(string groupOrUserName, byte[] packet, HashSet<string> exceptIds)
        {
            throw new NotImplementedException();
        }

        public Task RequestHost(OnlineUserInfo user, bool isRemoveExist)
        {
            throw new NotImplementedException();
        }

        public Task PushMessageToRoomQueue(string groupOrUserName, string userName, byte[] packet)
        {
            throw new NotImplementedException();
        }
    }
}