package com.liquidnet.service.sweet.service.impl;

import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.adam.dto.vo.AdamUserInfoVo;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.feign.adam.api.FeignAdamBaseClient;
import com.liquidnet.service.feign.stone.api.FeignStoneIntegralClient;
import com.liquidnet.service.sweet.dto.vo.WechatTokenInfoVo;
import com.liquidnet.service.sweet.dto.vo.WechatUserInfoVo;
import com.liquidnet.service.sweet.utils.QueueUtils;
import com.liquidnet.service.sweet.utils.WechatUsersRedisUtils;
import com.liquidnet.service.sweet.vo.SweetWechatUsersRelationVo;
import com.liquidnet.service.sweet.vo.SweetWechatUsersVo;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Objects;

/**
 * <p>
 * 小程序登陆 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2021-07-27
 */
@Slf4j
@Service
public class SweetWechatLoginServiceImpl {

    @Autowired
    private SweetWechatService sweetWechatService;

    @Autowired
    QueueUtils queueUtils;

    @Autowired
    private WechatUsersRedisUtils redisUtils;

    @Autowired
    private FeignAdamBaseClient feignAdamBaseClient;
    @Autowired
    private FeignStoneIntegralClient feignStoneIntegralClient;

    public ResponseDto userInfo(String code, String encryptedData, String iv, Integer type) {
        log.info("小程序解密用户信息参数：[code=[{}], encryptedData=[{}], [iv=[{}], type=[{}]", code, encryptedData, iv, type);
        try {
            // 获取unid openid
            WxMaJscode2SessionResult sessionInfo = sweetWechatService.sessionInfo(code, type);
            if (null == sessionInfo) {
                return ResponseDto.failure("login handler error");
            }
            String unionId = sessionInfo.getUnionid();
            String openId = sessionInfo.getOpenid();
            // 解密手机号码信息
            WxMaPhoneNumberInfo wxMaPhoneNumberInfo = sweetWechatService.phoneNumberInfo(sessionInfo.getSessionKey(), encryptedData, iv, type);
            if (Objects.isNull(wxMaPhoneNumberInfo) || StringUtils.isBlank(wxMaPhoneNumberInfo.getPhoneNumber())) {
                return ResponseDto.failure("解密手机信息失败");
            }
            String wechatId = IDGenerator.nextSnowId();
            String phoneNumber = wxMaPhoneNumberInfo.getPhoneNumber();
            String purePhoneNumber = wxMaPhoneNumberInfo.getPurePhoneNumber();
            String countryCode = wxMaPhoneNumberInfo.getCountryCode();
            Integer userType = type + 20;
            // 获取adam用户信息 自动注册
            ResponseDto<AdamUserInfoVo> userInfoVo = feignAdamBaseClient.registerByMobile(wxMaPhoneNumberInfo.getPurePhoneNumber());
            AdamUserInfoVo userInfoVoData = userInfoVo.getData();
            String mobile = userInfoVoData.getMobile();
            String userId = userInfoVoData.getUid();
            // mysql redis
            SweetWechatUsersVo sweetWechatUsers = redisUtils.getSweetWechatUsers(unionId, userType);
            if (null == sweetWechatUsers) {
                LinkedList<String> sqlsA = CollectionUtil.linkedListString();
                LinkedList<Object[]> sqlsDataA = CollectionUtil.linkedListObjectArr();
                sqlsA.add(SqlMapping.get("sweet_wechat_users_applet.insert"));
                sqlsDataA.add(new Object[]{
                        wechatId, openId, unionId, phoneNumber, purePhoneNumber, countryCode, userType
                });
                queueUtils.sendMsgByRedis(MQConst.SweetQueue.SWEET_WECHAT_USER_INSERT.getKey(),
                        SqlMapping.gets(sqlsA, sqlsDataA));
                SweetWechatUsersVo sweetWechatUsersVo = SweetWechatUsersVo.getNew();
                sweetWechatUsersVo.setWechatId(wechatId);
                sweetWechatUsersVo.setPhoneNumber(phoneNumber);
                sweetWechatUsersVo.setPurePhoneNumber(purePhoneNumber);
                sweetWechatUsersVo.setCountryCode(countryCode);
                sweetWechatUsersVo.setType(userType);
                redisUtils.setSweetWechatUsers(sweetWechatUsersVo);
            }
            SweetWechatUsersRelationVo sweetWechatUsersRelation = redisUtils.getSweetWechatUsersRelation(mobile);
            if (null == sweetWechatUsersRelation) {
                LinkedList<String> sqlsB = CollectionUtil.linkedListString();
                LinkedList<Object[]> sqlsDataB = CollectionUtil.linkedListObjectArr();
                sqlsB.add(SqlMapping.get("sweet_wechat_users_relation.insert"));
                String wechatRelationId = IDGenerator.nextSnowId();
                sqlsDataB.add(new Object[]{
                        wechatRelationId, unionId, userId, mobile
                });
                queueUtils.sendMsgByRedis(MQConst.SweetQueue.SWEET_WECHAT_USER_INSERT.getKey(),
                        SqlMapping.gets(sqlsB, sqlsDataB));
                SweetWechatUsersRelationVo usersRelationVo = SweetWechatUsersRelationVo.getNew();
                usersRelationVo.setWechatRelationId(wechatRelationId);
                usersRelationVo.setUnionId(unionId);
                usersRelationVo.setUserId(userId);
                usersRelationVo.setUserPhone(mobile);
                redisUtils.setSweetWechatUsersRelation(usersRelationVo);
                // 调用关注赠积分任务 这里如果不调用的话
                // 1。关注过了也登陆过小程序的可以脚本处理 脚本不处理就需要每个用户点进入小程序登陆
                // 2。关注过了 无小程序的 本次登陆才有的 接口也不是前端请求的 就没有地方触发做任务接口
                // 3。有小程序未关注的就关注时候适用
                SweetWechatUsersVo sweetWechatUsersSky = redisUtils.getSweetWechatUsers(unionId, 2);
                if (null != sweetWechatUsersSky) {
                    feignStoneIntegralClient.doTask(4, userId);
                }
            }
            // 返回给前端数据
            HashMap<String, Object> userInfo = CollectionUtil.mapStringObject();
            userInfo.put("unionId", unionId);
            userInfo.put("openId", openId);
            userInfo.put("getPhoneNumber", wxMaPhoneNumberInfo.getPhoneNumber());
            userInfo.put("getPurePhoneNumber", wxMaPhoneNumberInfo.getPurePhoneNumber());
            userInfo.put("getCountryCode", wxMaPhoneNumberInfo.getCountryCode());
            return ResponseDto.success(userInfo);
        } catch (Exception e) {
            log.error("WechatUserInfoError Exception:{}", e);
            return ResponseDto.failure();
        }
    }

