package com.zhongzheng.framework.web.service;


import cn.hutool.core.lang.Validator;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zhongzheng.common.constant.Constants;
import com.zhongzheng.common.exception.CustomException;

import com.zhongzheng.common.utils.*;
import com.zhongzheng.common.utils.http.HttpUtils;
import com.zhongzheng.common.utils.ip.IpUtils;
import com.zhongzheng.modules.course.mapper.CourseSectionMapper;
import com.zhongzheng.modules.user.bo.UserAddBo;
import com.zhongzheng.modules.user.domain.User;
import com.zhongzheng.modules.user.domain.UserBankRecord;
import com.zhongzheng.modules.user.domain.UserSchoolInfo;
import com.zhongzheng.modules.user.entity.ClientLoginUser;
import com.zhongzheng.modules.user.mapper.UserMapper;
import com.zhongzheng.modules.user.mapper.UserSchoolInfoMapper;
import com.zhongzheng.modules.user.service.IUserService;
import com.zhongzheng.modules.user.vo.UserVo;
import com.zhongzheng.modules.wx.bo.WxLoginBody;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * 登录校验方法
 *
 * @author zhongzheng
 */
@Component
public class WxLoginService
{
    @Autowired
    private WxTokenService wxTokenService;

    @Value("${wx.small.appid}")
    private String appid;

    @Value("${wx.small.appsecret}")
    private String appsrcret;


    private String wxAuthUrl = "https://api.weixin.qq.com/sns/jscode2session";

    private String wxAuthParam = "appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";

    @Value("${wx.gzh.appid}")
    private String gzh_appid;

    @Value("${wx.gzh.appsecret}")
    private String gzh_appsrcret;

    private String gzh_wxAuthUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";

    private String gzh_wxAuthParam = "appid=%s&secret=%s&code=%s&grant_type=authorization_code";

    private String gzh_wxUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo";

    private String gzh_wxUserInfoParam = "access_token=%s&openid=%s&lang=zh_CN";

    @Autowired
    private IUserService iUserService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserSchoolInfoMapper userSchoolInfoMapper;

    public Map<String,String> test_login() {
        String unionId = "oQ2yp56PgQ-PfwN4vxTZhR5eTpzk";
        User user = iUserService.queryByUnionId(unionId);
        ClientLoginUser loginUser = new ClientLoginUser();
        loginUser.setUser(user);

        Map<String,String> map = new HashMap<>();
        map.put(Constants.TOKEN,wxTokenService.createToken(loginUser));
        map.put("union_id",loginUser.getUser().getUnionId());
        return map;
    }

    @Transactional(rollbackFor = Exception.class)
    public Map<String,String> login(WxLoginBody loginBody) {
        User user = getWxUnionIdUser(loginBody);
        if(user==null){
            throw new CustomException("登录错误");
        }
        ClientLoginUser loginUser = new ClientLoginUser();
        loginUser.setUser(user);
        Map<String,String> map = new HashMap<>();
        map.put(Constants.TOKEN,wxTokenService.createToken(loginUser));
        map.put("union_id",loginUser.getUser().getUnionId());
        return map;
    }

    public Map<String,String> gzh_login(WxLoginBody loginBody) {
        User user = getWxGzhUnionIdUser(loginBody);
        if(user==null){
            throw new CustomException("登录错误");
        }
        ClientLoginUser loginUser = new ClientLoginUser();
        loginUser.setUser(user);
        Map<String,String> map = new HashMap<>();
        map.put(Constants.TOKEN,wxTokenService.createToken(loginUser));
        map.put("union_id",loginUser.getUser().getUnionId());
        return map;
    }

    public String refreshToken(String userAccount) {
        User user = iUserService.queryByAccount(userAccount);
        if(user==null){
            throw new CustomException("userAccount不存在");
        }
        user.setLastLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
        user.setLastLoginTime(DateUtils.getNowTime());
        userMapper.updateById(user);
        ClientLoginUser loginUser = new ClientLoginUser();
        loginUser.setUser(user);
        return wxTokenService.createToken(loginUser);
    }

