using Demo.Data.LocalData.Entity;
using Demo.Domain.Models;
using Demo.Domain.UseCase;
using System;

namespace Demo.UI
{
    public class MainMenu
    {
        private readonly UserUseCase _userUseCase;
        private readonly GroupUseCase _groupUseCase;
        private readonly AttendanceUseCase _attendanceUseCase;
        private readonly UseCaseGeneratePresence _presenceGenerator;

        // Конструктор с инициализацией всех необходимых зависимостей
        public MainMenu(UserUseCase userUseCase, GroupUseCase groupUseCase, AttendanceUseCase attendanceUseCase, UseCaseGeneratePresence presenceGenerator)
        {
            _userUseCase = userUseCase ?? throw new ArgumentNullException(nameof(userUseCase));
            _groupUseCase = groupUseCase ?? throw new ArgumentNullException(nameof(groupUseCase));
            _attendanceUseCase = attendanceUseCase ?? throw new ArgumentNullException(nameof(attendanceUseCase));
            _presenceGenerator = presenceGenerator ?? throw new ArgumentNullException(nameof(presenceGenerator));
        }

        public void DisplayMenu()
        {
            while (true)
            {
                Console.Clear();
                Console.WriteLine("1. Показать всех пользователей");
                Console.WriteLine("2. Удалить пользователя по GUID");
                Console.WriteLine("3. Обновить пользователя");
                Console.WriteLine("4. Найти пользователя по GUID");
                Console.WriteLine("5. Показать все группы");
                Console.WriteLine("6. Добавить группу");
                Console.WriteLine("7. Обновить группу");
                Console.WriteLine("8. Удалить группу по ID");
                Console.WriteLine("9. Найти группу по ID");
                Console.WriteLine("10. Показать все посещаемости");
                Console.WriteLine("11. Добавить посещаемость");
                Console.WriteLine("12. Обновить посещаемость");
                Console.WriteLine("13. Удалить посещаемость");
                Console.WriteLine("14. Генерация посещаемости на день");
                Console.WriteLine("15. Генерация посещаемости на неделю");
                Console.WriteLine("16. Показать посещаемость по группе и дате");
                Console.WriteLine("17. Показать посещаемость по группе за диапазон дат");

                Console.WriteLine("0. Выход");

                var choice = Console.ReadLine();
                switch (choice)
                {
                    case "1": ShowAllUsers(); break;
                    case "2": RemoveUser(); break;
                    case "3": UpdateUser(); break;
                    case "4": FindUserByGuid(); break;
                    case "5": ShowAllGroups(); break;
                    case "6": AddGroup(); break;
                    case "7": UpdateGroup(); break;
                    case "8": RemoveGroup(); break;
                    case "9": FindGroupById(); break;
                    case "10": ShowAllAttendances(); break;
                    case "11": AddAttendance(); break;
                    case "12": UpdateAttendance(); break;
                    case "13": RemoveAttendance(); break;
                    case "14": GeneratePresenceForDay(); break;
                    case "15": GeneratePresenceForWeek(); break;
                    case "16": ShowAttendancesByGroupAndDate(); break;
                    case "17": ShowAttendancesByGroupAndDateRange(); break;
                    case "0": return;
                    default: Console.WriteLine("Неверный ввод. Попробуйте снова."); break;
                }

                Console.WriteLine("Нажмите любую клавишу для продолжения...");
                Console.ReadKey();
            }
        }

        private void ShowAllUsers()
        {
            var users = _userUseCase.GetAllUsers();
            Console.WriteLine("Все пользователи:");
            foreach (var user in users)
            {
                Console.WriteLine($"GUID: {user.Guid}, ФИО: {user.FIO}, Группа ID: {user.GroupID}");
            }
        }

        private void RemoveUser()
        {
            Console.Write("Введите GUID пользователя для удаления: ");
            if (Guid.TryParse(Console.ReadLine(), out var userGuid))
            {
                var removed = _userUseCase.RemoveUser(userGuid);
                Console.WriteLine(removed ? "Пользователь удалён." : "Пользователь не найден.");
            }
            else
            {
                Console.WriteLine("Некорректный GUID.");
            }
        }