    public ResponseDto<String> wxaCode2Session(String jsCode, Integer type) {
        try {
            WxMaJscode2SessionResult wxMaJscode2SessionResult = sweetWechatService.sessionInfo(jsCode, type);
            return ResponseDto.success(wxMaJscode2SessionResult.getOpenid());
        } catch (Exception e) {
            log.error("wxaCode2SessionError Exception:{}", e);
            return ResponseDto.failure();
        }
    }

    public ResponseDto<String> wxOauth2AccessToken(String code, Integer type) {
        try {
            WxOAuth2AccessToken wxOAuth2AccessToken = sweetWechatService.wxOauth2AccessToken(code, type);
            return ResponseDto.success(wxOAuth2AccessToken.getOpenId());
        } catch (Exception e) {
            log.error("wxaCode2SessionError Exception:{}", e);
            return ResponseDto.failure();
        }
    }

    public ResponseDto<WechatTokenInfoVo> mpWxOauth2AccessTokenInfo(String code, Integer type) {
        try {
            WxOAuth2AccessToken wxOAuth2AccessToken = sweetWechatService.wxOauth2AccessToken(code, type);
            WechatTokenInfoVo userInfoVo = WechatTokenInfoVo.getNew().copy(wxOAuth2AccessToken);
            return ResponseDto.success(userInfoVo);
        } catch (Exception e) {
            log.error("wxaCode2SessionError Exception:{}", e);
            return ResponseDto.failure();
        }
    }

    public ResponseDto<WechatUserInfoVo> mpUserInfo(String code, Integer type) {
        try {
            WxOAuth2UserInfo wxOAuth2UserInfo = sweetWechatService.mpUserInfo(code, type);
            WechatUserInfoVo tokenInfoVo = WechatUserInfoVo.getNew().copy(wxOAuth2UserInfo);
            return ResponseDto.success(tokenInfoVo);
        } catch (Exception e) {
            log.error("wxaCode2SessionError Exception:{}", e);
            return ResponseDto.failure();
        }
    }

}
