package com.izouma.immall.service;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import com.izouma.immall.config.Constants;
import com.izouma.immall.domain.User;
import com.izouma.immall.exception.BusinessException;
import com.izouma.immall.repo.UserRepo;
import com.izouma.immall.service.sms.SmsService;
import com.izouma.immall.service.storage.StorageService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Slf4j
@AllArgsConstructor
public class UserService {
    private UserRepo userRepo;
    private WxMaService wxMaService;
    private WxMpService wxMpService;
    private SmsService smsService;
    private StorageService storageService;

    public User loginByPhone(String phone) {
        return userRepo.findByPhone(phone);
    }

    public User loginMp(String code) throws WxErrorException {
        WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
        WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(accessToken, null);
        User user = userRepo.findByOpenId(wxMpUser.getOpenId());
        if (user == null) {
            user = User.builder()
                    .username(UUID.randomUUID().toString())
                    .nickname(wxMpUser.getNickname())
                    .avatar(wxMpUser.getHeadImgUrl())
                    .sex(wxMpUser.getSexDesc())
                    .country(wxMpUser.getCountry())
                    .province(wxMpUser.getProvince())
                    .city(wxMpUser.getCity())
                    .openId(wxMpUser.getOpenId())
                    .language(wxMpUser.getLanguage())
                    .enabled(true)
//                       .invitationCode(invitation())
                    .money(BigDecimal.ZERO)
//                       .authorities(Collections.singleton(VipAuthority.builder().name("NO_VIP").build()))
                    .build();
            userRepo.save(user);
        }
        return user;
    }

    public User loginMa(String code) {
        try {
            WxMaJscode2SessionResult result = wxMaService.jsCode2SessionInfo(code);
            String openId = result.getOpenid();
            String sessionKey = result.getSessionKey();
            User userInfo = userRepo.findByOpenId(openId);
            if (userInfo != null) {
                return userInfo;
            }
            userInfo = User.builder()
                    .username(UUID.randomUUID().toString())
                    .nickname("用户" + RandomStringUtils.randomAlphabetic(6))
                    .openId(openId)
                    .avatar(Constants.DEFAULT_AVATAR)
                    .enabled(true)
//                           .invitationCode(invitation())
                    .money(BigDecimal.ZERO)
//                           .authorities(Collections.singleton(VipAuthority.builder().name("NO_VIP").build()))
                    .build();
            userInfo = userRepo.save(userInfo);
            return userInfo;
        } catch (WxErrorException e) {
            e.printStackTrace();
        }
        throw new BusinessException("登录失败");
    }

    public User getMaUserInfo(String sessionKey, String rawData, String signature,
                              String encryptedData, String iv) {
        // 用户信息校验
        if (!wxMaService.getUserService().checkUserInfo(sessionKey, rawData, signature)) {
            throw new BusinessException("获取用户信息失败");
        }

        // 解密用户信息
        WxMaUserInfo wxUserInfo = wxMaService.getUserService().getUserInfo(sessionKey, encryptedData, iv);
        User user = userRepo.findByOpenId(wxUserInfo.getOpenId());
        WxMaPhoneNumberInfo phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);
        String phone = phoneNoInfo.getPhoneNumber();

        String avatarUrl = Constants.DEFAULT_AVATAR;

        try {
            String path = "image/avatar/" +
                    new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) +
                    RandomStringUtils.randomAlphabetic(8) +
                    ".jpg";
            avatarUrl = storageService.uploadFromUrl(wxUserInfo.getAvatarUrl(), path);
        } catch (Exception e) {
            log.error("获取头像失败", e);
        }

        if (user == null) {

            user = User.builder()
                    .username(UUID.randomUUID().toString())
                    .nickname(wxUserInfo.getNickName())
                    .openId(wxUserInfo.getOpenId())
                    .avatar(avatarUrl)
                    .sex(wxUserInfo.getGender())
                    .country(wxUserInfo.getCountry())
                    .province(wxUserInfo.getProvince())
                    .city(wxUserInfo.getCity())
                    .enabled(true)
                    .money(BigDecimal.ZERO)
//                       .invitationCode(invitation())
                    .phone(phone)
//                       .authorities(Collections.singleton(VipAuthority.builder().name("NO_VIP").build()))
                    .build();
            user = userRepo.save(user);

        } else {
            user.setAvatar(avatarUrl);
            user.setNickname(wxUserInfo.getNickName());
            user.setSex(wxUserInfo.getGender());
            user.setCountry(wxUserInfo.getCountry());
            user.setProvince(wxUserInfo.getProvince());
            user.setCity(wxUserInfo.getCity());
            user.setPhone(phone);
            user = userRepo.save(user);
        }

        return user;
    }

/*    @PostConstruct
    public void init() {
        User root = userRepo.findByUsername("root");
        if (root == null) {
            Set<Authority> authorities = new HashSet<>();
            authorities.add(new Authority(Authority.NAMES.ROLE_ADMIN.name()));
            authorities.add(new Authority(Authority.NAMES.ROLE_USER.name()));
            root = User.builder()
                       .nickname("管理员")
                       .username("root")
                       .password(new BCryptPasswordEncoder().encode("123456"))
                       .avatar(Constants.DEFAULT_AVATAR)
                       .enabled(true)
                       .authorities(authorities)
                       .build();
            userRepo.save(root);
        }
    }*/

    /*
    查看邀请码是否已存在
     */
/*    private Integer invitation(){
        Integer invitationCode =(int) ((Math.random() * 9 + 1) * Math.pow(10, 8 - 1));
        while(userRepo.existsByInvitationCode(invitationCode)){
            invitationCode =(int) ((Math.random() * 9 + 1) * Math.pow(10, 8 - 1));
        }
        return invitationCode;
    }*/

}
