package vip.xiaonuo.biz.modular.api.service;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import vip.xiaonuo.biz.modular.officialinfo.entity.OfficialInfo;
import vip.xiaonuo.biz.modular.officialinfo.service.OfficialInfoService;
import vip.xiaonuo.biz.modular.utils.MsgUtil;
import vip.xiaonuo.biz.modular.utils.XmlUtil;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.prop.CommonProperties;

import java.io.PrintWriter;
import java.util.Date;
import java.util.Map;

@Slf4j
@Service
public class ApiService {

    @Resource
    private OfficialInfoService officialInfoService;

    @Resource
    private CommonProperties commonProperties;

    public static JSONObject wx_token_map = new JSONObject();

    public void officialCallback(HttpServletRequest request, HttpServletResponse response) {
        // 响应消息
        PrintWriter out = null;
        String resMessage = "";
        try {
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            //把微信返回的xml信息转义成map
            Map<String, Object> map = XmlUtil.parseXML(request.getInputStream());
            //消息来源用户标识
            String fromUserName = (String) map.get("FromUserName");
            //消息目的用户标识
            String toUserName = (String) map.get("ToUserName");
            //消息创建时间（整型）
            String createTime = (String) map.get("CreateTime");
            //消息类型
            String msgType = (String) map.get("MsgType");
            //事件类型：subscribe/unsubscribe
            String eventType = (String) map.get("Event");
            //如果为事件类型
            if (MsgUtil.MSGTYPE_EVENT.equals(msgType)) {
                //查询是否存在公众号表记录
                QueryWrapper<OfficialInfo> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(OfficialInfo::getOfficialOpenId, fromUserName)
                        .last("limit 1");
                OfficialInfo officialInfo = officialInfoService.getOne(queryWrapper);
                if (officialInfo == null) {
                    officialInfo = new OfficialInfo();
                    JSONObject jsonObject = this.getUserInfo(fromUserName);
                    if (jsonObject != null) {
                        officialInfo.setWxAddress(jsonObject.getString("country")
                                + jsonObject.getString("province")
                                + jsonObject.getString("city"));
                        officialInfo.setCreateTime(new Date());
                        officialInfo.setNickName(jsonObject.getString("nickname"));
                        officialInfo.setOfficialOpenId(jsonObject.getString("openid"));
                        officialInfo.setUnionId(jsonObject.getString("unionid"));
                        officialInfo.setWxHead(jsonObject.getString("headimgurl"));
                        officialInfoService.save(officialInfo);
                    }
                }
                //处理订阅事件-关注与取消关注
                if (MsgUtil.MESSAGE_SUBSCIBE.equals(eventType)) {
                    officialInfo.setStatus(1);
                    System.out.println("您好，谢谢您的关注！！");
                    if (ObjectUtil.isEmpty(officialInfo.getUnionId())) {
                        JSONObject jsonObject = this.getUserInfo(fromUserName);
                        if (jsonObject != null) {
                            officialInfo.setUnionId(jsonObject.getString("unionid"));
                        }
                    }
                    resMessage = MsgUtil.subscribeForText(toUserName, fromUserName, "您好，谢谢您的关注！！");
                } else if (MsgUtil.MESSAGE_UNSUBSCIBE.equals(eventType)) {//取消订阅
                    officialInfo.setStatus(0);
                    resMessage = MsgUtil.unsubscribeForText(toUserName, fromUserName, "取消关注~");
                }
                officialInfoService.updateById(officialInfo);
                log.info("eventType:" + eventType + ",fromUserName:" + fromUserName + ",toUserName:" + toUserName + ",msgType:" + msgType + ",createTime:" + createTime);
            }
            out = response.getWriter();
            out.println(resMessage);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("公众号回调异常------", e.getMessage());
            //itemErrorInfoService.errorAdd(e);
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }


    /**
     * 微信公众号的appid以及sercet
     *
     * @param openId
     * @return
     */
    private JSONObject getUserInfo(String openId) {
        JSONObject jsonObject = null;
        String accessToken = getAccessToken(commonProperties.getOfficialAppId(), commonProperties.getOfficialSecret());
        log.info("-------openId：" + openId + "-------");
        log.info("-------accessToken：" + accessToken + "-------");
        StringBuffer url = new StringBuffer("https://api.weixin.qq.com/cgi-bin/user/info");
        url.append("?access_token=").append(accessToken);
        url.append("&openid=").append(openId);
        url.append("&lang=zh_CN");

        String content = HttpUtil.get(url.toString());
        if (ObjectUtil.isNotEmpty(content)) {
            jsonObject = JSONObject.parseObject(content);
        }
        log.info("-------微信用户信息：" + content + "-------");
        return jsonObject;
    }


    private String getAccessToken(String sAppid, String sSecret) {
        // 因为微信有限制次数跟有效期，所以需要存在redis中
        if (wx_token_map.size() == 0) {
            wx_token_map.put("token", null);
        }
        String token = wx_token_map.getString("token");
        // token失效或者为空
        if (StrUtil.isEmpty(token) || "null".equals(token)) {
            StringBuffer url = new StringBuffer("https://api.weixin.qq.com/cgi-bin/token");
            url.append("?grant_type=client_credential");
            url.append("&appid=").append(sAppid);
            url.append("&secret=").append(sSecret);
            log.info(url.toString());
            String content = HttpUtil.get(url.toString());
            if (StrUtil.isEmpty(content) || !content.contains("access_token")) {
                log.info(content);
                throw new CommonException("获取公众号accessToken失败");
            }
            token = JSONObject.parseObject(content).getString("access_token");
            // 设置为1.9h(有效期2h)
            wx_token_map.put("token", token);
            wx_token_map.put("time", System.currentTimeMillis());
        } else {
            Long time = wx_token_map.getLong("time");
            long l = System.currentTimeMillis();
            if ((l - time) >= 1.9 * 3600 * 1000) {
                wx_token_map.clear();
                getAccessToken(sAppid, sSecret);
            }

        }
        return token;
    }
}
