using System;
using System.Collections.Generic;
using System.Linq;
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.NoticeFolder;
using GxPress.Result.NoticeFolder;
using Microsoft.Extensions.Options;
using Datory;

namespace GxPress.Repository.Implement
{
    public class NoticeFolderRepository : INoticeFolderRepository
    {
        private readonly Repository<NoticeFolder> _repository;
        private readonly Repository<User> _userRepository;
        private readonly Repository<NoticeAddressee> _noticeAddresseeRepository;
        private readonly Repository<Notice> _noticeRepository;
        private readonly IMapper _mapper;

        public NoticeFolderRepository(IOptionsMonitor<DatabaseOptions> dbOptionsAccessor, IMapper mapper)
        {
            var databaseType = StringUtils.ToEnum<DatabaseType>(dbOptionsAccessor.CurrentValue.DatabaseType, DatabaseType.MySql);
            var database = new Database(databaseType, dbOptionsAccessor.CurrentValue.ConnectionString);
            _repository = new Repository<NoticeFolder>(database);
            _userRepository = new Repository<User>(database);
            _noticeAddresseeRepository = new Repository<NoticeAddressee>(database);
            _noticeRepository = new Repository<Notice>(database);
            _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(NoticeFolderInRequest request)
        {
            if (string.IsNullOrEmpty(request.FolderName))
            {
                throw new BusinessException("文件夹名称不能为空");
            }

            var user = await _userRepository.GetAsync(request.UserId);
            if (user == null)
                throw new BusinessException("用户不存在");
            var noticeFolder = new NoticeFolder
            {
                FolderName = request.FolderName, ParentId = request.ParentId, UserId = request.UserId,IsTop = false
            };
            return await _repository.InsertAsync(noticeFolder) > 0;
        }

        /// <summary>
        /// 删除文件夹
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> DeleteAsync(int id)
        {
            try
            {
                //获取文件夹下面的所有通知
                using (TransactionScope transactionScope = new TransactionScope())
                {

                    //修改收件人
                    await _noticeAddresseeRepository.UpdateAsync(Q.Set(nameof(NoticeAddressee.NoticeFolderId), 0)
                        .Where(nameof(NoticeAddressee.NoticeFolderId), id));
                    //主通知
                    await _noticeRepository.UpdateAsync(Q.Set(nameof(Notice.NoticeFolderId), 0)
                        .Where(nameof(NoticeAddressee.NoticeFolderId), id));
                    await _repository.DeleteAsync(id);
                    transactionScope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new BusinessException(e.Message);
            }

            return true;

        }

        /// <summary>
        /// 修改文件夹
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> UpdateAsync(NoticeFolderUpRequest request)
        {
            var noticeFolder = await _repository.GetAsync(request.NoticeFolderId);
            if (noticeFolder == null)
                throw new BusinessException("文件夹不存在");
            noticeFolder.FolderName = request.FolderName;
            return await _repository.UpdateAsync(noticeFolder);
        }

        /// <summary>
        /// 文件夹中添加通知
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> InsertNoticeAsync(NoticeFolderInNoticeRequest request)
        {
            var noticeAddressee = await _noticeAddresseeRepository.GetAsync(request.NoticeAddresseeId);
            noticeAddressee.NoticeFolderId = request.NoticeFolderId;
            return await _noticeAddresseeRepository.UpdateAsync(noticeAddressee);
        }

        /// <summary>
        /// 文件夹移除通知
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> NoticeFolderDeleteNoticeAsync(NoticeFolderDeleteNoticeRequest request)
        {
            var noticeAddressee = await _noticeAddresseeRepository.GetAsync(request.NoticeAddresseeId);
            noticeAddressee.NoticeFolderId = 0;
            return await _noticeAddresseeRepository.UpdateAsync(noticeAddressee);
        }
        /// <summary>
        /// 是否置顶文件夹
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> SetNoticeFolderIsTopAsync(NoticeFolderFindRequest request)
        {
            var noticeFolder = await _repository.GetAsync(request.NoticeFolderId);
            noticeFolder.IsTop = !noticeFolder.IsTop;
            return await _repository.UpdateAsync(noticeFolder);
        }

        /// <summary>
        /// 根据用户ID获取文件夹
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<IEnumerable<NoticeFolderFindResult>> GetNoticeFolderByUserIdAsync(
            NoticeFolderFindRequest request)
        {
            //获取通知文件夹
            var noticeFolders = await _repository.GetAllAsync(Q.Where(nameof(NoticeFolder.UserId), request.UserId)
                .Where(nameof(NoticeFolder.ParentId), request.NoticeFolderId).OrderByDesc(nameof(NoticeFolder.IsTop),nameof(NoticeFolder.LastModifiedDate)));
            var noticeFolderFindResults = noticeFolders.Select(n => _mapper.Map<NoticeFolderFindResult>(n)).ToList();
            //获取文件夹通知数量
            foreach (var noticeFolderFindResult in noticeFolderFindResults)
            {
                //获取文件夹通知数量
                var noticeCount =
                    await _repository.CountAsync(
                        Q.Where(nameof(NoticeFolder.ParentId), noticeFolderFindResult.Id));
                //
                var noticeAddresseeCount =
                    await _noticeAddresseeRepository.CountAsync(
                        Q.Where(nameof(NoticeAddressee.NoticeFolderId), noticeFolderFindResult.Id).Where(nameof(NoticeAddressee.IsDelete),false));
                noticeFolderFindResult.FileCount = noticeCount + noticeAddresseeCount;
            }

            return noticeFolderFindResults;
        }
    }
}
