package com.mmc.iuav.user.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.github.wxpay.sdk.WXPayUtil;
import com.mmc.iuav.http.HttpHelper;
import com.mmc.iuav.http.HttpsRequestUtil;
import com.mmc.iuav.response.ResultBody;
import com.mmc.iuav.response.ResultEnum;
import com.mmc.iuav.user.constant.UserSystemConstant;
import com.mmc.iuav.user.constant.WxConstant;
import com.mmc.iuav.user.dao.UserSubInfoDao;
import com.mmc.iuav.user.entity.UserSubInfoDO;
import com.mmc.iuav.user.model.vo.AppletMsgVO;
import com.mmc.iuav.user.model.vo.WxLoginVO;
import com.mmc.iuav.user.model.vo.WxMsgVO;
import com.mmc.iuav.user.service.WxService;
import com.mmc.iuav.user.util.WxApiUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author: zj
 * @Date: 2023/5/16 13:44
 */
@Service
public class WxServiceImpl implements WxService {
    @Autowired
    private UserSystemConstant userSystemConstant;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserSubInfoDao userSubInfoDao;

    @Override
    public String appLogin(WxLoginVO wxLoginVO) {
        String url = WxConstant.CODE2_SESSION_URL + "?appid=" + userSystemConstant.getWxAppId() + "&secret=" +
                userSystemConstant.getWxAppSecret() + "&js_code=" + wxLoginVO.getCode() + "&grant_type=" + WxConstant.GRANT_TYPE;
        String data = HttpsRequestUtil.httpsGet(url, null);
        return data;
    }

    @Override
    public String pcLogin(WxLoginVO wxLoginVO) {
        String url = WxConstant.ACCESS_TOKEN_URL + "?appid=" + userSystemConstant.getWxAppId() + "&secret=" + userSystemConstant.getWxAppSecret() +
                "&code=" + wxLoginVO.getCode() + "&grant_type=" + WxConstant.GRANT_TYPE;
        String data = HttpsRequestUtil.httpsGet(url, null);
        return data;
    }

    @Override
    public String getAccessToken() {
        //token有效期为7200s，需要保存起来，先从redis中获取accessToken，没有则请求获取
        String accessToken = stringRedisTemplate.opsForValue().get(WxConstant.IUAV_MINI_PROGRAM_ACCESS_TOKEN);
        if (StringUtils.isBlank(accessToken)){
            String getAccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token" + "?grant_type=client_credential" + "&appid=" +
                    userSystemConstant.getWxAppId() + "&secret=" + userSystemConstant.getWxAppSecret();
            String accessTokenMsg = HttpsRequestUtil.httpsGet(getAccessTokenUrl, null);
            JSONObject tokenResult = JSONObject.parseObject(accessTokenMsg);
            if (accessTokenMsg.indexOf("access_token") == -1) {
                System.out.println("获取小程序access_token有误：" + tokenResult);
                return null;
            }
            accessToken = tokenResult.getString("access_token");
            long expiresIn = tokenResult.getLong("expires_in");
            //保存进redis
            stringRedisTemplate.opsForValue().set(WxConstant.IUAV_MINI_PROGRAM_ACCESS_TOKEN, accessToken, expiresIn, TimeUnit.SECONDS);
            return accessToken;
        }
        return accessToken;
    }

    @Override
    public String getSubAccessToken() {
        //token有效期为7200s，需要保存起来，先从redis中获取accessToken，没有则请求获取
        String accessToken = stringRedisTemplate.opsForValue().get(WxConstant.SHARE_FLY_SUB_ACCESS_TOKEN);
        if (StringUtils.isBlank(accessToken)){
            String getAccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token" + "?grant_type=client_credential" + "&appid=" +
                    userSystemConstant.getWxSubAppId() + "&secret=" + userSystemConstant.getWxSubSecret();
            String accessTokenMsg = HttpsRequestUtil.httpsGet(getAccessTokenUrl, null);
            JSONObject tokenResult = JSONObject.parseObject(accessTokenMsg);
            if (accessTokenMsg.indexOf("access_token") == -1) {
                System.out.println("获取公众号access_token有误：" + tokenResult);
                return null;
            }
            accessToken = tokenResult.getString("access_token");
            long expiresIn = tokenResult.getLong("expires_in");
            //保存进redis
            stringRedisTemplate.opsForValue().set(WxConstant.SHARE_FLY_SUB_ACCESS_TOKEN, accessToken, expiresIn, TimeUnit.SECONDS);
            return accessToken;
        }
        return accessToken;
    }

    @Override
    public String receiveSubAccountEvents(HttpServletRequest request) {
        try {
            Map<String, String> map = this.convertRequestToMap(request);
            String event = map.get("Event");
            if (WxConstant.subscribe.equals(event)) {
                // 关注事件
                this.subScribeUser(map);
            } else if (WxConstant.unsubscribe.equals(event)) {
                // 取消关注事件
                System.out.println("############################");
                System.out.println("###########取消关注############");
                System.out.println("############################");
                String openId = map.get("FromUserName");
                userSubInfoDao.removeUserSubInfo(openId);
            }
        } catch (Exception e) {
            System.out.println("接收消息异常" + e.getMessage());
            return "error";
        }
        return "success";
    }

    private void subScribeUser(Map<String, String> map) {
        String openId = map.get("FromUserName");
        Integer count = userSubInfoDao.countUserSubInfo(openId);
        if (count == 0) {
            UserSubInfoDO sub = new UserSubInfoDO();
            sub.setOpenId(openId);
            sub.setRegStatus(0);
            sub.setDeleted(0);
            sub.setCreateTime(new Date());
            userSubInfoDao.insertUserSubInfo(sub);
//            WxRequestVO wq = new WxRequestVO();
//            wq.setOpenId(sub.getOpenId());
//            publicsher.sendDirectWxRegUser(wq, RabbitMqConfig.USER_WX_ROUTING_KEY);
            this.updateWXUserInfo(openId);
        }
    }