        private void UpdateUser()
        {
            Console.Write("Введите GUID пользователя для обновления: ");
            if (Guid.TryParse(Console.ReadLine(), out var userGuid))
            {
                var user = _userUseCase.FindUserByGuid(userGuid);
                if (user != null)
                {
                    Console.Write("Введите новое имя пользователя: ");
                    user.FIO = Console.ReadLine();

                    var updated = _userUseCase.UpdateUser(user);
                    Console.WriteLine(updated ? "Пользователь обновлён." : "Не удалось обновить пользователя.");
                }
                else
                {
                    Console.WriteLine("Пользователь не найден.");
                }
            }
            else
            {
                Console.WriteLine("Некорректный GUID.");
            }
        }

        private void FindUserByGuid()
        {
            Console.Write("Введите GUID пользователя для поиска: ");
            if (Guid.TryParse(Console.ReadLine(), out var userGuid))
            {
                var userModel = _userUseCase.GetUserModelByGuid(userGuid);
                Console.WriteLine(userModel != null ? $"Пользователь найден: GUID = {userModel.Guid}, ФИО = {userModel.FIO}" : "Пользователь не найден.");
            }
            else
            {
                Console.WriteLine("Некорректный GUID.");
            }
        }

        private void ShowAllGroups()
        {
            var groups = _groupUseCase.GetAllGroups();
            Console.WriteLine("Все группы:");
            foreach (var group in groups)
            {
                Console.WriteLine($"ID: {group.Id}, Название: {group.Name}");
            }
        }

        private void AddGroup()
        {
            Console.Write("Введите название новой группы: ");
            var groupName = Console.ReadLine();
            var group = new Demo.Domain.Models.Group { Name = groupName };
            _groupUseCase.AddGroup(group);
            Console.WriteLine("Группа добавлена.");
        }

        private void UpdateGroup()
        {
            Console.Write("Введите ID группы для обновления: ");
            if (int.TryParse(Console.ReadLine(), out var groupId))
            {
                var group = _groupUseCase.GetGroupById(groupId);
                if (group != null)
                {
                    Console.Write("Введите новое название группы: ");
                    group.Name = Console.ReadLine();
                    var updated = _groupUseCase.UpdateGroup(group);
                    Console.WriteLine(updated ? "Группа обновлена." : "Не удалось обновить группу.");
                }
                else
                {
                    Console.WriteLine("Группа не найдена.");
                }
            }
            else
            {
                Console.WriteLine("Некорректный ID.");
            }
        }

        private void RemoveGroup()
        {
            Console.Write("Введите ID группы для удаления: ");
            if (int.TryParse(Console.ReadLine(), out var groupId))
            {
                var removed = _groupUseCase.RemoveGroupById(groupId);
                Console.WriteLine(removed ? "Группа удалена." : "Группа не найдена.");
            }
            else
            {
                Console.WriteLine("Некорректный ID.");
            }
        }

        private void FindGroupById()
        {
            Console.Write("Введите ID группы для поиска: ");
            if (int.TryParse(Console.ReadLine(), out var groupId))
            {
                var group = _groupUseCase.GetGroupById(groupId);
                Console.WriteLine(group != null ? $"Группа найдена: ID = {group.Id}, Название = {group.Name}" : "Группа не найдена.");
            }
            else
            {
                Console.WriteLine("Некорректный ID.");
            }
        }

        private void ShowAllAttendances()
        {
            var attendances = _attendanceUseCase.GetAllAttendances();
            Console.WriteLine("Все посещаемости:");
            foreach (var attendance in attendances)
            {
                Console.WriteLine($"User ID: {attendance.UserGuid}, Date: {attendance.Date}, Present: {attendance.IsPresent}");
            }
        }

