using data.Repository;
using domain.UseCase;

namespace ui
{
    // Основное меню консольного пользовательского интерфейса.
    public class MainMenuUI
    {
        private readonly UserConsole _userConsole; // Консольный интерфейс для работы с пользователями.
        private readonly GroupConsole _groupConsole; // Консольный интерфейс для работы с группами.
        private readonly PresenceConsole _presenceConsole; // Консольный интерфейс для работы с посещаемостью.

        // Конструктор для инициализации зависимостей.
        public MainMenuUI(UserUseCase userUseCase, GroupUseCase groupUseCase, UseCaseGeneratePresence presenceUseCase, IPresenceRepository presenceRepository)
        {
            // Инициализация всех интерфейсов с соответствующими UseCase и репозиториями.
            _userConsole = new UserConsole(userUseCase);
            _groupConsole = new GroupConsole(groupUseCase);
            _presenceConsole = new PresenceConsole(presenceUseCase, presenceRepository);
        }

        // Основной метод для отображения меню и обработки ввода пользователя.
        public void DisplayMenu()
        {
            while (true)
            {
                // Отображение доступных команд в консоль.
                Console.WriteLine("\n=== Главное меню ===");
                Console.WriteLine("1. Все пользователи");
                Console.WriteLine("2. Найти пользователя");
                Console.WriteLine("3. Обновить данные пользователя");
                Console.WriteLine("4. Удалить пользователя");
                Console.WriteLine("5. Список всех групп");
                Console.WriteLine("6. Найти группу");
                Console.WriteLine("7. Создать группу");
                Console.WriteLine("8. Изменить название группы");
                Console.WriteLine("9. Удалить группу");
                Console.WriteLine("10. Сгенерировать посещаемость на день");
                Console.WriteLine("11. Сгенерировать посещаемость на неделю");
                Console.WriteLine("12. Показать посещаемость группы");
                Console.WriteLine("13. Посещаемость группы за день");
                Console.WriteLine("14. Отметить отсутствующего пользователя");
                Console.WriteLine("15. Экспорт посещаемости в Excel");
                Console.WriteLine("0. Выход");
                Console.Write("Выберите команду: ");

                // Считывание команды пользователя.
                string command = Console.ReadLine();
                Console.WriteLine();

                // Обработка команд через switch-case.
                switch (command)
                {
                    case "1":
                        _userConsole.AllUsers(); // Показать всех пользователей.
                        break;

                    case "2":
                        ExecuteGuidCommand("Введите Guid пользователя для поиска: ", _userConsole.FindUserByGuid);
                        break;

                    case "3":
                        ExecuteGuidCommand("Введите Guid пользователя для обновления: ", _userConsole.UpdateUserByGuid);
                        break;

                    case "4":
                        ExecuteGuidCommand("Введите Guid пользователя для удаления: ", _userConsole.RemoveUserByGuid);
                        break;

                    case "5":
                        _groupConsole.DisplayAllGroups(); // Показать все группы.
                        break;

                    case "6":
                        ExecuteIntCommand("Введите ID группы для поиска: ", _groupConsole.FindGroupById);
                        break;

                    case "7":
                        Console.Write("Введите название новой группы: ");
                        _groupConsole.AddGroup(Console.ReadLine()); // Создать новую группу.
                        break;

                    case "8":
                        ExecuteIntCommand("Введите ID группы для изменения: ", id =>
                        {
                            Console.Write("Введите новое название группы: ");
                            _groupConsole.UpdateGroupName(id, Console.ReadLine());
                        });
                        break;

                    case "9":
                        ExecuteIntCommand("Введите ID группы для удаления: ", id => _groupConsole.RemoveGroup(id.ToString()));
                        break;

                    case "10":
                        GenerateAttendance("день"); // Генерация посещаемости на день.
                        break;

                    case "11":
                        GenerateAttendance("неделю"); // Генерация посещаемости на неделю.
                        break;

                    case "12":
                        Console.Write("Введите дату (гггг-мм-дд): ");
                        DateTime date = DateTime.Parse(Console.ReadLine());
                        ExecuteIntCommand("Введите ID группы: ", id => _presenceConsole.DisplayPresence(date, id));
                        break;

                    case "13":
                        ExecuteIntCommand("Введите ID группы: ", _presenceConsole.DisplayAllPresenceByGroup);
                        break;

                    case "14":
                        Console.Write("Введите Guid пользователя: ");
                        Guid userGuid = Guid.Parse(Console.ReadLine());
                        GenerateAbsence(userGuid); // Отметить пользователя как отсутствующего.
                        break;

                    case "15":
                        _presenceConsole.ExportAttendanceToExcel(); // Экспорт посещаемости в Excel.
                        break;

                    case "0":
                        return; // Завершение программы.

                    default:
                        Console.WriteLine("Команда не распознана."); // Сообщение об ошибке.
                        break;
                }
            }
        }

        // Метод для обработки команд с параметром Guid.
        private void ExecuteGuidCommand(string prompt, Action<Guid> action)
        {
            Console.Write(prompt);
            if (Guid.TryParse(Console.ReadLine(), out Guid guid))
            {
                action(guid);
            }
            else
            {
                Console.WriteLine("Неверный формат Guid.");
            }
        }

        // Метод для обработки команд с параметром int.
        private void ExecuteIntCommand(string prompt, Action<int> action)
        {
            Console.Write(prompt);
            if (int.TryParse(Console.ReadLine(), out int value))
            {
                action(value);
            }
            else
            {
                Console.WriteLine("Неверный формат числа.");
            }
        }

        // Генерация посещаемости на день или неделю.
        private void GenerateAttendance(string period)
        {
            try
            {
                Console.Write("Введите номер первого занятия: ");
                int firstLesson = int.Parse(Console.ReadLine());
                Console.Write("Введите номер последнего занятия: ");
                int lastLesson = int.Parse(Console.ReadLine());

                ExecuteIntCommand("Введите ID группы: ", id =>
                {
                    if (period == "день")
                    {
                        _presenceConsole.GeneratePresenceForDay(DateTime.Now, id, firstLesson, lastLesson);
                        Console.WriteLine("Посещаемость на день сгенерирована.");
                    }
                    else
                    {
                        _presenceConsole.GeneratePresenceForWeek(DateTime.Now, id, firstLesson, lastLesson);
                        Console.WriteLine("Посещаемость на неделю сгенерирована.");
                    }
                });
            }
            catch
            {
                Console.WriteLine("Ошибка ввода данных.");
            }
        }

        // Отметка пользователя как отсутствующего.
        private void GenerateAbsence(Guid userGuid)
        {
            try
            {
                Console.Write("Введите номер первого занятия: ");
                int firstLesson = int.Parse(Console.ReadLine());
                Console.Write("Введите номер последнего занятия: ");
                int lastLesson = int.Parse(Console.ReadLine());

                ExecuteIntCommand("Введите ID группы: ", id =>
                {
                    _presenceConsole.MarkUserAsAbsent(DateTime.Now, id, userGuid, firstLesson, lastLesson);
                    Console.WriteLine("Пользователь отмечен как отсутствующий.");
                });
            }
            catch
            {
                Console.WriteLine("Ошибка ввода данных.");
            }
        }
    }
}
