package com.aiup.service.service.impl;

import com.aiup.service.domain.WxCodeSessionResult;
import com.aiup.service.domain.exception.CommonException;
import com.aiup.service.domain.query.UpdateUserInfoQuery;
import com.aiup.service.domain.query.WeChatGetMobileQuery;
import com.aiup.service.domain.query.WeChatLoginQuery;
import com.aiup.service.domain.response.WeChatSessionKeyResponse;
import com.aiup.service.entity.UserInfo;
import com.aiup.service.service.UserInfoService;
import com.aiup.service.service.WeChatLoginService;
import com.aiup.service.utils.LoginUserUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import sun.misc.BASE64Decoder;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class WeChatLoginServiceImpl implements WeChatLoginService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private UserInfoService userInfoService;

    @Value("${wechat.code2session.url}")
    private String url ;
    @Value("${wechat.appId}")
    private String appId;
    @Value("${wechat.secret}")
    private String secret;

    /**
     * 根据code获取openId
     *
     * @param code
     * @return
     */
    @Override
    public WxCodeSessionResult getOpenIdByCode(String code) {
        String result = getWxOpenId(code);
        WxCodeSessionResult forObject = JSON.parseObject(result,WxCodeSessionResult.class);
        //WxCodeSessionResult forObject = new WxCodeSessionResult();
        //forObject.setErrcode(0);
        //forObject.setOpenid("openid_temp");
        return forObject;
    }

    /**
     * 获取手机号第一步
     *
     * @param query
     * @return
     */
    @Override
    public WeChatSessionKeyResponse getSessionKey(WeChatLoginQuery query) {
        String result = getWxOpenId(query.getCode());
        JSONObject object = JSON.parseObject(result);
        if(object.getInteger("errcode")==0){
            WeChatSessionKeyResponse response = new WeChatSessionKeyResponse();
            response.setOpenId(object.getString("openid"));
            response.setSessionKey(object.getString("session_key"));
            return response;
        }
        else {
            throw  new CommonException("授权失败",object.getInteger("errcode"));
        }
    }

    /**
     * 解密用户信息
     *
     * @param query
     * @return
     */
    @Override
    public UserInfo deCodeWxUserInfo(WeChatGetMobileQuery query) {
        UserInfo user = userInfoService.queryById(query.getUserId());
        String sSrc=query.getEncryptedData();
        String encodingFormat="utf-8";
        String sKey=query.getSessionKey();
        String ivParameter=query.getIv();
        try {
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] raw = decoder.decodeBuffer(sKey);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            IvParameterSpec iv = new IvParameterSpec(decoder.decodeBuffer(ivParameter));
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] myendicod = decoder.decodeBuffer(sSrc);
            byte[] original = cipher.doFinal(myendicod);
            System.out.println(new String(original, encodingFormat));
            String str = new String(original, encodingFormat);
            /**
             * {
             *   "nickName": "Band",
             *   "gender": 1,
             *   "language": "zh_CN",
             *   "city": "Guangzhou",
             *   "province": "Guangdong",
             *   "country": "CN",
             *   "avatarUrl": "http://wx.qlogo.cn/mmopen/vi_32/1vZvI39NWFQ9XM4LtQpFrQJ1xlgZxx3w7bQxKARol6503Iuswjjn6nIGBiaycAjAtpujxyzYsrztuuICqIM5ibXQ/0"
             * }
             */
            JSONObject userObj = JSON.parseObject(str);
            if(user == null)
            {
                user = new UserInfo();
            }
            user.setNickName(userObj.getString("nickName"));
            user.setGender(userObj.getInteger("gender"));
            user.setAvatarUrl(userObj.getString("avatarUrl"));
            user.setCountry(userObj.getString("country"));
            user.setProvince(userObj.getString("province"));
            user.setCity(userObj.getString("city"));
            user.setIsAuth(1);
            if(user.getUserId() == null || user.getUserId() <=0){
                user = userInfoService.insert(user);
            }
            else {
                user = userInfoService.update(user);
            }
            LoginUserUtils.setLoginUser(user);
            return  user;

        } catch (Exception ex) {
            throw new CommonException("授权信息解密失败");
        }
    }

    /**
     * 更新用户信息
     *
     * @param query
     * @return
     */
    @Override
    public UserInfo updateUserInfo(UpdateUserInfoQuery query) {
        UserInfo user = userInfoService.queryById(query.getUserId());
        if(user == null){
            throw new CommonException("用户不存在");
        }
        user.setNickName(query.getNickName());
        user.setAvatarUrl(query.getAvatarUrl());
        user.setGender(query.getGender());
        user.setCity(query.getCity());
        user.setProvince(query.getProvince());
        user.setCountry(query.getCountry());
        user.setUpdateTime(new Date());
        user = userInfoService.update(user);
        LoginUserUtils.setLoginUser(user);
        return user;
    }

    private String getWxOpenId(String code){
        Map<String,Object> param = new HashMap<>();
        param.put("appid",appId);
        param.put("secret",secret);
        param.put("js_code",code);
        param.put("grant_type","authorization_code");
        String loginUrl = url+"?appid={appid}&secret={secret}&js_code={js_code}&grant_type={grant_type}";
        //GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
        String result = restTemplate.getForObject(loginUrl, String.class, param);;
        return result;
    }
}