        private void AddAttendance()
        {
            Console.Write("Введите GUID пользователя: ");
            if (Guid.TryParse(Console.ReadLine(), out var userGuid))
            {
                Console.Write("Введите дату (гггг-мм-дд): ");
                if (DateOnly.TryParse(Console.ReadLine(), out var date))
                {
                    Console.Write("Введите номер урока: ");
                    if (int.TryParse(Console.ReadLine(), out var lessonNumber))
                    {
                        var attendance = new Attendance { UserGuid = userGuid, Date = date, LessonNumber = lessonNumber, IsPresent = true };
                        _attendanceUseCase.AddAttendance(attendance);
                        Console.WriteLine("Посещаемость добавлена.");
                    }
                    else
                    {
                        Console.WriteLine("Некорректный номер урока.");
                    }
                }
                else
                {
                    Console.WriteLine("Некорректная дата.");
                }
            }
            else
            {
                Console.WriteLine("Некорректный GUID.");
            }
        }

        private void UpdateAttendance()
        {
            Console.Write("Введите GUID пользователя: ");
            if (Guid.TryParse(Console.ReadLine(), out var userGuid))
            {
                Console.Write("Введите дату (гггг-мм-дд): ");
                if (DateOnly.TryParse(Console.ReadLine(), out var date))
                {
                    Console.Write("Введите статус присутствия (true/false): ");
                    if (bool.TryParse(Console.ReadLine(), out var isPresent))
                    {
                        var attendance = new Attendance { UserGuid = userGuid, Date = date, LessonNumber = 1, IsPresent = isPresent };
                        var updated = _attendanceUseCase.UpdateAttendance(attendance);
                        Console.WriteLine(updated ? "Посещаемость обновлена." : "Запись о посещаемости не найдена.");
                    }
                    else
                    {
                        Console.WriteLine("Некорректный статус присутствия.");
                    }
                }
                else
                {
                    Console.WriteLine("Некорректная дата.");
                }
            }
            else
            {
                Console.WriteLine("Некорректный GUID.");
            }
        }

        private void RemoveAttendance()
        {
            Console.Write("Введите GUID пользователя: ");
            if (Guid.TryParse(Console.ReadLine(), out var userGuid))
            {
                Console.Write("Введите дату (гггг-мм-дд): ");
                if (DateOnly.TryParse(Console.ReadLine(), out var date))
                {
                    var removed = _attendanceUseCase.RemoveAttendance(userGuid, date);
                    Console.WriteLine(removed ? "Посещаемость удалена." : "Запись о посещаемости не найдена.");
                }
                else
                {
                    Console.WriteLine("Некорректная дата.");
                }
            }
            else
            {
                Console.WriteLine("Некорректный GUID.");
            }
        }

        private void GeneratePresenceForDay()
        {
            Console.Write("Введите ID группы: ");
            if (int.TryParse(Console.ReadLine(), out var groupId))
            {
                Console.Write("Введите номер первого занятия: ");
                if (int.TryParse(Console.ReadLine(), out var firstLesson))
                {
                    Console.Write("Введите номер последнего занятия: ");
                    if (int.TryParse(Console.ReadLine(), out var lastLesson))
                    {
                        var currentDate = DateOnly.FromDateTime(DateTime.Now);
                        _presenceGenerator.GeneratePresenceForDay(firstLesson, lastLesson, groupId, currentDate);
                        Console.WriteLine("Посещаемость на текущий день сгенерирована.");
                    }
                    else
                    {
                        Console.WriteLine("Некорректный номер последнего занятия.");
                    }
                }
                else
                {
                    Console.WriteLine("Некорректный номер первого занятия.");
                }
            }
            else
            {
                Console.WriteLine("Некорректный ID группы.");
            }
        }

