package br.com.rayankonecny.userserviceapi.service;

import java.util.List;

import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import br.com.rayankonecny.userserviceapi.entity.User;
import br.com.rayankonecny.userserviceapi.mapper.UserMapper;
import br.com.rayankonecny.userserviceapi.repository.UserRepository;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import models.responses.UserResponse;
import models.exceptions.ResourceNotFoundException;
import models.requests.CreateUserRequest;
import models.requests.UpdateUserRequest;

@Service
@RequiredArgsConstructor
public class UserService {

    private final UserRepository repository;
    private final UserMapper mapper;
    private final BCryptPasswordEncoder encoder;

    public UserResponse findById(final String id) {
        return mapper.fromEntity(find(id));
    }

    public void save(CreateUserRequest request) {
        verifyIfEmailAlreadyEexists(request.email(), null);
        repository.save(mapper.fromRequest(request).withPassword(encoder.encode(request.password())));
    }

    private void verifyIfEmailAlreadyEexists(final String email, final String id) {
        repository.findByEmail(email).filter(user -> !user.getId().equals(id)).ifPresent(user -> {
            throw new DataIntegrityViolationException("Email [" + email + "] already exists");
        });
    }

    public List<UserResponse> findAll() {
        return repository.findAll().stream().map(user -> mapper.fromEntity(user)).toList();
    }

    public UserResponse update(final String id, @Valid
    final UpdateUserRequest request) {
        User entity = find(id);
        verifyIfEmailAlreadyEexists(request.email(), id);
        return mapper.fromEntity(repository.save(mapper.update(request, entity)
                .withPassword(request.password() != null ? encoder.encode(request.password()) : entity.getPassword())));
    }

    private User find(final String id) {
        return repository.findById(id).orElseThrow(() -> new ResourceNotFoundException(
                "Object not found! Id: " + id + ", Type: " + UserResponse.class.getSimpleName()));

    }
}