using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Transactions;
using AutoMapper;
using GxPress.Common.AppOptions;
using GxPress.Common.Exceptions;
using GxPress.Common.Tools;
using GxPress.Entity;
using GxPress.EnumConst;
using GxPress.Repository.Interface;
using GxPress.Request.App.IM;
using GxPress.Request.GroupChat;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Datory;
using System.Linq;
using GxPress.Result.App.GroupChat;
using Dapper;

namespace GxPress.Repository.Implement
{
    public class GroupChatRepository : IGroupChatRepository
    {
        private readonly Repository<GroupChat> _repository;
        private readonly Repository<User> _userRepository;
        private readonly Repository<GroupChatUser> _groupChatUserRepository;
        private readonly Repository<OftenContact> _oftenContactRepository;
        private readonly IWebHostEnvironment _environment;
        private readonly Repository<Entity.Middle.Middle> _middleRepository;
        private readonly IMapper _mapper;
        private readonly string _connectionString;
        private readonly string _databaseTypeStr;
        public GroupChatRepository(IOptionsMonitor<DatabaseOptions> dbOptionsAccessor, IMapper mapper, IWebHostEnvironment environment)
        {
            _databaseTypeStr = dbOptionsAccessor.CurrentValue.DatabaseType;
            _connectionString = dbOptionsAccessor.CurrentValue.ConnectionString;
            var databaseType = StringUtils.ToEnum<DatabaseType>(dbOptionsAccessor.CurrentValue.DatabaseType, DatabaseType.MySql);
            var database = new Database(databaseType, dbOptionsAccessor.CurrentValue.ConnectionString);
            _repository = new Repository<GroupChat>(database);
            _userRepository = new Repository<User>(database);
            _groupChatUserRepository = new Repository<GroupChatUser>(database);
            _oftenContactRepository = new Repository<OftenContact>(database);
            _middleRepository = new Repository<Entity.Middle.Middle>(database);
            _environment = environment;
            _mapper = mapper;
        }

        public IDatabase Database => _repository.Database;
        public string TableName => _repository.TableName;
        public List<TableColumn> TableColumns => _repository.TableColumns;

