package org.jeecg.api.service.impl;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jeecg.api.bean.LoginReq;
import org.jeecg.api.service.AppletLoginService;
import org.jeecg.api.untils.HttpConf;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.hanHaiMember.entity.HanHaiMember;
import org.jeecg.modules.hanHaiMember.service.IHanHaiMemberService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author lzx
 * @Date 2022-05-13 15:55
 **/
@Slf4j
@Service
@SuppressWarnings("all")
public class AppletLoginServiceImpl implements AppletLoginService {

    @Value("${wechat-dm.mpAppId}")
    private String mpAppId;
    @Value("${wechat-dm.mpAppSecret}")
    private String mpAppSecret;

    @Resource
    private IHanHaiMemberService memberService;

    @Resource
    private RedisUtil redisUtil;
    @Resource
    private HttpConf httpConf;




    /**
     * 微信小程序登录接口
     * @param loginReq
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    public Result<Object> appletLogin(LoginReq loginReq) {

        //传入数据：
        log.info("小程序登录参数：{}", loginReq);
        //传入邀请者标识
        log.info("小程序邀请者标识：" + loginReq.getShareId());



        Result<Object> result = new Result<>();
        Map<String, Object> map = new HashMap<>();
        if (StringUtils.isBlank(loginReq.getCode())) {
            throw new JeecgBootException("小程序code为空");
        }
        String loginUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + mpAppId + "&secret=" + mpAppSecret+ "&js_code=" + loginReq.getCode() + "&grant_type=authorization_code";
        //使用工具类
        JSONObject json_test = httpConf.getJSONObject(loginUrl);
        String wxOpenid = json_test.getString("openid");
        String sessionKey = json_test.getString("session_key");
        if (StringUtils.isBlank(wxOpenid)) {
            throw new JeecgBootException("未获取到openid");
        }

        HanHaiMember member = memberService.lambdaQuery().eq(HanHaiMember::getAppletOpenid,wxOpenid).one();
        if (member == null) {
            //如果user等于null说明该用户第一次登录，数据库没有该用户信息。
            loginReq.setOpenid(wxOpenid);
            loginReq.setSession_key(sessionKey);
            member = new HanHaiMember();
            member.setSessionKey(sessionKey);
            member.setAppletOpenid(wxOpenid);
            member.setNickName("农闲宝"+System.currentTimeMillis());
            member.setHeadImage(null);
            member.setShareId(loginReq.getShareId());
            member.setVtime(new Date());
            // 生成token返回给小程序端
            String token = JwtUtil.sign(member.getAppletOpenid(), wxOpenid);
            memberService.save(member);
            redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
            // 设置超时时间
            redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 100);
            map.put("userInfo", member);
            map.put("token", token);

            result.setCode(200);
            result.setResult(map);
            return result;
        } else {
//            member.setHeadImage(loginReq.getHeadimgurl());
//            member.setSessionKey(sessionKey);
//            memberService.saveOrUpdate(member);
            // 生成token返回给小程序端
            String token = JwtUtil.sign(member.getAppletOpenid(), wxOpenid);
            redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
            // 设置超时时间
            redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 100);
            map.put("userInfo", member);
            map.put("token", token);
            //用户id做im账号
            result.setResult(map);
            result.setCode(200);
//            result.setMessage(member.getNickName()+"已于"+member.getCreateTime()+"注册成功！请勿重复注册！");
            // 未绑定手机号，跳转授权绑定手机号
//            if (StringUtils.isBlank(member.getPhone())) {
//                result.setMessage("用户未绑定手机号码！需绑定手机号码");
//                result.setCode(905);
//                result.setResult(map);
//                return result;
//            }
        }
        return result;
    }






    //    private static final String APP_ID = mpAppId; // 替换为你的小程序AppID
//    private static final String APP_SECRET = "YOUR_APP_SECRET"; // 替换为你的小程序AppSecret
    private static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";

    public  String getAccessToken() throws Exception {
        String requestUrl = String.format(TOKEN_URL, mpAppId, mpAppSecret);
        URL url = new URL(requestUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");

        try (BufferedReader br = new BufferedReader(
                new InputStreamReader(conn.getInputStream(), "UTF-8"))) {
            StringBuilder response = new StringBuilder();
            String responseLine;
            while ((responseLine = br.readLine()) != null) {
                response.append(responseLine.trim());
            }

            org.json.JSONObject jsonResponse = new org.json.JSONObject(response.toString());
            return jsonResponse.getString("access_token");
        }
    }

    private static final String API_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber";

    public String getPhoneNumber(String code) throws Exception {
        URL url = new URL(API_URL + "?access_token=" + this.getAccessToken());
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json; utf-8");
        conn.setRequestProperty("Accept", "application/json");
        conn.setDoOutput(true);

        JSONObject jsonInput = new JSONObject();
        jsonInput.put("code", code);

        try (DataOutputStream os = new DataOutputStream(conn.getOutputStream())) {
            byte[] input = jsonInput.toString().getBytes(StandardCharsets.UTF_8);
            os.write(input, 0, input.length);
        }

        try (BufferedReader br = new BufferedReader(
                new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
            StringBuilder response = new StringBuilder();
            String responseLine;
            while ((responseLine = br.readLine()) != null) {
                response.append(responseLine.trim());
            }
            //获取手机号码
            return response.toString();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<Object> bindPhone(String code) {
        try {
            String phoneNumber = this.getPhoneNumber(code);
            return Result.OK(phoneNumber);
        }catch (Exception e){
            return Result.error(e.getMessage());
        }
    }

//    /**
//     * 微信小程序登录绑定手机号码接口
//     * @param loginReq
//     * @return
//     */
//    @Transactional(rollbackFor = Exception.class)
//    @Override
//    public Result<Object> bindPhone(LoginReq loginReq) {
//        Result<Object> result = new Result<>();
//        if (StringUtils.isEmpty(loginReq.getEncryptedData())) {
//            result.setCode(500);
//            result.setMessage("请授权手机号");
//            return result;
//        }
//        if(one==null){
//            return Result.error("未获取到openid");
//        }
//        return Result.OK("获取成功",userPhone);

    }



    /**
     * 解析电话号码
     * @param loginReq
     * @return
     */
    public String getPhoneNumber(LoginReq loginReq) {
        String encryptedData = loginReq.getEncryptedData();
        String session_key = loginReq.getSession_key();
        String iv = loginReq.getIv();
        // 被加密的数据
        byte[] dataByte = Base64.decodeBase64(encryptedData);
        // 加密秘钥
        byte[] keyByte = Base64.decodeBase64(session_key);
        // 偏移量
        byte[] ivByte = Base64.decodeBase64(iv);
        try {
            // 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, "UTF-8");
                JSONObject userPhoneObj = JSONObject.parseObject(result);
                Map<String, Object> userMap = new HashMap<>();
                for (Map.Entry<String, Object> entry : userPhoneObj.entrySet()) {
                    userMap.put(entry.getKey(), entry.getValue());
                }
                // 获取phoneNumber 带区号
                String userPhone = (String) userMap.get("phoneNumber");
                return userPhone;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