    private Map<String, String> convertRequestToMap(HttpServletRequest request) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8"));
        String line = "";
        StringBuffer buffer = new StringBuffer();
        while ((line = br.readLine()) != null) {
            buffer.append(line);
        }
        String notifyXml = buffer.toString();
        return WXPayUtil.xmlToMap(notifyXml);
    }

    private void updateWXUserInfo(String openid) {
        String accessToken = this.getSubAccessToken();
        if (StringUtils.isBlank(accessToken)) {
            return;
        }
        try {
            String InfoUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openid
                    + "&lang=zh_CN";
            //String jsonStr = HttpsOpenUtil.https(InfoUrl, "GET");// 错误：{"errcode":40013,"errmsg":"invalid appid"}
            String jsonStr = HttpsRequestUtil.httpsRequest(InfoUrl, "GET", null, null);
            JSONObject obj = JSONObject.parseObject(jsonStr);
            // 用户是否订阅该公众号标识，值为0时，代表此用户没有关注该公众号，拉取不到其余信息。
            Integer subscribe = obj.getInteger("subscribe");
            if (subscribe != null && subscribe == 1) {
                System.out.println("###########access_token##########");
                System.out.println(accessToken);
                System.out.println("###########用户信息##########");
                System.out.println(jsonStr);
                UserSubInfoDO user = new UserSubInfoDO();
                user.setOpenId(openid);
                user.setUnionId(obj.getString("unionid"));
                user.setNickName(obj.getString("nickname"));
                user.setRegStatus(1);
                userSubInfoDao.updateUserSubInfo(user);
                return;
            } else {
                System.out.println("未订阅公众号，无法拉取信息。");
                return;
            }
        }catch (Exception e){
            throw new RuntimeException();
        }
    }


    @Override
    public ResultBody sendSubTemplateMsg(WxMsgVO ws) {
        System.out.println("###########开始发送公众号消息##########");
        String accessToken = null;
        try {
            accessToken = this.getSubAccessToken();
            System.out.println("accesstoken:" + accessToken);
            String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;
            String param = ws.buildMsgJson();
            System.out.println("参数：" + param);
            String result = HttpHelper.httpPost(url, param);
            System.out.println("###########结束发送公众号消息##########");
            System.out.println(result);
        } catch (Exception e) {
            System.out.println("accessToken获取失败:" + e.getMessage());
            return ResultBody.error(ResultEnum.WX_ACCESS_TOKEN_ERROR.getResultCode(),
                    ResultEnum.WX_ACCESS_TOKEN_ERROR.getResultMsg() + e.getMessage());
        }
        return ResultBody.success();
    }

    @Override
    public ResultBody getUnLimitedQRCode(String path, String scene) {
        String base64 = "";
        try {
            String accessToken = this.getAccessToken();
            JSONObject param = new JSONObject();
            param.put("scene", scene);
            param.put("page", path);
            param.put("width", 430);
            param.put("check_path", false);
            param.put("env_version", userSystemConstant.getEnvVersion());
            String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + accessToken;
            //base64 = HttpHelper.httpPost(url, param.toJSONString());
            base64 = HttpsRequestUtil.getACodeBase64(url, "POST", null, param.toJSONString());
            return ResultBody.success(base64);
        } catch (Exception e) {
            return ResultBody.error(ResultEnum.APPLET_QR_CODE_CREATE_ERROR);
        }
    }

    @Override
    public ResultBody sendAppletMsg(AppletMsgVO appletMsgVO) {
        System.out.println("###########开始发送-小程序-用户端消息##########");
        String accessToken = this.getAccessToken();
        if (StringUtils.isBlank(accessToken)){
            return ResultBody.error(ResultEnum.WX_ACCESS_TOKEN_ERROR.getResultCode(),
                    ResultEnum.WX_ACCESS_TOKEN_ERROR.getResultMsg());
        }
        try {
            String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken;
            appletMsgVO.setData(WxApiUtil.buildMsgJson(appletMsgVO.getData()));
            String param = JSONObject.toJSONString(appletMsgVO);
            System.out.println("参数：" + param);
            HttpHelper.httpPost(url, param);
        } catch (Exception e){
            System.out.println("系统异常：" + e.getMessage());
        }
        System.out.println("###########结束发送-小程序-消息##########");
        return ResultBody.success();
    }

    @Override
    public String createUrlLink(String path, String query) {
        try {
            String accessToken = this.getAccessToken();
            JSONObject param = new JSONObject();
            param.put("path", path);
            param.put("env_version", userSystemConstant.getEnvVersion());
            param.put("query", query);
            String url = "https://api.weixin.qq.com/wxa/generate_urllink?access_token=" + accessToken;
            String res = HttpHelper.httpPost(url, param.toString());
            JSONObject result = JSONObject.parseObject(res);
            if (result.getString("errcode").equals("0")) {
                return result.getString("url_link");
            }
            return res;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String getUserPhoneNumber(Integer id, String code) {
        try {
            String accessToken = this.getAccessToken();
            JSONObject param = new JSONObject();
            param.put("code", code);
            String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
            String res = HttpHelper.httpPost(url, param.toString());
            JSONObject result = JSONObject.parseObject(res);
            System.out.println("用户授权手机号：" + res);
            if (result.getString("errcode").equals("0")) {
                String phone_info = result.getString("phone_info");
                JSONObject phoneInfoObject = JSONObject.parseObject(phone_info);
                return phoneInfoObject.getString("purePhoneNumber");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
