using data.Exception;
using data.Repository;
using domain.Models;

namespace domain.UseCase
{
    // Класс UserUseCase предоставляет операции с пользователями и их группами.
    public class UserUseCase
    {
        private readonly IUserRepository _repositoryUserImpl; // Репозиторий для работы с пользователями.
        private readonly IGroupRepository _repositoryGroupImpl; // Репозиторий для работы с группами.

        // Конструктор для инициализации зависимостей.
        public UserUseCase(IUserRepository repositoryImpl, IGroupRepository repositoryGroupImpl)
        {
            _repositoryUserImpl = repositoryImpl;// Репозиторий пользователей.
            _repositoryGroupImpl = repositoryGroupImpl;// Репозиторий групп.
        }

        // Получить список всех пользователей с их группами.
        public List<User> GetAllUsers() => _repositoryUserImpl.GetAllUsers.Join(_repositoryGroupImpl.GetAllGroup(),
            user => user.GroupID,
            group => group.Id,
            (user, group) =>
            new User
            {
                FIO = user.FIO,
                Guid = user.Guid,
                Group = new Group { Id = group.Id, Name = group.Name }
            }).ToList();// Список пользователей.

        // Удалить пользователя по GUID.
        public bool RemoveUserByGuid(Guid userGuid)
        {
            try
            {
                // Возвращает true, если пользователь успешно удален, иначе false.
                return _repositoryUserImpl.RemoveUserByGuid(userGuid);
            }
            catch (UserNotFoundException)
            {
                return false;// Пользователь не найден.
            }
            catch (RepositoryException)
            {
                return false;// Общая ошибка репозитория.
            }
        }

        // Обновить информацию о пользователе.
        public User UpdateUser(User user)
        {
            // Обновление пользователя в репозитории.
            var updatedUser = _repositoryUserImpl.UpdateUser(new UserLocalEntity
            {
                FIO = user.FIO,
                GroupID = user.Group.Id,
                Guid = user.Guid
            }) ?? throw new Exception("Ошибка при обновлении пользователя.");

            // Получение информации о группе.
            var group = _repositoryGroupImpl.GetAllGroup()
                .FirstOrDefault(g => g.Id == updatedUser.GroupID)
                ?? throw new Exception("Группа не найдена.");

            // Возврат обновленного пользователя.
            return new User
            {
                FIO = updatedUser.FIO,
                Guid = updatedUser.Guid,
                Group = new Group { Id = group.Id, Name = group.Name }
            };
        }


        // Найти пользователя по GUID.
        public User FindUserByGuid(Guid userGuid)
        {
            // Поиск пользователя и его группы.
            var user = _repositoryUserImpl.GetAllUsers
                .FirstOrDefault(u => u.Guid == userGuid)
                ?? throw new Exception("Пользователь не найден.");

            var group = _repositoryGroupImpl.GetAllGroup()
                .FirstOrDefault(g => g.Id == user.GroupID)
                ?? throw new Exception("Группа не найдена.");

            // Возврат пользователя с группой.
            return new User
            {
                FIO = user.FIO,
                Guid = user.Guid,
                Group = new Group { Id = group.Id, Name = group.Name }
            };
        }

    }
}
