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.Repository.Interface;
using GxPress.Request.App.OftenContact;
using GxPress.Result.App.OftenContact;
using Microsoft.Extensions.Options;
using Datory;
using SqlKata;
using Dapper;
using GxPress.Result.Job;
using System.Linq;

namespace GxPress.Repository.Implement
{
    public class OftenContactRepository : IOftenContactRepository
    {
        private readonly Repository<OftenContact> _repository;
        private readonly Repository<User> _userRepository;
        private readonly Repository<ChatRecord> _chatRecordRepository;
        private readonly Repository<GroupChat> _groupChatRepository;
        private readonly Repository<Entity.Middle.Middle> _middleRepository;
        private readonly IMapper _mapper;
        private readonly string _connectionString;
        private readonly string _databaseTypeStr;
        public OftenContactRepository(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<OftenContact>(database);
            _userRepository = new Repository<User>(database);
            _chatRecordRepository = new Repository<ChatRecord>(database);
            _groupChatRepository = new Repository<GroupChat>(database);
            _middleRepository = new Repository<Entity.Middle.Middle>(database);
            _mapper = mapper;
        }


        public IDatabase Database => _repository.Database;
        public string TableName => _repository.TableName;
        public List<TableColumn> TableColumns => _repository.TableColumns;
        public async Task<bool> DeleteAsync(int id)
        {
            return await _repository.DeleteAsync(id);
        }


