using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UserManagement.Common.GenericRespository;
using UserManagement.Common.UnitOfWork;
using UserManagement.Data.Dto;
using UserManagement.Data;
using UserManagement.Domain;
using UserManagement.Data.Resources;

namespace UserManagement.Repository
{
    public class UserNotificationRepository : GenericRepository<UserNotification, UserContext>,
       IUserNotificationRepository
    {

        private readonly IPropertyMappingService _propertyMappingService;
        private readonly UserInfoToken _userInfoToken;
        private readonly IUserRoleRepository _userRoleRepository;
        private readonly IConnectionMappingRepository _userInfoInMemory;
        private readonly IHubContext<UserHub, IHubClient> _hubContext;
        public UserNotificationRepository(
            IUserRoleRepository userRoleRepository,
            IPropertyMappingService propertyMappingService,
            UserInfoToken userInfoToken,
            IUnitOfWork<UserContext> uow,
            IConnectionMappingRepository userInfoInMemory,
             IHubContext<UserHub, IHubClient> hubContext) : base(uow)
        {
            _userRoleRepository = userRoleRepository;
            _propertyMappingService = propertyMappingService;
            _userInfoToken = userInfoToken;
            _userInfoInMemory = userInfoInMemory;
            _hubContext = hubContext;
        }

        public void CreateUsersDocumentNotifiction(List<Guid> userIds, Guid documentId)
        {
            userIds.ForEach(userId =>
            {
                Add(new UserNotification
                {
                    Id = Guid.NewGuid(),
                    UserId = userId,
                    IsRead = false,
                    NotificationsType = NotificationsType.SHARE_USER
                });
            });
        }

        public void AddUserNotificationByReminderScheduler(ReminderScheduler reminderScheduler)
        {
            Add(new UserNotification
            {
                Id = Guid.NewGuid(),
                UserId = reminderScheduler.UserId,
                Message = reminderScheduler.Subject,
                IsRead = false,
                NotificationsType = NotificationsType.REMINDER
            });
        }


        public async Task<List<User>> CreateRolesDocumentNotifiction(List<Guid> roleIds, Guid documentId)
        {
            var users = await _userRoleRepository.All.Include(c => c.User).Where(cs => roleIds.Contains(cs.RoleId)).Select(c => c.User).Distinct().ToListAsync();
            users.ForEach(user =>
            {
                Add(new UserNotification
                {
                    Id = Guid.NewGuid(),
                    UserId = user.Id,
                    IsRead = false,
                    NotificationsType = NotificationsType.SHARE_USER
                });

            });
            return users;
        }

        public async Task<NotificationList> GetUserNotifications(NotificationResource documentResource)
        {
            var UserId = Guid.Parse(_userInfoToken.Id);
            var collectionBeforePaging = AllIncluding(d => d.User).Where(c => c.UserId == UserId);
            collectionBeforePaging =
               collectionBeforePaging.ApplySort(documentResource.OrderBy,
               _propertyMappingService.GetPropertyMapping<UserNotificationDto, UserNotification>());

          

            var documentAuditTrailList = new NotificationList();
            return await documentAuditTrailList.Create(
                collectionBeforePaging,
                documentResource.Skip,
                documentResource.PageSize
                );
        }

        public async Task MarkAsRead(Guid notificationId)
        {
            var notification = Find(notificationId);
            if (notification != null)
            {
                notification.IsRead = true;
                Update(notification);
                await _uow.SaveAsync();
            }
        }

        public async Task SendNotification(List<Guid> userIds)
        {
            foreach (var userId in userIds)
            {
                await SendNotification(userId);
            }
        }

        public async Task SendNotification(Guid userId)
        {
            var userInfoReciever = _userInfoInMemory.GetUserInfoById(userId);
            if (userInfoReciever != null)
                await _hubContext.Clients.Client(userInfoReciever.ConnectionId).SendNotification(userId);
        }

        public async Task MarkAllAsRead()
        {
            var userId = Guid.Parse(_userInfoToken.Id);
            var notifications = All.Where(c => c.UserId == userId).ToList();
            notifications.ForEach(notification => notification.IsRead = true);
            UpdateRange(notifications);
            await _uow.SaveAsync();
        }

        public async Task MarkAsReadByDocumentId(Guid documentId)
        {
            var userId = Guid.Parse(_userInfoToken.Id);
            var notifications = All.Where(c => c.UserId == userId).ToList();
            notifications.ForEach(c => c.IsRead = true);
            UpdateRange(notifications);
            await _uow.SaveAsync();
        }
    }
}