package de.votian.services.service;

import de.votian.services.entity.Employee;
import de.votian.services.entity.GenericDataContainer;
import de.votian.services.entity.User;
import de.votian.services.repository.EmployeeRepository;
import de.votian.services.repository.GenericDataContainerRepository;
import de.votian.services.repository.UserRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

@Service
@Transactional
public class UserService {

    private final UserRepository userRepository;
    private final EmployeeRepository employeeRepository;
    private final GenericDataContainerRepository gdcRepository;

    public UserService(UserRepository userRepository, EmployeeRepository employeeRepository,
                       GenericDataContainerRepository gdcRepository) {
        this.userRepository = userRepository;
        this.employeeRepository = employeeRepository;
        this.gdcRepository = gdcRepository;
    }

    public Optional<User> findById(Long id) {
        return userRepository.findById(Objects.requireNonNull(id));
    }

    public Optional<User> findByAccount(String account) {
        return userRepository.findByAccount(account);
    }

    public List<User> findByEmail(String email) {
        return userRepository.findByEmailWithHq(email);
    }

    public User save(User user) {
        return userRepository.save(Objects.requireNonNull(user));
    }

    public boolean isAccountUnique(String account) {
        return userRepository.findByAccount(account).isEmpty();
    }

    public boolean isAccountUniqueExcluding(String account, Long excludeId) {
        return userRepository.findByAccountExcludingId(account, excludeId).isEmpty();
    }

    public void changePassword(Long userId, String newPasswordHash) {
        userRepository.findById(Objects.requireNonNull(userId)).ifPresent(user -> {
            user.setPassword(newPasswordHash);
            user.setPasswordModify(LocalDateTime.now());
            userRepository.save(user);
        });
    }

    public void clearPassword(Long userId) {
        userRepository.findById(Objects.requireNonNull(userId)).ifPresent(user -> {
            user.setPassword("");
            userRepository.save(user);
        });
    }

    public void setTotpSessionKey(Long userId, String sessionKey) {
        userRepository.findById(Objects.requireNonNull(userId)).ifPresent(user -> {
            user.setTotpSessionKey(sessionKey);
            userRepository.save(user);
        });
    }

    public Optional<Employee> findEmployeeByUserId(Long userId) {
        return employeeRepository.findByUserId(userId);
    }

    public Optional<String> getPasswordChangeStatus(Long userId) {
        return gdcRepository.findByTypeAndIdAndField("usr", userId, "set_new_pwd")
                .map(GenericDataContainer::getContent);
    }

    public List<Object[]> getBirthdaysToday() {
        return userRepository.findBirthdaysToday();
    }
}
