package com.kalyshev.yan.user.service;

import com.kalyshev.yan.coffee.repository.CoffeeNotFoundException;
import com.kalyshev.yan.user.controller.UserDto;
import com.kalyshev.yan.user.model.User;
import com.kalyshev.yan.user.repository.UserNotFoundException;
import com.kalyshev.yan.user.repository.UserRepository;
import com.kalyshev.yan.util.validation.ValidatorUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Optional;

@Service
public class UserService {
    private final UserRepository userRepository;
    private final ValidatorUtil validatorUtil;
    public UserService(UserRepository userRepository,
                         ValidatorUtil validatorUtil) {
        this.userRepository = userRepository;
        this.validatorUtil = validatorUtil;
    }
    @Transactional
    public User addUser(String login, String fio, String phone, String password, String role) {
        if (!StringUtils.hasText(login)) {
            throw new IllegalArgumentException("User login is null or empty");
        }
        if (!StringUtils.hasText(fio)) {
            throw new IllegalArgumentException("User fio is null or empty");
        }
        if (!StringUtils.hasText(phone)) {
            throw new IllegalArgumentException("User phone is null or empty");
        }
        if (!StringUtils.hasText(password)) {
            throw new IllegalArgumentException("User password is null or empty");
        }
        if (!StringUtils.hasText(role)) {
            throw new IllegalArgumentException("User role is null or empty");
        }
        final User user = new User(login, fio, phone, password, role);
        validatorUtil.validate(user);
        return userRepository.save(user);
    }
    @Transactional(readOnly = true)
    public User findUser(Long id) {
        final Optional<User> user = userRepository.findById(id);
        return user.orElseThrow(() -> new UserNotFoundException(id));
    }
    @Transactional(readOnly = true)
    public User tryLogin(String login, String password) {
        Optional<User> user = userRepository.tryLogin(login, password);
        if (user.isPresent()) {
            return user.orElseThrow((() -> new UserNotFoundException((long)0))) ;
        } else {
            return new User((long)0,"", "", "", "", "");
        }

    }
    @Transactional(readOnly = true)
    public List<UserDto> findAllUsers(int pageNo, int pageSize, String sortBy, String sortDir) {
        Sort sort = sortDir.equalsIgnoreCase(Sort.Direction.ASC.name()) ? Sort.by(sortBy).ascending()
                : Sort.by(sortBy).descending();

        // create Pageable instance
        Pageable pageable = PageRequest.of(pageNo, pageSize, sort);

        Page<User> users = userRepository.findAll(pageable);

        // get content for page object
        List<User> listOfUsers = users.getContent();

        return listOfUsers.stream()
                .map(UserDto::new)
                .toList();
    }
    @Transactional
    public User updateUser(Long id, String login, String fio, String phone, String password, String role) {
        final User currentUser = findUser(id);
        if (StringUtils.hasText(login)) {
            currentUser.setLogin(login);
        }
        if (StringUtils.hasText(fio)) {
            currentUser.setFio(fio);
        }
        if (StringUtils.hasText(phone)) {
            currentUser.setPhone(phone);
        }
        if (StringUtils.hasText(password)) {
            currentUser.setPassword(password);
        }
        if (StringUtils.hasText(role)) {
            currentUser.setRole(role);
        }
        validatorUtil.validate(currentUser);
        return userRepository.save(currentUser);
    }
    @Transactional
    public User deleteUser(Long id) {
        final User currentUser = findUser(id);
        userRepository.delete(currentUser);
        return currentUser;
    }
    @Transactional
    public void deleteAllUsers() {
        userRepository.deleteAll();
    }
}