        private void GeneratePresenceForWeek()
        {
            Console.Write("Введите ID группы: ");
            if (int.TryParse(Console.ReadLine(), out var groupId))
            {
                Console.Write("Введите номер первого занятия: ");
                if (int.TryParse(Console.ReadLine(), out var firstLesson))
                {
                    Console.Write("Введите номер последнего занятия: ");
                    if (int.TryParse(Console.ReadLine(), out var lastLesson))
                    {
                        var startDate = DateOnly.FromDateTime(DateTime.Now);
                        _presenceGenerator.GeneratePresenceForWeek(firstLesson, lastLesson, groupId, startDate);
                        Console.WriteLine("Посещаемость на неделю сгенерирована.");
                    }
                    else
                    {
                        Console.WriteLine("Некорректный номер последнего занятия.");
                    }
                }
                else
                {
                    Console.WriteLine("Некорректный номер первого занятия.");
                }
            }
            else
            {
                Console.WriteLine("Некорректный ID группы.");
            }
        }
        private void ShowAttendancesByGroupAndDate()
        {
            Console.Write("Введите ID группы: ");
            if (int.TryParse(Console.ReadLine(), out var groupId))
            {
                Console.Write("Введите дату (гггг-мм-дд): ");
                if (DateOnly.TryParse(Console.ReadLine(), out var date))
                {
                    var attendances = _attendanceUseCase.GetAttendancesByGroupAndDate(groupId, date);
                    if (attendances.Any())
                    {
                        // Построение таблицы
                        Console.WriteLine($"\nПосещаемость для группы {groupId} на дату {date:yyyy-MM-dd}:\n");

                        // Заголовок таблицы
                        Console.WriteLine("+------------------------------------------+-----------+");
                        Console.WriteLine($"| {"UserGuid",-40} | {"IsPresent",-9} |");
                        Console.WriteLine("+------------------------------------------+-----------+");

                        // Данные таблицы
                        foreach (var attendance in attendances)
                        {
                            Console.WriteLine($"| {attendance.UserGuid,-40} | {attendance.IsPresent,-9} |");
                            Console.WriteLine("+------------------------------------------+-----------+");
                        }
                    }
                    else
                    {
                        Console.WriteLine($"\nНет данных о посещаемости для группы {groupId} на дату {date:yyyy-MM-dd}.");
                    }
                }
                else
                {
                    Console.WriteLine("Некорректная дата.");
                }
            }
            else
            {
                Console.WriteLine("Некорректный ID группы.");
            }
        }

        private void ShowAttendancesByGroupAndDateRange()
        {
            Console.Write("Введите ID группы: ");
            if (int.TryParse(Console.ReadLine(), out var groupId))
            {
                Console.Write("Введите начальную дату (гггг-мм-дд): ");
                if (DateOnly.TryParse(Console.ReadLine(), out var startDate))
                {
                    Console.Write("Введите конечную дату (гггг-мм-дд): ");
                    if (DateOnly.TryParse(Console.ReadLine(), out var endDate))
                    {
                        var attendances = _attendanceUseCase.GetAttendancesByGroupAndDateRange(groupId, startDate, endDate);
                        if (attendances.Any())
                        {
                            // Построение таблицы
                            Console.WriteLine($"\nПосещаемость для группы {groupId} с {startDate:yyyy-MM-dd} по {endDate:yyyy-MM-dd}:\n");

                            // Заголовок таблицы
                            Console.WriteLine("+------------+------------------------------------------+-----------+");
                            Console.WriteLine($"| {"Date",-10} | {"UserGuid",-40} | {"IsPresent",-9} |");
                            Console.WriteLine("+------------+------------------------------------------+-----------+");

                            // Данные таблицы
                            foreach (var attendance in attendances)
                            {
                                Console.WriteLine($"| {attendance.Date,-10} | {attendance.UserGuid,-40} | {attendance.IsPresent,-9} |");
                                Console.WriteLine("+------------+------------------------------------------+-----------+");
                            }
                        }
                        else
                        {
                            Console.WriteLine($"\nНет данных о посещаемости для группы {groupId} за период с {startDate:yyyy-MM-dd} по {endDate:yyyy-MM-dd}.");
                        }
                    }
                    else
                    {
                        Console.WriteLine("Некорректная конечная дата.");
                    }
                }
                else
                {
                    Console.WriteLine("Некорректная начальная дата.");
                }
            }
            else
            {
                Console.WriteLine("Некорректный ID группы.");
            }
        }


    }
}
