using data.Exceptions;
using data.RemoteData.RemoteDataBase;
using data.RemoteData.RemoteDataBase.DAO;
using data.Repository;
using data.RemoteData.RemoteDataBase.DAO;

namespace data.Domain.UseCase
{
    public class UserUseCase
    {
        private readonly IUserRepository _repositoryUserImpl;
        private readonly IGroupRepository _repositoryGroupImpl;
        private readonly IPresenceRepository _repositoryPresenceImpl;
        public UserUseCase(IUserRepository repositoryImpl, IGroupRepository repositoryGroupImpl, IPresenceRepository presenceRepository)
        {
            _repositoryUserImpl = repositoryImpl;
            _repositoryGroupImpl = repositoryGroupImpl;
            _repositoryPresenceImpl = presenceRepository;
        }

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

        public void RemovePresenceByUserId(int userId)
        {
            using (var context = new RemoteDatabaseContext())
            {
                var presences = context.PresenceDaos.Where(p => p.UserId == userId).ToList();
                context.PresenceDaos.RemoveRange(presences);
                context.SaveChanges();
            }
        }

        // Приватный метод для валидации существования пользователя по 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;
        }

        // Вывести всех пользователей
        //упростить под ef
        public List<UserDao> GetAllUsers() => _repositoryUserImpl.GetAllUsers()
            .Join(_repositoryGroupImpl.GetAllGroups(),
            user => user.GroupId, // Ключ для пользователей
            group => group.Id, // Ключ для групп
            (user, group) => // Результирующий объект
            new UserDao
            {
                UserId = user.UserId,
                FIO = user.FIO,
                GroupId = group.Id
            }).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 UserDao UpdateUser(int userId, string newFio, int groupId)
        {
            ValidateUserFIO(newFio);
            ValidateGroupExistence(groupId);

            UserDao userDao = new UserDao
            {
                UserId = userId,
                FIO = newFio,
                GroupId = groupId
            };

            UserDao? result = _repositoryUserImpl.UpdateUser(userId, newFio, groupId);

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

            var groupEntity = ValidateGroupExistence(result.GroupId);

            return new UserDao
            {
                UserId = userId,
                FIO = newFio,
                GroupId = groupId
            };

        }

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

            return new UserDao
            {
                UserId = user.UserId,
                FIO = user.FIO,
                GroupId =group.Id
            };
        }
    }
}
