using System;
using System.Linq;
using Demo.Data.Repository;
using Demo.Domain.UseCase;
using Demo.Data.RemoteData.RemoteDataBase.DAO;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Demo.UI
{
    public class MainMenu
    {
        private readonly UserConsole _userConsole;
        private readonly GroupConsole _groupConsole;
        private readonly PresenceConsole _presenceConsole;
        private readonly ExcelExporter _excelExporter;
        private readonly GroupUseCase _groupUseCase;
        private readonly UserUseCase _userUseCase;
        private readonly UseCasePresence _presenceUseCase;

        public MainMenu(UserConsole userConsole, GroupConsole groupConsole, PresenceConsole presenceConsole, ExcelExporter excelExporter, GroupUseCase groupUseCase, UserUseCase userUseCase, UseCasePresence presenceUseCase)
        {
            _userConsole = userConsole;
            _groupConsole = groupConsole;
            _presenceConsole = presenceConsole;
            _excelExporter = excelExporter;
            _groupUseCase = groupUseCase;
            _userUseCase = userUseCase;
            _presenceUseCase = presenceUseCase;
        }

        public void ShowMenu()
        {
            while (true)
            {
                Console.WriteLine("=-= Команды с Пользователями =-=");
                Console.WriteLine("1. Вывести всех пользователей");
                Console.WriteLine("2. Удалить пользователя по id");
                Console.WriteLine("3. Обновить пользователя по id");
                Console.WriteLine("4. Найти пользователя по id");
                Console.WriteLine();

                Console.WriteLine("=-= Команды с Группами =-=");
                Console.WriteLine("5. Вывести все группы");
                Console.WriteLine("6. Добавить группу");
                Console.WriteLine("7. Изменить название группы");
                Console.WriteLine("8. Поиск группы по ID");
                Console.WriteLine();

                Console.WriteLine("=-= Команды Presence =-=");
                Console.WriteLine("9. Сгенерировать посещаемость на день");
                Console.WriteLine("10. Сгенерировать посещаемость на неделю");
                Console.WriteLine("11. Показать посещаемость");
                Console.WriteLine("12. Отметить пользователя как отсутствующего");
                Console.WriteLine("13. Вывести всю посещаемость группы");
                Console.WriteLine("14. Вывести общую информацию об посещаемости по группе");
                Console.WriteLine("15. Вывести отчёт в Excel");
                Console.WriteLine("16. Открыть АПИ");
                Console.WriteLine();
                Console.WriteLine("0. Выход");

                Console.Write("Выберите команду: ");

                if (int.TryParse(Console.ReadLine(), out int choice))
                {
                    switch (choice)
                    {
                        case 1:
                            _userConsole.DisplayAllUsers();
                            break;
                        case 2:
                            Console.Write("Введите id пользователя: ");
                            if (Guid.TryParse(Console.ReadLine(), out Guid userId))
                            {
                                _userConsole.DeleteUser(userId);
                            }
                            else
                            {
                                Console.WriteLine("Неверный формат id пользователя.");
                            }
                            break;
                        case 3:
                            Console.Write("Введите id пользователя: ");
                            if (Guid.TryParse(Console.ReadLine(), out Guid updateUserId))
                            {
                                var userToUpdate = _userUseCase.GetUserById(updateUserId);
                                if (userToUpdate != null)
                                {
                                    Console.Write("Введите новое ФИО: ");
                                    userToUpdate.FIO = Console.ReadLine();
                                    Console.Write("Введите новый GroupID: ");
                                    if (int.TryParse(Console.ReadLine(), out int newGroupID))
                                    {
                                        userToUpdate.GroupID = newGroupID;
                                        _userConsole.UpdateUser(userToUpdate);
                                    }
                                    else
                                    {
                                        Console.WriteLine("Неверный формат GroupID.");
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("Пользователь не найден.");
                                }
                            }
                            else
                            {
                                Console.WriteLine("Неверный формат id пользователя.");
                            }
                            break;
                        case 4:
                            Console.Write("Введите id пользователя: ");
                            if (Guid.TryParse(Console.ReadLine(), out Guid findUserId))
                            {
                                _userConsole.FindUser(findUserId);
                            }
                            else
                            {
                                Console.WriteLine("Неверный формат id пользователя.");
                            }
                            break;
                        case 5:
                            _groupConsole.DisplayAllGroups();
                            break;
                        case 6:
                            Console.Write("Введите название группы: ");
                            string groupName = Console.ReadLine();
                            var newGroup = new Group { Name = groupName };
                            _groupConsole.AddGroup(newGroup);
                            break;
                        case 7:
                            Console.Write("Введите id группы: ");
                            if (int.TryParse(Console.ReadLine(), out int groupId))
                            {
                                Console.Write("Введите новое название группы: ");
                                string newGroupName = Console.ReadLine();
                                _groupConsole.UpdateGroupName(groupId, newGroupName);
                            }
                            else
                            {
                                Console.WriteLine("Неверный формат id группы.");
                            }
                            break;
                        case 8:
                            Console.Write("Введите id группы: ");
                            if (int.TryParse(Console.ReadLine(), out int searchGroupId))
                            {
                                var group = _groupUseCase.GetAllGroups().FirstOrDefault(g => g.Id == searchGroupId);
                                if (group != null)
                                {
                                    Console.WriteLine($"ID: {group.Id}, Название: {group.Name}");
                                }
                                else
                                {
                                    Console.WriteLine("Группа не найдена.");
                                }
                            }
                            else
                            {
                                Console.WriteLine("Неверный формат id группы.");
                            }
                            break;
                        case 9:
                            Console.Write("Введите номер первого занятия: ");
                            if (int.TryParse(Console.ReadLine(), out int firstLesson))
                            {
                                Console.Write("Введите номер последнего занятия: ");
                                if (int.TryParse(Console.ReadLine(), out int lastLesson))
                                {
                                    Console.Write("Введите id группы: ");
                                    if (int.TryParse(Console.ReadLine(), out int groupIdForPresence))
                                    {
                                        Console.Write("Введите дату (yyyy-MM-dd): ");
                                        if (DateTime.TryParse(Console.ReadLine(), out DateTime date))
                                        {
                                            var generatePresenceUseCase = new UseCaseGeneratePresence(_presenceUseCase.PresenceRepository, _userUseCase.UserRepository);
                                            generatePresenceUseCase.GeneratePresenceForToday(firstLesson, lastLesson, groupIdForPresence, date);
                                            Console.WriteLine("Посещаемость сгенерирована на день.");
                                        }
                                        else
                                        {
                                            Console.WriteLine("Неверный формат даты.");
                                        }
                                    }
                                    else
                                    {
                                        Console.WriteLine("Неверный формат id группы.");
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("Неверный формат номера последнего занятия.");
                                }
                            }
                            else
                            {
                                Console.WriteLine("Неверный формат номера первого занятия.");
                            }
                            break;
                        case 10:
                            Console.Write("Введите номер первого занятия: ");
                            if (int.TryParse(Console.ReadLine(), out int firstLessonWeek))
                            {
                                Console.Write("Введите номер последнего занятия: ");
                                if (int.TryParse(Console.ReadLine(), out int lastLessonWeek))
                                {
                                    Console.Write("Введите id группы: ");
                                    if (int.TryParse(Console.ReadLine(), out int groupIdForPresenceWeek))
                                    {
                                        Console.Write("Введите дату начала недели (yyyy-MM-dd): ");
                                        if (DateTime.TryParse(Console.ReadLine(), out DateTime startDateWeek))
                                        {
                                            var generatePresenceUseCaseWeek = new UseCaseGeneratePresence(_presenceUseCase.PresenceRepository, _userUseCase.UserRepository);
                                            generatePresenceUseCaseWeek.GeneratePresenceForWeek(firstLessonWeek, lastLessonWeek, groupIdForPresenceWeek, startDateWeek);
                                            Console.WriteLine("Посещаемость сгенерирована на неделю.");
                                        }
                                        else
                                        {
                                            Console.WriteLine("Неверный формат даты.");
                                        }
                                    }
                                    else
                                    {
                                        Console.WriteLine("Неверный формат id группы.");
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("Неверный формат номера последнего занятия.");
                                }
                            }
                            else
                            {
                                Console.WriteLine("Неверный формат номера первого занятия.");
                            }
                            break;
                        case 11:
                            Console.Write("Введите id группы: ");
                            if (int.TryParse(Console.ReadLine(), out int groupIdForPresenceDisplay))
                            {
                                _presenceConsole.DisplayPresenceByGroup(groupIdForPresenceDisplay);
                            }
                            else
                            {
                                Console.WriteLine("Неверный формат id группы.");
                            }
                            break;
                        case 12:
                            Console.Write("Введите id пользователя: ");
                            if (Guid.TryParse(Console.ReadLine(), out Guid userIdForAbsent))
                            {
                                Console.Write("Введите номер занятия: ");
                                if (int.TryParse(Console.ReadLine(), out int lessonNumberForAbsent))
                                {
                                    Console.Write("Введите дату (yyyy-MM-dd): ");
                                    if (DateTime.TryParse(Console.ReadLine(), out DateTime dateForAbsent))
                                    {
                                        _presenceConsole.MarkUserAsAbsent(userIdForAbsent, lessonNumberForAbsent, dateForAbsent);
                                    }
                                    else
                                    {
                                        Console.WriteLine("Неверный формат даты.");
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("Неверный формат номера занятия.");
                                }
                            }
                            else
                            {
                                Console.WriteLine("Неверный формат id пользователя.");
                            }
                            break;
                        case 13:
                            Console.Write("Введите id группы: ");
                            if (int.TryParse(Console.ReadLine(), out int groupIdForPresenceAll))
                            {
                                _presenceConsole.DisplayPresenceByGroup(groupIdForPresenceAll);
                            }
                            else
                            {
                                Console.WriteLine("Неверный формат id группы.");
                            }
                            break;
                        case 14:
                            Console.Write("Введите id группы: ");
                            if (int.TryParse(Console.ReadLine(), out int groupIdForPresenceInfo))
                            {
                                var groupForInfo = _groupUseCase.GetAllGroups().FirstOrDefault(g => g.Id == groupIdForPresenceInfo);
                                if (groupForInfo != null)
                                {
                                    var usersForInfo = _userUseCase.GetAllUsers().Where(u => u.GroupID == groupIdForPresenceInfo).ToList();
                                    var presenceForInfo = _presenceUseCase.GetPresenceByGroup(groupIdForPresenceInfo).ToList();
                                    Console.WriteLine($"Количество человек в группе: {usersForInfo.Count}");
                                    Console.WriteLine($"Количество проведенных занятий: {presenceForInfo.Select(p => p.Date).Distinct().Count()}");
                                    Console.WriteLine($"Общий процент посещаемости: {presenceForInfo.Count(p => p.IsAttendance) * 100.0 / presenceForInfo.Count}%");
                                    foreach (var user in usersForInfo)
                                    {
                                        var userPresence = presenceForInfo.Where(p => p.UserId == user.Id).ToList();
                                        int attended = userPresence.Count(p => p.IsAttendance);
                                        int missed = userPresence.Count(p => !p.IsAttendance);
                                        double percentage = (attended * 100.0) / (attended + missed);
                                        Console.WriteLine($"ФИО: {user.FIO}, Посещено: {attended}, Пропущено: {missed}, Процент посещаемости: {percentage}%");
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("Группа не найдена.");
                                }
                            }
                            else
                            {
                                Console.WriteLine("Неверный формат id группы.");
                            }
                            break;
                        case 15:
                            Console.Write("Введите id группы: ");
                            if (int.TryParse(Console.ReadLine(), out int groupIdForExport))
                            {
                                var groupForExport = _groupUseCase.GetAllGroups().FirstOrDefault(g => g.Id == groupIdForExport);
                                if (groupForExport != null)
                                {
                                    var usersForExport = _userUseCase.GetAllUsers().Where(u => u.GroupID == groupIdForExport).ToList();
                                    var presenceForExport = _presenceUseCase.GetPresenceByGroup(groupIdForExport).ToList();

                                    // Указываем путь для сохранения файла
                                    string directoryPath = @"C:\Users\class_Student\Source\Repos\slarny4\Demo1\Excel";
                                    string filePath = Path.Combine(directoryPath, "GroupInfo.xlsx");

                                    // Проверяем, существует ли директория, и если нет, создаем её
                                    if (!Directory.Exists(directoryPath))
                                    {
                                        Directory.CreateDirectory(directoryPath);
                                    }

                                    _excelExporter.ExportGroupInfoToExcel(groupForExport, usersForExport, presenceForExport, filePath);
                                    Console.WriteLine("Отчёт экспортирован в Excel.");
                                }
                                else
                                {
                                    Console.WriteLine("Группа не найдена.");
                                }
                            }
                            else
                            {
                                Console.WriteLine("Неверный формат id группы.");
                            }
                            break;
                        case 16:
                            OpenBrowser("http://localhost:5000/swagger");
                            break;
                        case 0:
                            return;
                        default:
                            Console.WriteLine("Неверный ввод. Пожалуйста, введите число.");
                            break;
                    }
                }
                else
                {
                    Console.WriteLine("Неверный ввод. Пожалуйста, введите число.");
                }
            }
        }

        private static void OpenBrowser(string url)
        {
            try
            {
                Process.Start(url);
            }
            catch
            {
                // Если запуск через Process.Start не работает, попробуем другой метод
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    url = url.Replace("&", "^&");
                    Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true });
                }
                else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                {
                    Process.Start("xdg-open", url);
                }
                else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                {
                    Process.Start("open", url);
                }
                else
                {
                    throw;
                }
            }
        }
    }
}