using Demo.Data.Exceptions;
using Demo.Data.RemoteData.RemoteDataBase.DAO;
using Demo.Data.Repository;
using Demo.domain.Models;

namespace Demo.Domain.UseCase
{
    public class UserUseCase
    {
        private readonly IUserRepository _repositoryUserImpl;
        private readonly IGroupRepository _repositoryGroupImpl;

        public UserUseCase(IUserRepository repositoryImpl, IGroupRepository repositoryGroupImpl)
        {
            _repositoryUserImpl = repositoryImpl;
            _repositoryGroupImpl = repositoryGroupImpl;
        }

        // Приватный метод для валидации ФИО пользователя
        private void ValidateUserFIO(string fio)
        {
            if (string.IsNullOrWhiteSpace(fio))
            {
                throw new ArgumentException("ФИО не может быть пустым.");
            }
        }

        // Приватный метод для валидации существования пользователя по ID
        private UserDao ValidateUserExistence(int userId)
        {
            var user = _repositoryUserImpl.GetAllUsers
                .FirstOrDefault(u => u.UserId == userId);

            if (user == null)
            {
                throw new Exception("Пользователь не найден.");
            }

            return user;
        }

        // Приватный метод для валидации существования группы по ID
        private GroupDao ValidateGroupExistence(int groupId)
        {
            var group = _repositoryGroupImpl.GetAllGroups()
                .FirstOrDefault(g => g.Id == groupId);

            if (group == null)
            {
                throw new Exception("Группа не найдена.");
            }

            return group;
        }

        // Вывести всех пользователей
        public List<User> GetAllUsers() => _repositoryUserImpl.GetAllUsers
            .Join(_repositoryGroupImpl.GetAllGroups(),
            user => user.GroupId,
            group => group.Id,
            (user, group) =>
            new User
            {
                ID = user.UserId,
                FIO = user.FIO,
                Group = new Group { Id = group.Id, Name = group.Name }
            }).ToList();

        // Удалить пользователя по id
        public bool RemoveUserById(int userId)
        {
            try
            {
                return _repositoryUserImpl.RemoveUserById(userId);
            }
            catch (UserNotFoundException ex)
            {
                Console.WriteLine($"Ошибка: {ex.Message}");
                return false;
            }
            catch (RepositoryException ex)
            {
                Console.WriteLine($"Ошибка в репозитории: {ex.Message}");
                return false;
            }
        }

        // Обновить пользователя по id
        public User UpdateUser(User user)
        {
            ValidateUserFIO(user.FIO);
            ValidateGroupExistence(user.Group.Id);

            UserDao userDao = new UserDao
            {
                FIO = user.FIO,
                GroupId = user.Group.Id
            };

            UserDao? result = _repositoryUserImpl.UpdateUser(userDao);

            if (result == null)
            {
                throw new Exception("Ошибка при обновлении пользователя.");
            }

            var groupEntity = ValidateGroupExistence(result.GroupId);

            return new User
            {
                FIO = result.FIO,
                Group = new Group
                {
                    Id = groupEntity.Id,
                    Name = groupEntity.Name
                }
            };
        }

        // Найти пользователя по id
        public User FindUserById(int userId)
        {
            var user = ValidateUserExistence(userId);
            var group = ValidateGroupExistence(user.GroupId);

            return new User
            {
                FIO = user.FIO,
                Group = new Group { Id = group.Id, Name = group.Name }
            };
        }
    }
}