        /// <summary>
        /// 添加好友关系
        /// </summary>
        /// <param name="request"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<bool> InsertAsync(OftenContactInRequest request, int userId)
        {
            if (string.IsNullOrEmpty(request.ContactUserId))
                throw new BusinessException("缺少必要字段");
            if (request.ChatType == 0)
                throw new BusinessException("类型必须");
            var count = await _repository.CountAsync(Q.Where(nameof(OftenContact.UserId), userId)
                .Where(nameof(OftenContact.ContactUserId), request.ContactUserId));
            if (count > 0)
            {
                //修改好友关系
                await _repository.UpdateAsync(Q.Set(nameof(OftenContact.IsDelete), false)
                    .Where(nameof(OftenContact.UserId), userId)
                    .Where(nameof(OftenContact.ContactUserId), request.ContactUserId));
                if (request.ChatType == 1)
                    await _repository.UpdateAsync(Q.Set(nameof(OftenContact.IsDelete), false)
                        .Where(nameof(OftenContact.UserId), int.Parse(request.ContactUserId))
                        .Where(nameof(OftenContact.ContactUserId), userId));
                return true;
            }

            try
            {

                using (TransactionScope transactionScope = new TransactionScope())
                {
                    if (request.ChatType == 1)
                    {
                        var oftenContact = new OftenContact
                        {
                            IndividualGroupId = request.IndividualGroupId,
                            ContactUserId = request.ContactUserId,
                            UserId = userId,
                            ChatType = request.ChatType,
                            IsBlack = false,
                            IsDelete = false
                        };
                        await _repository.InsertAsync(oftenContact);
                        oftenContact = new OftenContact
                        {
                            IndividualGroupId = 0,
                            ContactUserId = userId.ToString(),
                            UserId = int.Parse(request.ContactUserId),
                            ChatType = request.ChatType,
                            IsBlack = false,
                            IsDelete = false
                        };
                        await _repository.InsertAsync(oftenContact);
                    }
                    else
                    {
                        var oftenContact = new OftenContact
                        {
                            IndividualGroupId = request.IndividualGroupId,
                            ContactUserId = request.ContactUserId,
                            UserId = userId,
                            ChatType = request.ChatType,
                            IsBlack = false,
                            IsDelete = false
                        };
                        await _repository.InsertAsync(oftenContact);
                    }

                    transactionScope.Complete();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }

            return true;
        }



        /// <summary>
        /// 修改黑名单
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="blackUserId"></param>
        /// <returns></returns>
        public async Task<bool> SetBlackUserAsync(int userId, int blackUserId)
        {
            //获取
            var oftenContact = await _repository.GetAsync(Q.Where(nameof(OftenContact.UserId), userId)
                .Where(nameof(OftenContact.ContactUserId), blackUserId.ToString()));
            if (oftenContact != null)
            {
                oftenContact.IsBlack = !oftenContact.IsBlack;
                return await _repository.UpdateAsync(oftenContact);
            }
            return true;
        }

        public async Task<OftenContact> FindOftenContactAsync(int userId, string groupChatImId)
        {
            return await _repository.GetAsync(Q.Where(nameof(OftenContact.UserId), userId)
                .Where(nameof(OftenContact.ContactUserId), groupChatImId));
        }

        /// <summary>
        /// 移除当前文件夹关系
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> RemoveOftenContactAsync(OftenContactDeRequest request)
        {
            var oftenContact = await _repository.GetAsync(request.OftenContactId);
            oftenContact.IndividualGroupId = 0;
            return await _repository.UpdateAsync(oftenContact);

        }

        /// <summary>
        /// 设置置顶
        /// </summary>
        /// <returns></returns>
        public async Task<bool> SetOftenContactIsTopAsync(OftenContactDeRequest request)
        {
            var oftenContact = await _repository.GetAsync(request.OftenContactId);
            if (oftenContact == null)
                throw new BusinessException("聊天不存在");
            return await _repository.UpdateAsync(Q.Set(nameof(OftenContact.IsTop), !oftenContact.IsTop)
                       .Where(nameof(oftenContact.Id), request.OftenContactId)) > 0;
        }
        /// <summary>
        /// 移动到文件夹
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> MoveOftenContactToIndividualGroupAsync(OftenContactUpRequest request)
        {
            return await _repository.UpdateAsync(Q
                       .Set(nameof(OftenContact.IndividualGroupId), request.IndividualGroupId)
                       .WhereIn(nameof(OftenContact.Id), request.OftenContactIds)) > 0;
        }
        /// <summary>
        /// 删除聊天界面
        /// </summary>
        /// <param name="oftenContactIds"></param>
        /// <returns></returns>
        public async Task<bool> DeleteAsync(List<int> oftenContactIds)
        {
            return await _repository.UpdateAsync(Q.Set(nameof(OftenContact.IsDelete), true)
                .WhereIn(nameof(OftenContact.Id), oftenContactIds)) > 0;
        }

        /// <summary>
        /// 获取是否置顶
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="imId"></param>
        /// <returns></returns>
        public async Task<bool> GetIsTopAsync(int userId, string imId)
        {
            var oftenContact = await _repository.GetAsync(Q.Where(nameof(Entity.OftenContact.UserId), userId)
                .Where(nameof(Entity.OftenContact.ContactUserId), imId));
            if (oftenContact == null)
                return false;
            var midel = await _middleRepository.GetAsync(Q.Where(nameof(Entity.Middle.Middle.FolderType), 10).Where(nameof(Entity.Middle.Middle.MiddleId), oftenContact.Id));
            return midel.IsTop;
        }

        public async Task<int> CountAsync(Query query)
        {
            return await _repository.CountAsync(query);
        }

        public async Task<bool> UpdateAsync(Query query)
        {
            return await _repository.UpdateAsync(query) > 0;
        }

        public async Task<int> InsertAsync(OftenContact oftenContact)
        {
            return await _repository.InsertAsync(oftenContact);
        }
        /// <summary>
        /// 插入多个
        /// </summary>
        /// <param name="oftenContacts"></param>
        /// <returns></returns>
        public async Task<bool> InsertAsync(List<OftenContact> oftenContacts)
        {
            if (oftenContacts.Count == 0 || oftenContacts == null)
                return false;
            string sql = @"INSERT INTO `tede_often_contact`(`Guid`,`CreatedDate`,`LastModifiedDate`,`UserId`,`ContactUserId`,`IndividualGroupId`,`UpdateTime`,`ChatType`,`IsBlack`,`IsTop`,`IsDelete`)VALUES";
            foreach (var item in oftenContacts)
            {
                var guId = Guid.NewGuid().ToString();
                var nowTime = System.DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
                var isBlack = item.IsBlack ? 1 : 0;
                var isTop = item.IsTop ? 1 : 0;
                var isDelete = item.IsDelete ? 1 : 0;
                sql += $@"('{guId}','{nowTime}','{nowTime}',{item.UserId},'{item.ContactUserId}',{item.IndividualGroupId},'{nowTime}',{item.ChatType},{isBlack},{isTop},{isDelete}),";
            }
            sql = sql.Remove(sql.Length - 1, 1);
            var databaseType = StringUtils.ToEnum<DatabaseType>(_databaseTypeStr, DatabaseType.MySql);
            var database = new Database(databaseType, _connectionString);
            var connection = database.GetConnection();
            return await connection.ExecuteAsync(sql) > 0;
        }
        public async Task<Entity.OftenContact> GetAsync(SqlKata.Query query)
        {
            return await _repository.GetAsync(query);
        }

        public async Task<IEnumerable<Entity.OftenContact>> GetAllAsync(SqlKata.Query query)
        {
            return await _repository.GetAllAsync(query);
        }
        public async Task<IEnumerable<OftenContactInfo>> GetContactInfosAsync(OftenContactSearchRequest request)
        {
            var sql =
               $"select a.*,b.* from tede_middle a left join tede_often_contact b on a.MiddleId=b.Id where a.FolderType=10 and a.UserId={request.UserId} and a.ParentId={request.IndividualGroupId} and a.IsDelete=0 order by a. IsTop desc,a.LastModifiedDate desc";
            var databaseType = StringUtils.ToEnum<DatabaseType>(_databaseTypeStr, DatabaseType.MySql);
            var database = new Database(databaseType, _connectionString);
            var connection = database.GetConnection();
            var result =
               await connection
                    .QueryAsync<OftenContactInfo, Entity.OftenContact, OftenContactInfo>(sql,
                        (oftenContactInfo, oftenContact) =>
                        {
                            oftenContactInfo.ChatType = oftenContact == null ? 0 : oftenContact.ChatType;
                            oftenContactInfo.ContactUserId = oftenContact == null ? "" : oftenContact.ContactUserId;
                            return oftenContactInfo;
                        }, splitOn: "Id,Id");
            return result;
        }

        public async Task<IEnumerable<OftenContactInfo>> GetContactInfoAllAsync(OftenContactSearchRequest request)
        {
            var sql =
               $"select a.*,b.* from tede_middle a inner join tede_often_contact b on a.MiddleId=b.Id where a.FolderType=10 and a.UserId={request.UserId}  and a.IsDelete=0 order by a. IsTop desc,a.LastModifiedDate desc";
            var databaseType = StringUtils.ToEnum<DatabaseType>(_databaseTypeStr, DatabaseType.MySql);
            var database = new Database(databaseType, _connectionString);
            var connection = database.GetConnection();
            var result =
               await connection
                    .QueryAsync<OftenContactInfo, Entity.OftenContact, OftenContactInfo>(sql,
                        (oftenContactInfo, oftenContact) =>
                        {
                            oftenContactInfo.ChatType = oftenContact == null ? 0 : oftenContact.ChatType;
                            oftenContactInfo.ContactUserId = oftenContact == null ? "" : oftenContact.ContactUserId;
                            return oftenContactInfo;
                        }, splitOn: "Id,Id");
            return result;
        }
        /// <summary>
        /// 获取全局索引聊天群
        /// </summary>
        /// <returns></returns>
        public async Task<List<JobChatResult>> ElasticSearchGroupChat()
        {
            string sql = "select a.Id,a.GuId,a.MiddleId,a.UserId,a.CreatedDate,b.ContactUserId,c.AvatarUrl,c.Name from tede_middle a  inner join tede_often_contact b on a.MiddleId=b.Id  inner join tede_group_chat c on c.GroupChatImId=b.ContactUserId where a.FolderType=10 and b.ChatType=2 and a.IsUpload=0 order by a.CreatedDate desc limit 0,100";
            var databaseType = StringUtils.ToEnum<DatabaseType>(_databaseTypeStr, DatabaseType.MySql);
            var database = new Database(databaseType, _connectionString);
            var connection = database.GetConnection();
            var result =
               await connection
                    .QueryAsync<JobChatResult, Entity.OftenContact, Entity.GroupChat, JobChatResult>(sql,
                        (jobChatResult, oftenContact, groupChat) =>
                        {
                            jobChatResult.ChatType = 2;
                            jobChatResult.Name = groupChat != null ? groupChat.Name : "";
                            jobChatResult.AvatarUrl = groupChat != null ? groupChat.AvatarUrl : "";
                            jobChatResult.ImId = oftenContact != null ? oftenContact.ContactUserId : "";
                            return jobChatResult;
                        }, splitOn: "Id,ContactUserId,AvatarUrl");
            return result.ToList();
        }
        /// <summary>
        /// 获取全局索引聊天
        /// </summary>
        /// <returns></returns>
        public async Task<List<JobChatResult>> ElasticSearchChat()
        {
            string sql = "select a.Id,a.GuId,a.MiddleId,a.UserId,a.CreatedDate,b.ContactUserId,c.AvatarUrl,c.Name,c.ImId from tede_middle a  inner join tede_often_contact b on a.MiddleId=b.Id  inner join tede_user c on c.Id=b.ContactUserId where a.FolderType=10 and b.ChatType=1 and a.IsUpload=0 order by a.CreatedDate desc limit 0,100";
            var databaseType = StringUtils.ToEnum<DatabaseType>(_databaseTypeStr, DatabaseType.MySql);
            var database = new Database(databaseType, _connectionString);
            var connection = database.GetConnection();
            var result =
               await connection
                    .QueryAsync<JobChatResult, Entity.OftenContact, Entity.User, JobChatResult>(sql,
                        (jobChatResult, oftenContact, user) =>
                        {
                            jobChatResult.ChatType = 1;
                            jobChatResult.Name = user != null ? user.Name : "";
                            jobChatResult.AvatarUrl = user != null ? user.AvatarUrl : "";
                            jobChatResult.ImId = user != null ? user.ImId : "";
                            jobChatResult.ToUserId = oftenContact != null ? Convert.ToInt32(oftenContact.ContactUserId) : 0;
                            return jobChatResult;
                        }, splitOn: "Id,ContactUserId,AvatarUrl");
            return result.ToList();
        }
    }
}