using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.Linq.Extensions;
using Abp.Runtime.Session;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using YGNT.Exam.Messages.Dto;
using YGNT.Infrastructure.Extension;
using Z.EntityFramework.Plus;

namespace YGNT.Exam.Messages
{
    [AbpAuthorize()]
    public class UserMessageAppService : IUserMessageAppService
    {
        private readonly IRepository<UserMessage, long> _userMessageRepository;
        public IAbpSession AbpSession { get; set; }

        public UserMessageAppService(IRepository<UserMessage, long> userMessageRepository)
        {
            _userMessageRepository = userMessageRepository;
            AbpSession = NullAbpSession.Instance;
        }

        /// <summary>
        /// 获取用户未读消息数量
        /// </summary>
        /// <returns></returns>
        public async Task<long> GetNotReadCountAsync()
        {
            var userId = AbpSession.GetUserId();
            return await _userMessageRepository.CountAsync(x => x.UserId == userId
                                                                && !x.IsRead);
        }

        /// <summary>
        /// 获取用户消息
        /// </summary>
        /// <param name="search"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<UserMessageDto>> GetUserMessageAsync(UserMessageSearchInputDto search)
        {
            var userId = AbpSession.GetUserId();
            var queryable = _userMessageRepository.GetAll()
                .WhereIf(!search.KeyWord.IsNullOrEmpty(), x => x.Message.Contains(search.KeyWord))
                .WhereIf(search.MessageType.HasValue, x => x.MessageType == search.MessageType)
                .WhereIf(search.IsRead.HasValue, x => x.IsRead == search.IsRead)
                .Where(x => x.UserId == userId)
                .OrderBy(x => x.IsRead)
                .ThenByDescending(x => x.CreationTime);

            var result = await queryable.GetResultAsync(search, x => x.Adapt<UserMessageDto>(), default(long));
            if (!search.IsPreview)
                await _userMessageRepository.GetAll()
                    .Where(x => result.Items.Select(f => f.Id).Contains(x.Id))
                    .UpdateAsync(x => new UserMessage() { IsRead = true });
            return result;
        }

        /// <summary>
        /// 删除消息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task DeleteAsync([Required] long id)
        {
            await _userMessageRepository.DeleteAsync(id);
        }

        /// <summary>
        /// 删除消息
        /// </summary>
        /// <param name="idList"></param>
        /// <returns></returns>
        public async Task DeleteListAsync([Required] List<long> idList)
        {
            foreach (var id in idList)
            {
                await DeleteAsync(id);
            }
        }

        /// <summary>
        /// 读取消息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<UserMessageInfoDto> ReadAsync([Required] long id)
        {
            var message = await _userMessageRepository.GetAsync(id);
            message.IsRead = true;
            return message.Adapt<UserMessageInfoDto>();
        }
    }
}