package de.szut.casino.user;

import de.szut.casino.exceptionHandling.exceptions.UserNotFoundException;
import de.szut.casino.user.dto.CreateUserDto;
import jakarta.persistence.EntityExistsException;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Optional;

@Service
public class UserService {
    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }

    public UserEntity createUser(CreateUserDto createUserDto) {
        if (userRepository.existsByUsername(createUserDto.getUsername())) {
            throw new EntityExistsException("Username is already taken");
        }

        if (userRepository.existsByEmail(createUserDto.getEmail())) {
            throw new EntityExistsException("Email is already in use");
        }

        UserEntity user = new UserEntity(
                createUserDto.getEmail(),
                createUserDto.getUsername(),
                passwordEncoder.encode(createUserDto.getPassword()),
                BigDecimal.valueOf(100),
                RandomStringUtils.randomAlphanumeric(64)
        );

        return userRepository.save(user);
    }

    public UserEntity getCurrentUser() {
        String username = SecurityContextHolder.getContext().getAuthentication().getName();

        Optional<UserEntity> optionalUser = userRepository.findByUsername(username);
        if (optionalUser.isEmpty()) {
            throw new UserNotFoundException();
        }

        return optionalUser.get();
    }

    public Optional<UserEntity> getUserByVerificationToken(String token) {
        return this.userRepository.findOneByVerificationToken(token);
    }

    public void saveUser(UserEntity user) {
        userRepository.save(user);
    }

    public boolean isVerified(String usernameOrEmail) {
        Optional<UserEntity> optionalUser = userRepository.findOneByUsernameOrEmail(usernameOrEmail);

        if (!optionalUser.isPresent()) {
            return false;
        }

        return optionalUser.get().getEmailVerified();
    }

    public Optional<UserEntity> getUserByEmail(String email) {
        return userRepository.findByEmail(email);
    }

    public Optional<UserEntity> getUserByPasswordResetToken(String token) {
        return this.userRepository.findOneByPasswordResetToken(token);
    }
}
