package cn.reghao.tnb.auth.app.rpc;

import cn.reghao.jutil.jdk.string.IDObfuscation;
import cn.reghao.tnb.auth.api.dto.AccountAvatar;
import cn.reghao.tnb.auth.api.dto.AccountInfo;
import cn.reghao.tnb.auth.api.dto.AuthedAccount;
import cn.reghao.tnb.auth.api.dto.CrawledUser;
import cn.reghao.tnb.auth.api.iface.AccountQuery;
import cn.reghao.tnb.auth.app.db.repository.AccountRepository;
import cn.reghao.tnb.auth.app.model.po.UserAccount;
import cn.reghao.tnb.auth.app.security.form.AccountAuthToken;
import cn.reghao.tnb.auth.app.service.AccountTokenService;
import cn.reghao.tnb.common.util.ConstantId;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;

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

/**
 * @author reghao
 * @date 2021-11-12 17:32:01
 */
@DubboService
@Service
public class AccountQueryImpl implements AccountQuery {
    private final int pageSize = 100;
    private final AccountRepository accountRepository;
    private final AccountTokenService accountTokenService;
    private final IDObfuscation userIdObfuscation;

    public AccountQueryImpl(AccountRepository accountRepository, AccountTokenService accountTokenService,
                            IDObfuscation userIdObfuscation) {
        this.accountRepository = accountRepository;
        this.accountTokenService = accountTokenService;
        this.userIdObfuscation = userIdObfuscation;
    }

    @Override
    public AuthedAccount getAuthedAccount(int type, String sessId) {
        AccountAuthToken accountAuthToken = accountTokenService.getAuthToken(type, sessId);
        if (accountAuthToken != null) {
            String loginId = accountAuthToken.getLoginId();
            long userId = accountAuthToken.getUserId();
            String userIdStr = userIdObfuscation.obfuscate(userId);
            Set<String> roles = accountAuthToken.getAuthorities().stream()
                    .map(GrantedAuthority::getAuthority)
                    .collect(Collectors.toSet());
            return new AuthedAccount(loginId, userId, userIdStr, roles);
        }

        return null;
    }

    @Override
    public AccountInfo getAccountInfo(long userId) {
        AccountInfo accountInfo = accountRepository.getAccountInfo(userId);
        if (accountInfo != null) {
            String mobile = accountInfo.getMobile();
            if (mobile != null) {
                String mobile1 = new StringBuilder(mobile).replace(3, 7, "****").toString();
                accountInfo.setMobile(mobile1);
            }
        }

        return accountInfo;
    }

    @Override
    public AccountAvatar getAccountAvatar(long userId) {
        String userIdStr = userIdObfuscation.obfuscate(userId);
        AccountInfo accountInfo = accountRepository.getAccountInfo(userId);
        return accountInfo != null ? new AccountAvatar(userIdStr, accountInfo) : null;
    }

    @Override
    public List<AccountInfo> getAccountInfos(List<Long> userIds) {
        return accountRepository.getAccountInfos(userIds);
/*        return userIds.stream()
                .map(accountRepository::getAccountInfo)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());*/
    }

    @Override
    public AccountInfo getByMobile(String mobile) {
        return accountRepository.getAccountInfoByMobile(mobile);
    }

    @Override
    public AccountInfo getByUsername(String username) {
        return accountRepository.getAccountInfoByUsername(username);
    }

    @Override
    public long getByRole(String role) {
        List<Long> userIds = accountRepository.getRoleUsers(role);
        return userIds.isEmpty() ? ConstantId.ANONYMOUS_USER_ID : userIds.get(0);
    }

    @Override
    public Long createCrawledAccount(CrawledUser crawledUser) {
        String screenName = crawledUser.getScreenName();
        String username = crawledUser.getUsername();
        String avatarUrl = crawledUser.getAvatarUrl();
        AccountInfo accountInfo = getByUsername(username);
        Long userId = accountInfo != null ? accountInfo.getUserId() : null;
        if (userId != null) {
            return userId;
        } else {
            userId = accountRepository.getNextUserId();
        }

        String email = String.format("%s@tnb.cn", userId);
        String mobile = String.format("190%s", userId);
        UserAccount userAccount = new UserAccount(mobile, userId, username, screenName, avatarUrl);
        accountRepository.saveAccount(userAccount);
        return userId;
    }

    @Override
    public void updateAvatar(long userId, String avatarUrl) {
        accountRepository.updateUserAvatar(userId, avatarUrl);
    }

    @Override
    public String getUserIdStr(long userIdLong) {
        return userIdObfuscation.obfuscate(userIdLong);
    }

    @Override
    public long getUserIdLong(String userIdStr) {
        return userIdObfuscation.restore(userIdStr);
    }
}
