using data.RemoteData.RemoteDataBase;
using data.RemoteData.RemoteDataBase.DAO;
using System.Data;

namespace data.Repository
{
    public class SQLPresenceRepositoryImpl : IPresenceRepository
    {
        private readonly RemoteDatabaseContext _remoteDatabaseContext;

        public SQLPresenceRepositoryImpl(RemoteDatabaseContext remoteDatabaseContext)
        {
            _remoteDatabaseContext = remoteDatabaseContext;
        }


        public List<PresenceDao> GetAttendanceByGroup(int groupId)
        {
            // Получаем записи посещаемости для указанной группы
            return _remoteDatabaseContext.PresenceDaos
                .Where(p => p.GroupId == groupId)
                .Select(p => new PresenceDao
                {
                    UserId = p.UserId,
                    GroupId = p.GroupId,
                    Date = p.Date,
                    LessonNumber = p.LessonNumber,
                    IsAttedance = p.IsAttedance
                })
                .ToList();
        }


        public List<PresenceDao> GetPresenceForAbsent(DateTime date, int GroupId)
        {
            return _remoteDatabaseContext.PresenceDaos.Where(p => p.GroupId == GroupId && p.Date == DateOnly.FromDateTime(date)).ToList();
        }
        public List<PresenceDao> GetPresenceByDateAndGroup(DateTime date, int groupId)
        {
            return _remoteDatabaseContext.PresenceDaos.Where(p => p.Date == DateOnly.FromDateTime(date) &&
                                         _remoteDatabaseContext.Users.Any(u => u.GroupId == groupId && u.UserId == p.UserId)).ToList();
        }

        // Реализация метода для получения всех данных по группе
        public List<PresenceDao> GetPresenceByGroup(int groupId)
        {
            return _remoteDatabaseContext.PresenceDaos.Where(p => p.GroupId == groupId)
                                                      .OrderBy(p => p.Date)
                                                      .ThenBy(p => p.UserId).ToList();
        }

        public void SavePresence(List<PresenceDao> presences)
        {
            _remoteDatabaseContext.PresenceDaos.AddRange(presences.Select(it => new PresenceDao
            {
                Date = it.Date,
                IsAttedance = it.IsAttedance,
                LessonNumber = it.LessonNumber,
                UserId = it.UserId,
                GroupId = it.GroupId
            }));
            _remoteDatabaseContext.SaveChanges();
        }

        public void UpdateAtt(int userId, int groupId, int firstLesson, int lastLesson, DateOnly date, bool isAttendance)
        {
            // Находим все записи по UserId, GroupId, LessonNumber (в диапазоне) и дате
            var presences = _remoteDatabaseContext.PresenceDaos
                .Where(p => p.UserId == userId
                            && p.GroupId == groupId
                            && p.LessonNumber >= firstLesson
                            && p.LessonNumber <= lastLesson
                            && p.Date == date)
                .ToList();

            // Обновляем значение IsAttendance для всех найденных записей
            foreach (var presence in presences)
            {
                presence.IsAttedance = isAttendance;
            }

            _remoteDatabaseContext.SaveChanges(); // Сохраняем изменения в базе данных
        }

        public DateOnly? GetLastDateByGroupId(int groupId)
        {
            // Проверяем наличие записей о посещаемости в базе данных для данной группы.
            var lastDate = _remoteDatabaseContext.PresenceDaos
                .Where(p => p.GroupId == groupId)
                .OrderByDescending(p => p.Date)
                .Select(p => p.Date)
                .FirstOrDefault();

            return lastDate == default ? (DateOnly?)null : lastDate;
        }

        public List<PresenceDao> PresenceSort(List<PresenceDao> presences)
        {
            presences = _remoteDatabaseContext.PresenceDaos.OrderBy(p => p.Date).ToList();
            return presences;
        }


        public GroupAttendanceStatistics GetGeneralPresenceForGroup(int groupId)
        {
            var presences = _remoteDatabaseContext.PresenceDaos.Where(p => p.GroupId == groupId).OrderBy(p => p.LessonNumber).ToList();
            var dates = _remoteDatabaseContext.PresenceDaos;
            var distDates = dates.Select(p => p.Date).Distinct().ToList();
            int lesId = 0;
            int lesNum = 1;
            double att = 0;
            int days = -1;
            int countAllLes = 0;
            DateOnly date = DateOnly.MinValue;
            List<int> usersId = new List<int>();

            foreach (var presence in presences)
            {
                if (!usersId.Contains(presence.UserId))
                {
                    usersId.Add(presence.UserId);
                }
                if (presence.Date != date)
                {
                    date = presence.Date;
                    lesId++;
                    lesNum = presence.LessonNumber;
                    days++;
                }
                if (presence.LessonNumber != lesNum && date == presence.Date)
                {
                    lesNum = presence.LessonNumber;
                    countAllLes++;
                    lesId++;
                }


                if (presence.IsAttedance)
                {
                    att++;
                }

            }
            List<UserAttendance> a = new List<UserAttendance>();
            List<int> ids = new List<int>();
            double ok = 0;
            double skip = 0;
            int userId = 0;
            foreach (var user in usersId)
            {
                var users = _remoteDatabaseContext.PresenceDaos.Where(p => p.UserId == user);
                foreach (var usera in users)
                {
                    userId = usera.UserId;
                    if (!ids.Contains(usera.UserId))
                    {
                        skip = 0;
                        ok = 0;
                        ids.Add(userId);
                        a.Add(new UserAttendance { UserId = userId, Attended = ok, Missed = skip });
                        userId = usera.UserId;
                        if (usera.IsAttedance)
                        {
                            a.First(a => a.UserId == usera.UserId).Attended = ok += 1;
                        }
                        else
                        {
                            a.First(a => a.UserId == usera.UserId).Missed = skip += 1;
                        }
                    }
                    else
                    {
                        if (usera.IsAttedance)
                        {
                            a.First(a => a.UserId == usera.UserId).Attended = ok += 1;
                        }
                        else
                        {
                            a.First(a => a.UserId == usera.UserId).Missed = skip += 1;
                        }
                    }
                }
            }

            var statistics = new GroupAttendanceStatistics
            {
                UserCount = usersId.Count,
                TotalLessons = lesId,
                AttendancePercentage = att / usersId.Count / lesNum / distDates.Count() * 100
            };

            foreach (var user in a)
            {
                statistics.UserAttendanceDetails.Add(new UserAttendance
                {
                    UserId = user.UserId,
                    Attended = user.Attended,
                    Missed = user.Missed,
                    AttendanceRate = user.Attended / (user.Missed + user.Attended) * 100
                });
            }

            return statistics;
        }
    }
}
