package com.fsd.hellovelo.service;

import com.fsd.hellovelo.controller.UserController;
import com.fsd.hellovelo.entity.ERole;
import com.fsd.hellovelo.entity.EStatus;
import com.fsd.hellovelo.entity.Role;
import com.fsd.hellovelo.entity.User;
import com.fsd.hellovelo.exceptions.ResourceNotFoundException;
import com.fsd.hellovelo.payload.request.SignupRequest;
import com.fsd.hellovelo.payload.request.UpdateUserRequest;
import com.fsd.hellovelo.payload.request.UserStatus;
import com.fsd.hellovelo.repository.RoleRepository;
import com.fsd.hellovelo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.SQLIntegrityConstraintViolationException;
import java.util.*;

@Service
public class AdminUserService {

    private final UserRepository userRepository;
    private final RoleRepository roleRepository;

    @Autowired
    public AdminUserService(UserRepository userRepository, RoleRepository roleRepository){
        this.userRepository = userRepository;
        this.roleRepository = roleRepository;
    }

    public List<User> getUsers() {
        return userRepository.findAll();
    }

    public User getUser(Long id) {
        return userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("Error: User " + id + " not found."));
    }

    public void updateUser(UpdateUserRequest userInput){
        User user = userRepository.findById(userInput.getId()).orElseThrow(() -> new ResourceNotFoundException("Error: User " + userInput.getId() + " not found."));
        Optional<User> byUsername = userRepository.findByUsername(userInput.getUsername());
        if(byUsername.isPresent() && !byUsername.get().getId().equals(userInput.getId())){
            throw new IllegalArgumentException("Error: Username already taken.");
        }
        Optional<User> byEmail = userRepository.findByUsername(userInput.getEmail());
        if(byEmail.isPresent() && !byEmail.get().getId().equals(userInput.getId())){
            throw new IllegalArgumentException("Error: Email already in use");
        }
        user.setEmail(userInput.getEmail());
        user.setUsername(userInput.getUsername());
        user.setLastName(userInput.getLastName());
        user.setFirstName(userInput.getFirstName());
        switch (userInput.getStatus().toLowerCase()) {
            case "active" -> user.setStatus(EStatus.ACTIVE);
            case "disabled" -> user.setStatus(EStatus.DISABLED);
            default -> throw new IllegalArgumentException("Error: Status is not recognized.");
        }

        Set<String> strRoles = userInput.getRole();
        Set<Role> roles = new HashSet<>();
        if (strRoles == null) {
            Role userRole = roleRepository.findByName(ERole.ROLE_USER)
                    .orElseThrow(() -> new RuntimeException("Error: Role is not found."));
            roles.add(userRole);
        } else {
            strRoles.forEach(role -> {
                switch (role) {
                    case "admin":
                        Role adminRole = roleRepository.findByName(ERole.ROLE_ADMIN)
                                .orElseThrow(() -> new RuntimeException("Error: Role is not found."));
                        roles.add(adminRole);
                        break;
                    case "mod":
                        Role modRole = roleRepository.findByName(ERole.ROLE_MODERATOR)
                                .orElseThrow(() -> new RuntimeException("Error: Role is not found."));
                        roles.add(modRole);
                        break;
                    default:
                        Role userRole = roleRepository.findByName(ERole.ROLE_USER)
                                .orElseThrow(() -> new RuntimeException("Error: Role is not found."));
                        roles.add(userRole);
                }
            });
        }
        user.setRoles(roles);
        userRepository.save(user);
    }

    public void deleteUser(Long id) {
        User user = userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("User with id " + id + " not found."));
        user.setStatus(EStatus.DISABLED);
        userRepository.save(user);
    }

    public void updateStatus(Long id, UserStatus status) {
        User user = userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("Error: user with id " + id + "not found."));
        if(status.status == null){
            throw new IllegalArgumentException("Error: Status is empty.");
        }
        switch (status.status.toLowerCase()) {
            case "active" -> user.setStatus(EStatus.ACTIVE);
            case "disabled" -> user.setStatus(EStatus.DISABLED);
            default -> throw new IllegalArgumentException("Error: Status is not recognized.");
        }
        userRepository.save(user);
    }

    public List<User> getActiveUsers() {
        return userRepository.findByStatus(EStatus.ACTIVE);
    }
}
