using ClosedXML.Excel;
using data.RemoteData.DAO;
using data.Repository;
using domain.Models;

namespace domain.UseCase
{
    public class UseCaseGeneratePresence
    {
        public readonly IUserRepository _userRepository; // Репозиторий пользователей
        public readonly IPresenceRepository _presenceRepository; // Репозиторий посещаемости
        private readonly IGroupRepository _groupRepository; // Репозиторий групп

        // Конструктор класса UseCaseGeneratePresence.
        // Инициализирует зависимости для работы с пользователями, посещаемостью и группами.
        public UseCaseGeneratePresence(IUserRepository userRepository, IPresenceRepository presenceRepository, IGroupRepository groupRepository)
        {
            // Сохраняем переданный репозиторий пользователей в поле класса
            _userRepository = userRepository;

            // Сохраняем переданный репозиторий посещаемости в поле класса
            _presenceRepository = presenceRepository;

            // Сохраняем переданный репозиторий групп в поле класса
            _groupRepository = groupRepository;
        }

        // Получить посещаемость по группе и дате
        public List<PresenceLocalEntity> GetPresenceByGroupAndDate(int groupId, DateTime date)
        {
            return _presenceRepository.GetPresenceByGroupAndDate(groupId, date);
        }

        public void GeneratePresenceForDay(int firstLesson, int lastLesson, int groupId, DateTime currentDate)
        {
            // Проверяем существование группы
            if (!_groupRepository.GetAllGroup().Any(g => g.Id == groupId))
                throw new ArgumentException($"Группа с ID {groupId} не существует.");

            // Получаем пользователей группы
            var users = _userRepository.GetAllUsers
                .Where(u => u.GroupID == groupId)
                .Select(u => u.Guid)
                .ToList();

            // Генерируем записи посещаемости
            var presences = Enumerable.Range(firstLesson, lastLesson - firstLesson + 1)
                .SelectMany(lesson => users.Select(userGuid => new PresenceLocalEntity
                {
                    UserGuid = userGuid,
                    Date = currentDate,
                    LessonNumber = lesson,
                    IsAttedance = true
                }))
                .ToList();

            // Сохраняем записи
            _presenceRepository.SavePresence(presences);
        }


        public void GeneratePresenceForWeek(int firstLesson, int lastLesson, int groupId, DateTime startTime)
        {
            // Проверяем, существует ли группа
            var groupExists = _groupRepository.GetAllGroup().Any(g => g.Id == groupId);
            if (!groupExists)
            {
                throw new ArgumentException($"Группа с ID {groupId} не существует.");
            }

            // Генерируем посещаемость для каждого дня недели
            for (int i = 0; i < 7; i++)
            {
                DateTime currentTime = startTime.AddDays(i);
                GeneratePresenceForDay(firstLesson, lastLesson, groupId, currentTime);
            }
        }

        // Отметить пользователя как отсутствующего
        public void MarkUserAsAbsent(Guid userGuid, int groupId, int firstLesson, int lastLesson, DateTime date)
        {
            // Получаем записи о посещаемости
            var presences = _presenceRepository.GetPresenceByGroupAndDate(groupId, date);

            // Помечаем нужные записи как отсутствующие
            foreach (var presence in presences.Where(p => p.UserGuid == userGuid && p.LessonNumber >= firstLesson && p.LessonNumber <= lastLesson))
            {
                presence.IsAttedance = false;
            }
            // Сохраняем изменения
            _presenceRepository.SavePresence(presences);
        }

        // Получить все записи о посещаемости по группе
        public List<PresenceLocalEntity> GetAllPresenceByGroup(int groupId)
        {
            return _presenceRepository.GetPresenceByGroup(groupId);
        }

        // Получить общее резюме посещаемости для группы
        public GroupPresenceSummary GetGeneralPresenceForGroup(int groupId)
        {
            return _presenceRepository.GetGeneralPresenceForGroup(groupId);
        }

        // Получить всю посещаемость по всем группам
        public Dictionary<string, List<Excel>> GetAllAttendanceByGroups()
        {
            var attendanceByGroup = new Dictionary<string, List<Excel>>();
            var allGroups = _groupRepository.GetAllGroup();

            // Для каждой группы получаем записи о посещаемости
            foreach (var group in allGroups)
            {
                var groupAttendance = _presenceRepository.GetAttendanceByGroup(group.Id);
                var attendanceRecords = new List<Excel>();

                // Создаем записи для экспорта
                foreach (var record in groupAttendance)
                {
                    var names = _userRepository.GetUserNames().Where(u => u.Guid == record.UserGuid);
                    foreach (var name in names)
                    {
                        attendanceRecords.Add(new Excel
                        {
                            UserName = name.FIO,
                            UserGuid = name.Guid,
                            Date = record.Date,
                            IsAttedance = record.IsAttedance,
                            LessonNumber = record.LessonNumber,
                            GroupName = group.Name
                        });
                    }
                }
                // Сохраняем данные для группы
                attendanceByGroup.Add(group.Name, attendanceRecords);
            }
            return attendanceByGroup;
        }

        // Экспорт посещаемости в файл Excel
        public void ExportAttendanceToExcel()
        {
            var attendanceByGroup = GetAllAttendanceByGroups();

            // Определяем путь для сохранения файла
            string projectDirectory = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), @"..\..\.."));
            string reportsFolderPath = Path.Combine(projectDirectory, "Reports");
            string filePath = Path.Combine(reportsFolderPath, "AttendanceReport.xlsx");

            // Создаем папку, если ее нет
            Directory.CreateDirectory(reportsFolderPath);

            using var workbook = new XLWorkbook();

            // Создаем листы и заполняем данные
            foreach (var group in attendanceByGroup)
            {
                var worksheet = workbook.Worksheets.Add(group.Key);
                var header = new[] { "ФИО", "Группа", "Дата", "Занятие", "Статус" };
                for (int i = 0; i < header.Length; i++)
                    worksheet.Cell(1, i + 1).Value = header[i];

                int row = 2;

                foreach (var record in group.Value.OrderBy(r => r.Date).ThenBy(r => r.LessonNumber).ThenBy(r => r.UserGuid))
                {
                    worksheet.Cell(row, 1).Value = record.UserName;
                    worksheet.Cell(row, 2).Value = record.GroupName;
                    worksheet.Cell(row, 3).Value = record.Date.ToString("dd.MM.yyyy");
                    worksheet.Cell(row, 4).Value = record.LessonNumber.ToString();
                    worksheet.Cell(row, 5).Value = record.IsAttedance ? "Присутствует" : "Отсутствует";
                    row++;
                }

                // Автоматическая подгонка ширины колонок
                worksheet.Columns().AdjustToContents();
            }

            // Сохраняем файл
            workbook.SaveAs(filePath);
        }

    }
}
