using System.Security.Cryptography.X509Certificates;
using Demo.Data.Repository;
using Demo.Domain.Models;

namespace Demo.Domain.UseCase
{
    public class PresenceUseCase : IPresenceUseCase
    {
		private readonly IUserRepository _repositoryUserImpl;
        private readonly IPresenceRepository _repositoryPresenceImpl;
        private readonly IGroupRepository _repositoryGroupImpl;

        public PresenceUseCase(IPresenceRepository repositoryPresenceImpl, IUserRepository repositoryUserImpl, IGroupRepository repositoryGroupImpl)
        {
            _repositoryPresenceImpl = repositoryPresenceImpl;
            _repositoryUserImpl = repositoryUserImpl;
            _repositoryGroupImpl = repositoryGroupImpl;
        }

        public List<Presence> GetPresenceByGroup(int groupID){
            var usersByGroup = _repositoryUserImpl.GetAllUser()
            .Where(user => user.GroupID == groupID).ToList();

            var presenceByGroup = _repositoryPresenceImpl.GetAllPresences()
            .Where(x => usersByGroup.Any(user => user.Guid == x.UserGuid))
            .Select(presence => new Presence{
                User = new User{
                    Guid = presence.UserGuid,
                    Group = new Group{
                        ID = groupID,
                        Name = _repositoryGroupImpl.GetAllGroup().First(group => group.ID == groupID).Name
                    },
                    FIO = usersByGroup.First(user => user.Guid == presence.UserGuid).FIO, 
                },
                LessonNumber = presence.LessonNumber,
                Date = presence.Date,
                IsAttedance = presence.IsAttedance
            }).ToList();

            return presenceByGroup;
        }

        public List<Presence> GetFalsePresenceByGroup(int groupID){
            var usersByGroup = _repositoryUserImpl.GetAllUser()
            .Where(user => user.GroupID == groupID).ToList();

            var presenceByGroup = _repositoryPresenceImpl.GetAllPresences()
            .Where(x => usersByGroup.Any(user => user.Guid == x.UserGuid) && x.IsAttedance == false)
            .Select(presence => new Presence{
                User = new User{
                    Guid = presence.UserGuid,
                    Group = new Group{
                        ID = groupID,
                        Name = _repositoryGroupImpl.GetAllGroup().First(group => group.ID == groupID).Name
                    },
                    FIO = usersByGroup.First(user => user.Guid == presence.UserGuid).FIO, 
                },
                LessonNumber = presence.LessonNumber,
                Date = presence.Date,
                IsAttedance = presence.IsAttedance
            }).ToList();

            return presenceByGroup;
        }

        public List<Presence> GetPresenceByUser(Guid userGuid){
            var user = _repositoryUserImpl.GetUserByGuid(userGuid);

            var presenceByUser = _repositoryPresenceImpl.GetAllPresences()
            .Where(user => userGuid == user.UserGuid)
            .Select(presence => new Presence{
                User = new User{
                    Guid = user.Guid,
                    Group = new Group{
                        ID = user.GroupID,
                        Name = _repositoryGroupImpl.GetAllGroup().First(group => group.ID == user.GroupID).Name
                    },
                    FIO = user.FIO
                },
                LessonNumber = presence.LessonNumber,
                Date = presence.Date,
                IsAttedance = presence.IsAttedance
            }).ToList();

            return presenceByUser;
        }

        public List<Presence> GetFalsePresenceByUser(Guid userGuid){
            var user = _repositoryUserImpl.GetUserByGuid(userGuid);

            var presenceByUser = _repositoryPresenceImpl.GetAllPresences()
            .Where(user => userGuid == user.UserGuid && user.IsAttedance == false)
            .Select(presence => new Presence{
                User = new User{
                    Guid = user.Guid,
                    Group = new Group{
                        ID = user.GroupID,
                        Name = _repositoryGroupImpl.GetAllGroup().First(group => group.ID == user.GroupID).Name
                    },
                    FIO = user.FIO
                },
                LessonNumber = presence.LessonNumber,
                Date = presence.Date,
                IsAttedance = presence.IsAttedance
            }).ToList();

            return presenceByUser;
        }
        
        public List<Presence> GetPresenceByGroupByTime(int groupID, DateOnly date){
            var usersByGroup = _repositoryUserImpl.GetAllUser()
            .Where(user => user.GroupID == groupID).ToList();

            var presenceByGroup = _repositoryPresenceImpl.GetAllPresences()
            .Where(x => usersByGroup.Any(user => user.Guid == x.UserGuid && x.Date == date))
            .Select(presence => new Presence{
                User = new User{
                    Guid = presence.UserGuid,
                    Group = new Group{
                        ID = groupID,
                        Name = _repositoryGroupImpl.GetAllGroup().First(group => group.ID == groupID).Name
                    },
                    FIO = usersByGroup.First(user => user.Guid == presence.UserGuid).FIO, 
                },
                LessonNumber = presence.LessonNumber,
                Date = presence.Date,
                IsAttedance = presence.IsAttedance
            }).ToList();

            return presenceByGroup;
        }

        public bool IsAttedance(int firstLesson, int lastLesson, DateOnly date, Guid UserGuid){
            _repositoryPresenceImpl.IsAttedance(firstLesson, lastLesson, date, UserGuid);
            return true;
        }

        public bool GeneratePresence(int firstLesson, int lastLesson, int groupID, DateOnly date)
        {
            var usersByGroup = _repositoryUserImpl.GetAllUser().Where(x => x.GroupID == groupID).ToList();
            var groupName = _repositoryGroupImpl.GetAllGroup().First(group => group.ID == groupID).Name;

            List<Presence> presenceList = new List<Presence>();

            for (int i = firstLesson; i <= lastLesson; i++)
            {
                foreach (UserLocalEntity user in usersByGroup)
                {
                    presenceList.Add(new Presence
                    {
                        User = new User
                        {
                            Group = new Group
                            {
                                ID = groupID,
                                Name = groupName
                            },
                            FIO = user.FIO,
                            Guid = user.Guid
                        },
                        IsAttedance = true,
                        Date = date,
                        LessonNumber = i
                    });
                }
            }

            var presenceLocalEntity = presenceList.Select(x => new PresenceLocalEntity
            {
                UserGuid = x.User.Guid,
                IsAttedance = x.IsAttedance,
                LessonNumber = x.LessonNumber,
                Date = x.Date
            }).ToList();

            _repositoryPresenceImpl.GeneratePresence(presenceLocalEntity);

            return true;
        }

        public bool GeneratePresenceWeek(int firstLesson, int lastLesson, int groupID, DateOnly date){
            for (int i = 0; i < 8; i++){
                GeneratePresence(firstLesson, lastLesson, groupID, date.AddDays(i));
            }
            return true;
        }
    }
}