    /**
     * 小程序注册
     * @param openId
     * @param unionId
     * @param tel
     * @return
     */
    public Boolean register_small(String openId,String unionId,String tel,String inviteCode) {
        User bo = new User();
        bo.setOpenId(openId);
        bo.setUnionId(unionId);
        bo.setTelphone(tel);
        //隐藏手机号作为初始昵称
        bo.setNickname(TelPhoneUtils.hideTelPhone(tel));
        //雪花算法产生账号ID
        SnowflakeIdUtils idWorker = new SnowflakeIdUtils(3, 1);
        bo.setUserAccount(String.valueOf(idWorker.nextId()));
        bo.setSex(1);
        bo.setStatus(1);
        bo.setRegisterPlat("1");
        bo.setAvatar(Constants.DEFAULT_AVATAR);
        bo.setLastLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
        bo.setLastLoginTime(DateUtils.getNowTime());
        bo.setCreateTime(DateUtils.getNowTime());
        bo.setUpdateTime(DateUtils.getNowTime());
        bo.setStudentCode(ServletUtils.getEncoded("XY"));
        if(inviteCode!=null){
            User inviteUser = iUserService.queryByAccount(inviteCode);
            if(inviteUser!=null){
                bo.setInviteUserAccount(inviteCode);
            }
        }
        if(iUserService.save(bo)){
            UserSchoolInfo schoolInfo = new UserSchoolInfo();
            schoolInfo.setUserId(bo.getUserId());
            schoolInfo.setCreateTime(DateUtils.getNowTime());
            schoolInfo.setUpdateTime(DateUtils.getNowTime());
            userSchoolInfoMapper.insert(schoolInfo);
        }
        return true;
    }
    //小程序获取用户openid
    public String getWxOpenId(WxLoginBody loginBody,Long userId) {
        LambdaQueryWrapper<User> lqw = Wrappers.lambdaQuery();
        lqw.eq(User::getUserId, userId);
        User user = iUserService.getOne(lqw);
        String openId = user.getOpenId();
        if(Validator.isEmpty(openId)){
            String param = String.format(wxAuthParam, appid, appsrcret, loginBody.getCode());
            String resultString  = HttpUtils.sendGet(wxAuthUrl,param);
            //解析json
            JSONObject jsonObject = (JSONObject) JSONObject.parse(resultString);
            String session_key = String.valueOf(jsonObject.get("session_key"));
            openId = String.valueOf(jsonObject.get("openid"));
            user.setOpenId(openId);
            iUserService.updateById(user);
        }
        return openId;
    }


    //小程序获取用户信息
    public User getWxUnionIdUser(WxLoginBody loginBody) {
        String param = String.format(wxAuthParam, appid, appsrcret, loginBody.getCode());
        String resultString  = HttpUtils.sendGet(wxAuthUrl,param);
        //解析json
        JSONObject jsonObject = (JSONObject) JSONObject.parse(resultString);
        String session_key = String.valueOf(jsonObject.get("session_key"));
        String openId = String.valueOf(jsonObject.get("openid"));
        String unionId = String.valueOf(jsonObject.get("unionid"));
        String phoneNumber = obtainWxPhone(loginBody.getIv(),loginBody.getEncryptedData(),session_key);
        User user = iUserService.queryByUnionId(unionId);
        if(user==null){
            if(!register_small(openId,unionId,phoneNumber,loginBody.getInviteCode())){
                throw new CustomException("注册失败");
            }
            user = iUserService.queryByUnionId(unionId);
        }
        return user;
    }

    //公众号获取用户信息
    public User getWxGzhUnionIdUser(WxLoginBody loginBody) {
        String param = String.format(gzh_wxAuthParam, gzh_appid, gzh_appsrcret, loginBody.getCode());
        String resultString  = HttpUtils.sendGet(gzh_wxAuthUrl,param);
        //解析json
        JSONObject jsonObject = (JSONObject) JSONObject.parse(resultString);
        String access_token = String.valueOf(jsonObject.get("access_token"));
        String openId = String.valueOf(jsonObject.get("openid"));

        String userInfoParam = String.format(gzh_wxUserInfoParam, access_token, openId);
        String userInfoResultString  = HttpUtils.sendGet(gzh_wxUserInfoUrl,userInfoParam);
        //解析json
        JSONObject jsonObject1 = (JSONObject) JSONObject.parse(userInfoResultString);
        String unionId = String.valueOf(jsonObject1.get("unionid"));
        User user = iUserService.queryByUnionId(unionId);
        if(user==null){
            throw new CustomException("您尚未注册，请前往小程序注册");
        }
        if(!Validator.isNotNull(user.getGzhOpenId())){
            user.setGzhOpenId(openId);
            iUserService.updateById(user);
        }
        return user;
    }

    public String obtainWxPhone(String iv, String encryptedData,String session_key){
        String userInfo = null;
        JSONObject userInfoJSON = null;
        try {
            byte[] resultByte = AES.decrypt(Base64.decodeBase64(encryptedData),
                    Base64.decodeBase64(session_key),
                    Base64.decodeBase64(iv));

            userInfo = new String(resultByte, "UTF-8");
            userInfoJSON = JSON.parseObject(userInfo);
            return String.valueOf(userInfoJSON.get("phoneNumber"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
