using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using GxPress.Common.AppOptions;
using GxPress.Common.Exceptions;
using GxPress.Common.Tools;
using GxPress.Entity;
using GxPress.Repository.Interface;
using GxPress.Request.AddressBookGroupUser;
using GxPress.Result.AddressBookGroupUser;
using Microsoft.Extensions.Options;
using Datory;
using SqlKata;
using System.Transactions;
using Dapper;

namespace GxPress.Repository.Implement
{
    public class AddressBookGroupUserRepository : IAddressBookGroupUserRepository
    {
        private readonly Repository<AddressBookGroupUser> _repository;
        private readonly Repository<AddressBookGroup> _addressBookGroupRepository;
        private readonly Repository<User> _userRepository;
        private readonly IMapper _mapper;

        private readonly string _connectionString;
        private readonly string _databaseTypeStr;
        public AddressBookGroupUserRepository(IOptionsMonitor<DatabaseOptions> dbOptionsAccessor, IMapper mapper)
        {
            _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<AddressBookGroupUser>(database);
            _userRepository = new Repository<User>(database);
            _addressBookGroupRepository = new Repository<AddressBookGroup>(database);
            _mapper = mapper;
        }

        public IDatabase Database => _repository.Database;
        public string TableName => _repository.TableName;
        public List<TableColumn> TableColumns => _repository.TableColumns;
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> DeleteAsync(int id)
        {
            return await _repository.DeleteAsync(id);
        }
        /// <summary>
        /// 批量删除通讯录自建分组用户
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<bool> DeletesAsync(List<int> ids)
        {
            return await _repository.DeleteAsync(Q.WhereIn(nameof(Entity.AddressBookGroupUser.Id), ids)) > 0;
        }
        /// <summary>
        /// 查询通讯录好友
        /// </summary>
        /// <param name="request"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<AddressBookGroupUserListResult> GetAddressBookGroupUserListAsync(
            AddressBookGroupUserSearchRequest request, int userId)
        {
            var result = new AddressBookGroupUserListResult();
            //sql
            var sql = $"select b.Id,b.AddressBookGroupId,a.Id as UserId,a.Name as UserName,a.AvatarUrl,a.ImId from ccpph.tede_user a inner join ccpph.tede_address_book_group_user b on a.Id=b.UserId where b. AddressBookGroupId={request.AddressBookGroupId}";
            var databaseType = StringUtils.ToEnum<DatabaseType>(_databaseTypeStr, DatabaseType.MySql);
            var database = new Database(databaseType, _connectionString);
            var connection = database.GetConnection();
            result.AddressBookGroupUsers = await connection.QueryAsync<AddressBookGroupUserModel>(sql);
            var userlist = result.AddressBookGroupUsers.ToList();
            //排除成员
            for (int i = 0; i < userlist.Count; i++)
            {
                if (!string.IsNullOrWhiteSpace(userlist[i].AvatarUrl))
                    userlist[i].AvatarUrl = StringUtils.AddDomainMin(userlist[i].AvatarUrl);
                if (!request.IsShow)
                    if (request.UserIds.Contains(userlist[i].UserId))
                        userlist.Remove(userlist[i]);
                if (request.IsShow)
                    if (request.UserIds.Contains(userlist[i].UserId))
                        userlist[i].IsDisable = true;
            }
            result.AddressBookGroupUsers = userlist;
            result.AddressBookGroups =
                await _addressBookGroupRepository.GetAllAsync(Q.Where(nameof(AddressBookGroup.ParentId),
                    request.AddressBookGroupId).Where(nameof(AddressBookGroup.UserId), userId));
            return result;
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> InsertAsync(AddressBookGroupUserInRequest request)
        {
            //查询组是否存在
            var addressBookGroup = await _addressBookGroupRepository.GetAsync(request.AddressBookGroupId);
            if (addressBookGroup == null)
                throw new BusinessException("通讯录组不存在!");
            var user = await _userRepository.GetAsync(request.UserId);
            if (user == null)
                throw new BusinessException("用户不存在!");
            var addressBookGroupUserEntity = await _repository.GetAsync(Q
                .Where(nameof(AddressBookGroupUser.UserId), request.UserId)
                .Where(nameof(AddressBookGroupUser.AddressBookGroupId), request.AddressBookGroupId));
            if (addressBookGroupUserEntity != null)
                throw new BusinessException("用户已经存在!");
            var addressBookGroupUser = new AddressBookGroupUser
            {
                AddressBookGroupId = request.AddressBookGroupId,
                UserId = request.UserId
            };
            return await _repository.InsertAsync(addressBookGroupUser) > 0;
        }
        /// <summary>
        /// 移动分组成员到分组下面
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> AddressBookGroupUserMoveAsync(AddressBookGroupUserMoveRequest request)
        {
            var addressBookGroup = await _addressBookGroupRepository.GetAsync(request.AddressBookGroupId);
            if (addressBookGroup == null)
                throw new BusinessException("分组ID不存在");
            try
            {
                //事务
                using (var transactionScope = new TransactionScope())
                {
                    //获取成员
                    var addressBookGroupUsers = await _repository.GetAllAsync(Q.WhereIn(nameof(AddressBookGroupUser.Id), request.AddressBookGroupUserId));
                    //获取小组成员
                    var addressBookGroupUsersDto = await _repository.GetAllAsync(Q.Where(nameof(AddressBookGroupUser.AddressBookGroupId), request.AddressBookGroupId));
                    foreach (var item in addressBookGroupUsers)
                    {
                        if (!addressBookGroupUsersDto.Any(n => n.UserId == item.UserId))
                        {
                            item.Id = 0;
                            item.AddressBookGroupId = request.AddressBookGroupId;
                            //添加
                            await _repository.InsertAsync(item);
                        }
                    }
                    await _repository.DeleteAsync(Q.WhereIn(nameof(AddressBookGroupUser.Id), request.AddressBookGroupUserId));
                    transactionScope.Complete();
                }
            }
            catch (System.Exception ex)
            {
                throw new BusinessException(ex.Message);
            }
            return true;
        }

        public async Task<IEnumerable<AddressBookGroupUser>> GetAllAsync(Query query)
        {
            return await _repository.GetAllAsync(query);
        }
    }
}