package cn.reghao.oss.console.account.service.impl;

import cn.reghao.oss.console.account.db.repository.RoleRepository;
import cn.reghao.oss.console.account.db.repository.UserRepository;
import cn.reghao.oss.console.account.model.constant.RoleType;
import cn.reghao.oss.console.account.model.dto.CreateAccountDto;
import cn.reghao.oss.console.account.model.po.Role;
import cn.reghao.oss.console.account.service.AccountService;
import cn.reghao.oss.console.account.service.AccountSessionService;
import cn.reghao.jutil.jdk.result.Result;
import cn.reghao.jutil.jdk.security.RandomString;
import cn.reghao.oss.console.account.model.dto.AccountProfile;
import cn.reghao.oss.console.account.model.dto.AccountRole;
import cn.reghao.oss.console.account.model.po.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2020-06-19 16:36:53
 */
@Slf4j
@Service
public class AccountServiceImpl implements AccountService {
    private final UserRepository userRepository;
    private final RoleRepository roleRepository;
    private final PasswordEncoder passwordEncoder;
    private final AccountSessionService accountSessionService;

    public AccountServiceImpl(UserRepository userRepository, RoleRepository roleRepository,
                              PasswordEncoder passwordEncoder, AccountSessionService accountSessionService) {
        this.userRepository = userRepository;
        this.roleRepository = roleRepository;
        this.passwordEncoder = passwordEncoder;
        this.accountSessionService = accountSessionService;
    }

    @Override
    public void initAccount() {
        List<User> list = userRepository.findAll(PageRequest.of(0, 1)).getContent();
        if (list.isEmpty()) {
            String username = RandomString.getString(3).toLowerCase(Locale.ROOT);
            username = "admin";
            String password = RandomString.getString(10);

            Role role = roleRepository.findByName(RoleType.ROLE_ADMIN.name());
            if (role != null) {
                int roleId = role.getId();
                CreateAccountDto createAccountDto = new CreateAccountDto(username, password, roleId);
                createAccount(createAccountDto);
                log.info("初始化完成, 帐号和密码分别是 {} 和 {}", username, password);
            }
        }
    }

    @Override
    public Result createAccount(CreateAccountDto createAccountDto) {
        int roleId = createAccountDto.getRoleId();
        Role role = roleRepository.findById(roleId).orElse(null);
        if (role == null) {
            return Result.fail("role 不存在");
        }

        String username = createAccountDto.getUsername();
        User user = userRepository.findByUsername(username);
        if (user == null) {
            String password = createAccountDto.getPassword();
            String salt = RandomString.getSalt(64);
            String encodedPassword = passwordEncoder.encode(password + salt);

            user = new User(username, encodedPassword, salt, Set.of(role.getName()));
            userRepository.save(user);
            return Result.success();
        }

        String errMsg = String.format("帐号 %s 已存在", username);
        return Result.fail(errMsg);

    }

    @Override
    public void updateAccountPassword(Integer userId, String newPassword) {
        User userEntity = userRepository.findById(userId).orElse(null);
        if (userEntity == null) {
            return;
        }

        String salt = RandomString.getSalt(64);
        String encodedPassword = passwordEncoder.encode(newPassword + salt);
        userEntity.setSalt(salt);
        userEntity.setEncodedPassword(encodedPassword);
        userRepository.save(userEntity);
        accountSessionService.deactiveSession(userEntity);
    }

    @Override
    public void updateAccountProfile(AccountProfile accountProfile) {
        User userEntity = userRepository.findById(accountProfile.getUserId()).orElse(null);
        if (userEntity == null) {
            return;
        }

        userEntity.setScreenName(accountProfile.getScreenName());
        userEntity.setMobile(accountProfile.getMobile());
        userEntity.setEmail(accountProfile.getEmail());
        userRepository.save(userEntity);
    }

    @Override
    public void updateAccountRole(AccountRole accountRole) {
        int userId = accountRole.getUserId();
        User userEntity = userRepository.findById(userId).orElse(null);
        if (userEntity == null) {
            return;
        }

        Set<String> roles = accountRole.getRoles().stream().map(Role::getName).collect(Collectors.toSet());
        userEntity.setRole(roles);
        userRepository.save(userEntity);
        accountSessionService.deactiveSession(userEntity);
    }

    @Override
    public void updateAccountStatus(Integer userId, Boolean enable) {
        User userEntity = userRepository.findById(userId).orElse(null);
        if (userEntity == null) {
            return;
        }

        userEntity.setEnabled(enable);
        userRepository.save(userEntity);
    }

    @Override
    public void deleteAccount(Integer userId) {
        User userEntity = userRepository.findById(userId).orElse(null);
        if (userEntity == null) {
            return;
        }

        if (userEntity.getId() == 1) {
            log.error("不能删除管理员帐号");
        } else {
            userRepository.delete(userEntity);
        }
    }
}
