// C:\Users\class_Student\source\repos\slarny4\Demo1\UI\MainMenu.cs
using System;
using System.Globalization;
using System.Linq;
using Demo.Domain.Models;
using Demo.Domain.UseCase;
using Demo.Data.Repository;
using Demo.Data.LocalData.Entity;
using Demo.Data.RemoteData.RemoteDataBase;
using Microsoft.EntityFrameworkCore;

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

        private readonly RemoteDatabaseContext _context;

        public MainMenu(RemoteDatabaseContext context = null)
        {
            if (context == null)
            {
                // Если контекст не предоставлен, создаем новый
                var optionsBuilder = new DbContextOptionsBuilder<RemoteDatabaseContext>();
                optionsBuilder.UseNpgsql("Host=45.67.56.214;Port=5421;Database=PresenceDB;Username=user5;Password=EtEJqhsf");
                _context = new RemoteDatabaseContext(optionsBuilder.Options);
            }
            else
            {
                _context = context;
            }

            // Инициализация репозиториев
            IUserRepository userRepository = new SQLUserRepositoryImpl(_context);
            IGroupRepository groupRepository = new GroupRepositoryImpl(_context);
            IPresenceRepository presenceRepository = new PresenceRepositoryImpl(_context);

            // Инициализация use cases
            _userUseCase = new UserUseCase(userRepository);
            _groupUseCase = new GroupUseCase(groupRepository);
            _presenceGenerator = new UseCaseGeneratePresence(presenceRepository, userRepository);
            _presenceUseCase = new PresenceUseCase(presenceRepository, groupRepository, userRepository);
        }

        public void Show()
        {
            bool exit = false;
            while (!exit)
            {
                Console.Clear();
                Console.WriteLine("=== Учёт Посещаемости ===");
                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("0. Выход");
                Console.Write("Выберите пункт меню: ");

                var input = Console.ReadLine() ?? string.Empty;

                Console.WriteLine();

                switch (input)
                {
                    case "1":
                        ShowAllUsers();
                        break;
                    case "2":
                        DeleteUserByGuid();
                        break;
                    case "3":
                        UpdateUser();
                        break;
                    case "4":
                        FindUserByGuid();
                        break;
                    case "5":
                        ShowAllGroups();
                        break;
                    case "6":
                        AddGroup();
                        break;
                    case "7":
                        UpdateGroup();
                        break;
                    case "8":
                        DeleteGroupById();
                        break;
                    case "9":
                        FindGroupById();
                        break;
                    case "10":
                        GenerateDailyPresence();
                        break;
                    case "11":
                        GenerateWeeklyPresence();
                        break;
                    case "12":
                        ShowPresenceByGroupAndDate();
                        break;
                    case "13":
                        MarkUserAbsent();
                        break;
                    case "14":
                        ShowAllPresences();
                        break;
                    case "0":
                        exit = true;
                        break;
                    default:
                        Console.WriteLine("Неверный выбор. Нажмите любую клавишу для продолжения...");
                        Console.ReadKey();
                        break;
                }
            }
        }

        private void ShowAllUsers()
        {
            var users = _userUseCase.GetAllUsers();
            Console.WriteLine("Список пользователей:");
            foreach (var user in users)
            {
                var group = _groupUseCase.GetGroupById(user.GroupID);
                Console.WriteLine($"ID: {user.Id} | ФИО: {user.FIO} | Группа: {group?.Name ?? "Неизвестно"}");
            }
            Pause();
        }

        private void DeleteUserByGuid()
        {
            Console.Write("Введите GUID пользователя для удаления: ");
            var input = Console.ReadLine();
            if (Guid.TryParse(input, out Guid userId))
            {
                try
                {
                    _userUseCase.DeleteUser(userId);
                    Console.WriteLine("Пользователь удалён.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Ошибка: {ex.Message}");
                }
            }
            else
            {
                Console.WriteLine("Неверный формат GUID.");
            }
            Pause();
        }

        private void UpdateUser()
        {
            Console.Write("Введите GUID пользователя для обновления: ");
            var input = Console.ReadLine();
            if (Guid.TryParse(input, out Guid userId))
            {
                try
                {
                    var user = _userUseCase.GetUserById(userId);
                    Console.WriteLine($"Текущие данные: ФИО: {user.FIO}, Группа ID: {user.GroupID}");
                    Console.Write("Введите новое ФИО (оставьте пустым, чтобы сохранить текущее): ");
                    var newFIO = Console.ReadLine();
                    Console.Write("Введите новый ID группы (оставьте пустым, чтобы сохранить текущую): ");
                    var groupInput = Console.ReadLine();

                    if (!string.IsNullOrWhiteSpace(newFIO))
                    {
                        user.FIO = newFIO;
                    }

                    if (!string.IsNullOrWhiteSpace(groupInput))
                    {
                        if (int.TryParse(groupInput, out int newGroupId))
                        {
                            var group = _groupUseCase.GetGroupById(newGroupId);
                            if (group != null)
                            {
                                user.GroupID = newGroupId;
                            }
                            else
                            {
                                Console.WriteLine("Группа с таким ID не найдена. Группа не обновлена.");
                            }
                        }
                        else
                        {
                            Console.WriteLine("Неверный формат ID группы. Группа не обновлена.");
                        }
                    }

                    _userUseCase.UpdateUser(user);
                    Console.WriteLine("Пользователь обновлён.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Ошибка: {ex.Message}");
                }
            }
            else
            {
                Console.WriteLine("Неверный формат GUID.");
            }
            Pause();
        }

        private void FindUserByGuid()
        {
            Console.Write("Введите GUID пользователя для поиска: ");
            var input = Console.ReadLine();
            if (Guid.TryParse(input, out Guid userId))
            {
                try
                {
                    var user = _userUseCase.GetUserById(userId);
                    var group = _groupUseCase.GetGroupById(user.GroupID);
                    Console.WriteLine($"ID: {user.Id} | ФИО: {user.FIO} | Группа: {group?.Name ?? "Неизвестно"}");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Ошибка: {ex.Message}");
                }
            }
            else
            {
                Console.WriteLine("Неверный формат GUID.");
            }
            Pause();
        }

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

        private void AddGroup()
        {
            Console.Write("Введите ID группы: ");
            var idInput = Console.ReadLine();
            Console.Write("Введите название группы: ");
            var name = Console.ReadLine() ?? string.Empty;
            if (int.TryParse(idInput, out int groupId))
            {
                var existingGroup = _groupUseCase.GetGroupById(groupId);
                if (existingGroup != null)
                {
                    Console.WriteLine("Группа с таким ID уже существует.");
                }
                else
                {
                    var group = new Group
                    {
                        Id = groupId,
                        Name = name
                    };
                    try
                    {
                        _groupUseCase.AddGroup(group);
                        Console.WriteLine("Группа добавлена.");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"Ошибка: {ex.Message}");
                    }
                }
            }
            else
            {
                Console.WriteLine("Неверный формат ID группы.");
            }
            Pause();
        }

        private void UpdateGroup()
        {
            Console.Write("Введите ID группы для обновления: ");
            var idInput = Console.ReadLine();
            if (int.TryParse(idInput, out int groupId))
            {
                try
                {
                    var group = _groupUseCase.GetGroupById(groupId);
                    Console.WriteLine($"Текущие данные: Название: {group.Name}");
                    Console.Write("Введите новое название группы: ");
                    var newName = Console.ReadLine();
                    if (!string.IsNullOrWhiteSpace(newName))
                    {
                        group.Name = newName;
                        _groupUseCase.UpdateGroup(group);
                        Console.WriteLine("Группа обновлена.");
                    }
                    else
                    {
                        Console.WriteLine("Название не может быть пустым. Группа не обновлена.");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Ошибка: {ex.Message}");
                }
            }
            else
            {
                Console.WriteLine("Неверный формат ID группы.");
            }
            Pause();
        }

        private void DeleteGroupById()
        {
            Console.Write("Введите ID группы для удаления: ");
            var input = Console.ReadLine();
            if (int.TryParse(input, out int groupId))
            {
                try
                {
                    _groupUseCase.DeleteGroup(groupId);
                    Console.WriteLine("Группа удалена.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Ошибка: {ex.Message}");
                }
            }
            else
            {
                Console.WriteLine("Неверный формат ID группы.");
            }
            Pause();
        }

        private void FindGroupById()
        {
            Console.Write("Введите ID группы для поиска: ");
            var input = Console.ReadLine();
            if (int.TryParse(input, out int groupId))
            {
                try
                {
                    var group = _groupUseCase.GetGroupById(groupId);
                    Console.WriteLine($"ID: {group.Id} | Название: {group.Name}");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Ошибка: {ex.Message}");
                }
            }
            else
            {
                Console.WriteLine("Неверный формат ID группы.");
            }
            Pause();
        }

        private void GenerateDailyPresence()
        {
            Console.Write("Введите номер первой пары: ");
            var firstLessonInput = Console.ReadLine();
            Console.Write("Введите номер последней пары: ");
            var lastLessonInput = Console.ReadLine();
            Console.Write("Введите ID группы: ");
            var groupIdInput = Console.ReadLine();
            Console.Write("Введите дату (yyyy-MM-dd): ");
            var dateInput = Console.ReadLine();

            if (int.TryParse(firstLessonInput, out int firstLesson) &&
                int.TryParse(lastLessonInput, out int lastLesson) &&
                int.TryParse(groupIdInput, out int groupId) &&
                DateTime.TryParseExact(dateInput, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date))
            {
                try
                {
                    _presenceGenerator.GenerateDailyPresence(groupId, firstLesson, lastLesson, date);
                    Console.WriteLine("Посещаемость сгенерирована.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Ошибка: {ex.Message}");
                }
            }
            else
            {
                Console.WriteLine("Неверные входные данные.");
            }
            Pause();
        }

        private void GenerateWeeklyPresence()
        {
            Console.Write("Введите номер первой пары: ");
            var firstLessonInput = Console.ReadLine();
            Console.Write("Введите номер последней пары: ");
            var lastLessonInput = Console.ReadLine();
            Console.Write("Введите ID группы: ");
            var groupIdInput = Console.ReadLine();
            Console.Write("Введите начальную дату недели (yyyy-MM-dd): ");
            var startDateInput = Console.ReadLine();

            if (int.TryParse(firstLessonInput, out int firstLesson) &&
                int.TryParse(lastLessonInput, out int lastLesson) &&
                int.TryParse(groupIdInput, out int groupId) &&
                DateTime.TryParseExact(startDateInput, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime startDate))
            {
                try
                {
                    _presenceGenerator.GenerateWeeklyPresence(groupId, firstLesson, lastLesson, startDate);
                    Console.WriteLine("Посещаемость на неделю сгенерирована.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Ошибка: {ex.Message}");
                }
            }
            else
            {
                Console.WriteLine("Неверные входные данные.");
            }
            Pause();
        }

        private void ShowPresenceByGroupAndDate()
        {
            Console.Write("Введите ID группы: ");
            var groupIdInput = Console.ReadLine();
            Console.Write("Введите дату (yyyy-MM-dd): ");
            var dateInput = Console.ReadLine();

            if (int.TryParse(groupIdInput, out int groupId) &&
                DateTime.TryParseExact(dateInput, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date))
            {
                try
                {
                    var presences = _presenceUseCase.GetPresencesByGroupAndDate(groupId, date);
                    var group = _groupUseCase.GetGroupById(groupId);
                    Console.WriteLine($"Посещаемость группы {group?.Name ?? "Неизвестно"} на {date.ToString("yyyy-MM-dd")}:");
                    foreach (var presence in presences)
                    {
                        var user = _userUseCase.GetUserById(presence.UserId);
                        Console.WriteLine($"Пользователь: {user.FIO} | Пара: {presence.LessonNumber} | Был/Не был: {(presence.WasPresent ? "Был" : "Не был")}");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Ошибка: {ex.Message}");
                }
            }
            else
            {
                Console.WriteLine("Неверные входные данные.");
            }
            Pause();
        }

        private void MarkUserAbsent()
        {
            Console.Write("Введите GUID пользователя: ");
            var userIdInput = Console.ReadLine();
            Console.Write("Введите номер пары: ");
            var lessonInput = Console.ReadLine();
            Console.Write("Введите дату (yyyy-MM-dd): ");
            var dateInput = Console.ReadLine();

            if (Guid.TryParse(userIdInput, out Guid userId) &&
                int.TryParse(lessonInput, out int lessonNumber) &&
                DateTime.TryParseExact(dateInput, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date))
            {
                try
                {
                    _presenceUseCase.MarkUserAbsent(userId, lessonNumber, date);
                    Console.WriteLine("Пользователь отмечен как отсутствующий.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Ошибка: {ex.Message}");
                }
            }
            else
            {
                Console.WriteLine("Неверные входные данные.");
            }
            Pause();
        }

        private void ShowAllPresences()
        {
            var presences = _presenceUseCase.GetAllPresences();
            Console.WriteLine("Вся посещаемость:");
            foreach (var presence in presences)
            {
                var user = _userUseCase.GetUserById(presence.UserId);
                var group = _groupUseCase.GetGroupById(user.GroupID);
                Console.WriteLine($"Пользователь: {user.FIO} | Группа: {group?.Name ?? "Неизвестно"} | Дата: {presence.ClassDate.ToString("yyyy-MM-dd")} | Пара: {presence.LessonNumber} | Был/Не был: {(presence.WasPresent ? "Был" : "Не был")}");
            }
            Pause();
        }

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