        /// <summary>
        /// 添加群
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> InsertAsync(GroupChatInRequest request)
        {
            var user = await _userRepository.GetAsync(request.UserId);
            if (user == null)
                throw new BusinessException("用户不存在");
            try
            {
                using (TransactionScope transactionScope = new TransactionScope())
                {
                    //创建群
                    var groupChat = new GroupChat
                    {
                        GroupChatImId = request.GroupChatImId,
                        Introduce = request.Introduce,
                        IsAdmin = request.IsAdmin,
                        IsWords = request.IsWords,
                        Name = request.Name,
                        UserId = request.UserId,
                        IsOpenQrCoder = true
                    };
                    if (!string.IsNullOrEmpty(request.AvatarUrl))
                        groupChat.AvatarUrl = StringUtils.RemoveDomain(request.AvatarUrl);
                    var groupChatId = await _repository.InsertAsync(groupChat);
                    //
                    var groupChatDto = await _repository.GetAsync(groupChatId);
                    //生成二维码
                    var qrCodeData = new { key = QRCodeTypeConst.GroupChatInfo, value = groupChatDto.Guid };
                    var resultPath =
                        FileHelper.SaveQRCodeFile(StringUtils.GetWebRootPath(_environment.WebRootPath),
                            JsonConvert.SerializeObject(qrCodeData));
                    groupChatDto.QRCoder = resultPath.RelativePath;
                    await _repository.UpdateAsync(groupChatDto);
                    //默认添加管理员为群成员
                    var groupChatUser = new GroupChatUser
                    {
                        GroupChatId = groupChatId,
                        UserId = request.UserId,
                        ImId = user.ImId,
                        IsAdmin = true,
                        GroupChatImId = request.GroupChatImId
                    };
                    //创建环信Mi群
                    await _groupChatUserRepository.InsertAsync(groupChatUser);
                    //建立关系
                    var oftenContact = new OftenContact
                    {
                        ChatType = 2,
                        ContactUserId = groupChat.GroupChatImId,
                        IndividualGroupId = 0,
                        UserId = request.UserId
                    };
                    var oftenContactId = await _oftenContactRepository.InsertAsync(oftenContact);
                    //添加middle
                    var middle = new Entity.Middle.Middle();
                    middle.IsAdmin = true;
                    middle.MiddleId = oftenContactId;
                    middle.FolderType = 10;
                    middle.IsDefault = false;
                    middle.IsDelete = false;
                    middle.UserId = request.UserId;
                    middle.IsRead = false;
                    middle.IsTop = false;
                    middle.ParentId = request.FolderId;
                    await _middleRepository.InsertAsync(middle);
                    //添加用户
                    // foreach (var userId in request.UserIds)
                    // {
                    //     if (userId == request.UserId)
                    //         continue;
                    //     oftenContact = new OftenContact
                    //     {
                    //         ChatType = 2,
                    //         ContactUserId = groupChat.GroupChatImId,
                    //         IndividualGroupId = 0,
                    //         UserId = userId
                    //     };
                    //     user = await _userRepository.GetAsync(userId);
                    //     groupChatUser = new GroupChatUser
                    //     {
                    //         GroupChatId = groupChatId,
                    //         UserId = userId,
                    //         ImId = user.ImId,
                    //         IsAdmin = false,
                    //         GroupChatImId = request.GroupChatImId
                    //     };
                    //     //创建环信Mi群
                    //     await _groupChatUserRepository.InsertAsync(groupChatUser);

                    // }

                    transactionScope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new BusinessException(e.Message);
            }

            return true;
        }

        /// <summary>
        /// 群添加用户
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> InsertUsersIntoGroupChatAsync(InsertGroupChatUsersRequest request)
        {
            try
            {
                using (TransactionScope transactionScope = new TransactionScope())
                {
                    var groupChat =
                        await _repository.GetAsync(Q.Where(nameof(GroupChat.GroupChatImId), request.GroupChatImId));
                    if (groupChat == null)
                        return false;
                    //添加用户
                    
                    foreach (var user in request.Users)
                    {
                        if (user.Id == groupChat.UserId)
                            continue;
                        var oftenContact = new OftenContact
                        {
                            ChatType = 2,
                            ContactUserId = groupChat.GroupChatImId,
                            IndividualGroupId = 0,
                            UserId = user.Id
                        };
                        var oftenContactId = await _oftenContactRepository.InsertAsync(oftenContact);
                        //添加middle
                        var middle = new Entity.Middle.Middle();
                        middle.IsAdmin = true;
                        middle.MiddleId = oftenContactId;
                        middle.FolderType = 10;
                        middle.IsDefault = false;
                        middle.IsDelete = false;
                        middle.UserId = user.Id;
                        middle.IsRead = false;
                        middle.IsTop = false;
                        middle.ParentId = 0;
                        await _middleRepository.InsertAsync(middle);
                        var groupChatUser = new GroupChatUser
                        {
                            GroupChatId = groupChat.Id,
                            UserId = user.Id,
                            ImId = user.ImId,
                            GroupChatImId = request.GroupChatImId,
                            IsAdmin = false
                        };
                        //创建环信Mi群
                        var id = await _groupChatUserRepository.InsertAsync(groupChatUser);
                    }
                    transactionScope.Complete();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }

            return true;
        }
        /// <summary>
        /// 删除群用户
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> DeleteUsersIntoGroupChatAsync(InsertGroupChatUsersRequest request)
        {
            try
            {
                using (TransactionScope transactionScope = new TransactionScope())
                {
                    var groupChat =
                        await _repository.GetAsync(Q.Where(nameof(GroupChat.GroupChatImId), request.GroupChatImId));
                    if (groupChat == null)
                        return false;
                    //删除群用户
                    await _groupChatUserRepository.DeleteAsync(Q.Where(nameof(GroupChatUser.GroupChatId), groupChat.Id)
                        .WhereIn(nameof(GroupChatUser.UserId), request.UserIds));
                    //删除关系
                    var oftenContact = await _oftenContactRepository.GetAsync(Q
                           .Where(nameof(OftenContact.ContactUserId), request.GroupChatImId)
                           .WhereIn(nameof(OftenContact.UserId), request.UserIds));
                    //删除middle
                    await _middleRepository.DeleteAsync(Q.Where(nameof(Entity.Middle.Middle.MiddleId), oftenContact.Id).Where(nameof(Entity.Middle.Middle.FolderType), 10));
                    await _oftenContactRepository.DeleteAsync(Q
                        .Where(nameof(OftenContact.ContactUserId), request.GroupChatImId)
                        .WhereIn(nameof(OftenContact.UserId), request.UserIds));
                    transactionScope.Complete();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }

            return true;
        }

        /// <summary>
        /// 修改群信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> UpdateAsync(GroupChatUpRequest request)
        {
            var groupChat = await _repository.GetAsync(request.Id);
            if (groupChat == null)
                throw new BusinessException("群不存在");
            if (!string.IsNullOrEmpty(request.AvatarUrl))
                groupChat.AvatarUrl = StringUtils.RemoveDomain(request.AvatarUrl);
            if (!string.IsNullOrEmpty(request.Introduce))
                groupChat.Introduce = request.Introduce;
            if (!string.IsNullOrEmpty(request.Name))
                groupChat.Name = request.Name;
            if (!string.IsNullOrEmpty(request.QrCode))
                groupChat.QRCoder = StringUtils.RemoveDomain(request.QrCode);
            return await _repository.UpdateAsync(groupChat);
        }

        /// <summary>
        /// 删除群
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> DeleteAsync(int id)
        {
            var groupChat = await _repository.GetAsync(id);
            if (groupChat == null)
                throw new BusinessException("群不存在");
            try
            {
                //增加事务
                using (TransactionScope scope = new TransactionScope())
                {
                    //删除群
                    await _groupChatUserRepository.DeleteAsync(Q.Where(nameof(GroupChatUser.GroupChatId), id));
                    await _repository.DeleteAsync(id);
                    //删除middle
                    var oftenContacts = await _oftenContactRepository.GetAllAsync(Q.WhereIn(nameof(OftenContact.ContactUserId), groupChat.GroupChatImId));
                    await _middleRepository.DeleteAsync(Q.WhereIn(nameof(Entity.Middle.Middle.MiddleId), oftenContacts.Select(n => n.Id)).Where(nameof(Entity.Middle.Middle.FolderType), 10));
                    //删除关系界面
                    await _oftenContactRepository.DeleteAsync(Q.WhereIn(nameof(OftenContact.ContactUserId), groupChat.GroupChatImId));
                    scope.Complete();
                    return true;
                }
            }
            catch (Exception e)
            {
                throw new BusinessException(e.Message);
            }

        }

        /// <summary>
        /// 获取用户群
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<IEnumerable<GroupChat>> GetGroupChatByUserIdAsync(GroupChatSearchRequest request)
        {
            //var groupChat = await _repository.GetAsync(request.UserId);
            //if (groupChat == null)
            //    throw new BusinessException("群不存在");
            //获取参与群
            var groupChatUsers = await _groupChatUserRepository.GetAllAsync(Q.Where(nameof(GroupChatUser.UserId)));
            var groupChats = new List<GroupChat>();
            foreach (var item in groupChatUsers)
            {
                groupChats.Add(await _repository.GetAsync(item.GroupChatId));
            }

            foreach (var groupChatItem in groupChats)
            {
                groupChatItem.AvatarUrl = StringUtils.AddDomainMin(groupChatItem.AvatarUrl);
            }
            return groupChats;
        }
        /// <summary>
        /// 修改是否管理员同意 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> UpIsAdminAsync(GroupChatUpIsAdminRequest request)
        {
            var groupChat = await _repository.GetAsync(request.Id);
            if (groupChat == null)
                throw new BusinessException("群不存在");
            return await _repository.UpdateAsync(Q.Where(nameof(GroupChat.Id), request.Id)
                .Set(nameof(GroupChat.IsAdmin), !groupChat.IsAdmin)) > 0;
        }
        /// <summary>
        /// 修改是否禁言
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> UpIsWordsAsync(GroupChatUpIsWordsRequest request)
        {
            var groupChat = await _repository.GetAsync(request.Id);
            if (groupChat == null)
                throw new BusinessException("群不存在");
            return await _repository.UpdateAsync(Q.Where(nameof(GroupChat.Id), request.Id).Set(nameof(groupChat.IsWords), !groupChat.IsWords)) > 0;
        }

        public async Task<GroupChat> FindGroupChatByIdAsync(int id)
        {
            return await _repository.GetAsync(id);
        }

        public async Task<GroupChat> GetAsync(int id)
        {
            return await _repository.GetAsync(id);
        }
        public async Task<GroupChat> GetAsync(SqlKata.Query query)
        {
            return await _repository.GetAsync(query);
        }
        public async Task<GroupChat> GetGroupChatByImIdAsync(string imId)
        {
            var groupChat = await _repository.GetAsync(Q.Where(nameof(GroupChat.GroupChatImId), imId));
            groupChat.AvatarUrl = Common.Tools.StringUtils.AddDomainMin(groupChat.AvatarUrl);
            groupChat.QRCoder = Common.Tools.StringUtils.AddDomain(groupChat.QRCoder);
            return groupChat;
        }
        /// <summary>
        /// 根据ImId获取群信息
        /// </summary>
        /// <param name="imId"></param>
        /// <returns></returns>
        public async Task<GroupChatInfoResult> GetGroupChatInfoByImIdAsync(string imId)
        {
            var sql = $"select *,(select Name from ccpph.tede_user where id=a.UserId) as UserName from ccpph.tede_group_chat a where a.GroupChatImId='{imId}';";
            var databaseType = StringUtils.ToEnum<DatabaseType>(_databaseTypeStr, DatabaseType.MySql);
            var database = new Database(databaseType, _connectionString);
            var connection = database.GetConnection();
            var result = await connection.QueryFirstOrDefaultAsync<GroupChatInfoResult>(sql);
            if (result == null)
                return new GroupChatInfoResult();
            result.QRCoder = StringUtils.AddDomain(result.QRCoder);
            result.AvatarUrl = StringUtils.AddDomainMin(result.AvatarUrl);
            return result;
        }
        public async Task<IEnumerable<GroupChat>> GetAllGroupChatAsync()
        {
            return await _repository.GetAllAsync();
        }
        /// <summary>
        /// 根据Guid获取群信息
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public async Task<GroupChat> GetGroupChatByGuidAsync(string guid)
        {
            return await _repository.GetAsync(Q.Where(nameof(GroupChat.Guid), guid));
        }

        /// <summary>
        /// set群是否开启
        /// </summary>
        /// <param name="groupChatImId"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<bool> SetIsOpenQrCoderAsync(string groupChatImId, int userId)
        {
            var groupChat = await _repository.GetAsync(Q.Where(nameof(GroupChat.GroupChatImId), groupChatImId));
            if (groupChat.UserId != userId)
                throw new BusinessException("不是群主无法设置");
            if (groupChat == null)
                throw new BusinessException("群不存在");
            return await _repository.UpdateAsync(Q.Set(nameof(groupChat.IsOpenQrCoder), !groupChat.IsOpenQrCoder)
                       .Where(nameof(groupChat.Id), groupChat.Id)) > 0;
        }
    }
}