package com.ematou.wxservice.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ematou.wxservice.api.WeChatApi;
import com.ematou.wxservice.api.WeChatApiRestTemplate;
import com.ematou.wxservice.common.constant.WeChatConstant;
import com.ematou.wxservice.common.utils.DateUtil;
import com.ematou.wxservice.common.utils.SignUtil;
import com.ematou.wxservice.config.WeChatGeneralConfig;
import com.ematou.wxservice.entity.pojo.Material;
import com.ematou.wxservice.entity.vo.AccessToken;
import com.ematou.wxservice.entity.vo.BindingInfo;
import com.ematou.wxservice.entity.vo.TemplateMessage;
import com.ematou.wxservice.entity.pojo.UserInfo;
import com.ematou.wxservice.mapper.UserInfoMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.text.DecimalFormat;
import java.util.*;

/**
 * @author lhm
 * @version 1.0
 * 2021-05-10 18:04
 */
@Service
public class WeChatService {

    private final static Logger logger = LoggerFactory.getLogger(WeChatService.class);

    @Autowired
    WeChatGeneralConfig weChatGeneralConfig;

    @Autowired
    WeChatApiRestTemplate weChatApiRestTemplate;

    @Autowired
    UserInfoMapper userInfoMapper;

    @Autowired
    private MaterialService materialService;
    @Autowired
    WeChatMessageService weChatMessageService;
    @Value("${wechat}")
    String wechat;
    @Value("${wx.general.appId}")
    private String appId;
    /**
     * 获取普通AccessToken
     * @return AccessToken
     * @throws RuntimeException 异常
     */
    public AccessToken getAccessToken() throws RuntimeException {
        String response = weChatApiRestTemplate.getForOther(String.format(WeChatApi.GET_TOKEN_NEW.getUrl(),wechat));
        AccessToken accessToken = null;
        if(StringUtils.isEmpty(response)){
            accessToken = JSON.parseObject(response).getObject("data", AccessToken.class);
        }

        if (null == accessToken) {
            response = weChatApiRestTemplate.getForOther(String.format(WeChatApi.GET_TOKEN_NEW.getUrl(),wechat));
            accessToken = JSON.parseObject(response).getObject("data", AccessToken.class);
            if (null == accessToken) {
                logger.error("微信基础服务可能已经宕机！response：" + response);
                throw new RuntimeException("获取AccessToken失败，请稍后再试！");
            }
        }

        return accessToken;
    }

    /**
     * 获取用户信息
     * @param bindingInfo bindingInfo
     * @return 用户信息
     * @throws RuntimeException 异常
     */
    public UserInfo getUserInfo(BindingInfo bindingInfo) throws RuntimeException {
        if (!StringUtils.hasLength(bindingInfo.getOpenId())) {
            logger.error("获取用户信息的openId为空");
            return null;
        }
        String accessToken = getAccessToken().getAccessToken();

        UserInfo userInfo;
        String response = null;
        try {
            response = weChatApiRestTemplate.getForOther(String.format(WeChatApi.GET_USER_INFO.getUrl(), accessToken, bindingInfo.getOpenId()));
            userInfo = JSON.parseObject(response, UserInfo.class);
            userInfo.setTellPhoneNumber(bindingInfo.getTellPhoneNumber());
            userInfo.setValidateCode(bindingInfo.getValidateCode());
            userInfo.setTagidList(null);
            userInfoMapper.updateOrInsertUserInfo(userInfo);
        } catch (RuntimeException e) {
            logger.error("请求微信平台获取用户信息出错！response：" + response + "，error message：" + e.getMessage());
            throw new RuntimeException("请求微信平台获取用户信息出错！");
        }
        return userInfo;
    }

    /**
     * 根据模板编号获取模板消息ID
     * @param templateNum 模板编号
     * @see WeChatConstant.TemplateMsgId
     * @return 模板消息id
     */
    public String getTemplateMsgId(String templateNum){

        String url = String.format(WeChatApi.GET_TEMPLATE_MSGID.getUrl(), getAccessToken().getAccessToken());

        String requestBody = "{ \"template_id_short\": \"" + templateNum + "\" }";

        String res = weChatApiRestTemplate.postForRest(url, requestBody);

        if (StringUtils.hasLength(res)) {
            JSONObject response = JSON.parseObject(res);
            String templateId = response.getObject("template_id", String.class);
            logger.info("获取模板消息ID成功，template_id：" + templateId);
            return templateId;
        }
        return "";
    }

    /**
     * 发送取件模板信息
     * @param msg 模板信息数据
     * @return 是否发送成功
     */
    public Integer sendTemplateMsg(TemplateMessage msg){

        String accessToken = getAccessToken().getAccessToken();
        if (!StringUtils.hasLength(accessToken)) {
            logger.error("发送模板消息时获取AccessToken值为空");
            return 0;
        }
        // TODO 这里先写死，后期可以通过请求参数传过来，由客户端决定发送什么消息
        String templateMsgId = WeChatConstant.TemplateMsgId.TAKE_PARCEL_CODE_TEMPLATE_MSG_ID;

        String url = String.format(WeChatApi.SEND_TEMPLATE_MSG.getUrl(), accessToken);

        // 组装消息数据
        HashMap<String, Object> body = new HashMap<>();
        body.put("touser", msg.getOpenId());
        body.put("template_id", templateMsgId);
        if (StringUtils.hasLength(msg.getUrl())) {
            body.put("url", msg.getUrl());
        }
        if (null != msg.getMiniProgram()) {
            body.put("miniprogram", msg.getMiniProgram());
        }
        HashMap<String, Object> data = new HashMap<>();
        // 组装data数据
        for (int i = 0; i < msg.getData().size(); i++) {
            TemplateMessage.TemplateData templateData = msg.getData().get(i);
            if (i == 0) {
                data.put("first", templateData);
                continue;
            }
            if (i == msg.getData().size()-1) {
                data.put("remark", templateData);
                break;
            }
            data.put("keyword" + i, templateData);
        }
        body.put("data", data);

        String res;
        try {
            res = weChatApiRestTemplate.postForRest(url, body);

            if (!StringUtils.hasLength(res)) {
                return 0;
            }
        } catch (Exception e) {
            logger.error("推送模板消息失败，exception message：" + e.getMessage());
            return 0;
        }

        return 1;
    }

    /**
     * 微信OAuth2.0授权，静默授权只获取openid
     * @param code 请求参数, 临时凭证
     * @return openid
     */
    public Map<String, Object> oauth2(String code){

        HashMap<String, Object> map = new HashMap<>();
        String url = String.format(WeChatApi.WECHAT_OAUTH_TOKEN.getUrl(), weChatGeneralConfig.getAppId(), weChatGeneralConfig.getAppSecret(), code);

        String res = weChatApiRestTemplate.getForOther(url);

        if (StringUtils.hasLength(res)) {

            JSONObject jsonObject = JSON.parseObject(res);

            Object openid = jsonObject.get("openid");

            if (null != openid && StringUtils.hasLength(openid.toString())) {
                map.put("openid", openid);
            } else {
                logger.error("授权出现错误! 错误信息: " + res);
            }
        }
        return map;
    }

    public Map<String, Object> jsSign(String url) {
        AccessToken accessToken = getAccessToken();
        String getUrl = String.format(WeChatApi.GET_TICKET.getUrl(), accessToken.getAccessToken());
        String resp = weChatApiRestTemplate.getForOther(getUrl);
        JSONObject jsonObject = JSONObject.parseObject(resp);
        String ticket = jsonObject.getString("ticket");
        String timestamp = String.valueOf(new Date().getTime() / 1000);
        DecimalFormat df = new DecimalFormat("00000000");
        String nonceStr = df.format(new Random().nextInt(100000000));
        String sign = SignUtil.jsApiSign(ticket, url, timestamp, nonceStr);
        Map<String, Object> result = new HashMap<>();
        result.put("appId", appId);
        result.put("timestamp", timestamp);
        result.put("nonceStr", nonceStr);
        result.put("signature", sign);
        return result;
    }


    public String mediaUpload(String eventKey) {
        try {
            File file = null;
            if (eventKey.equals(WeChatConstant.CustomEventKey.BUSINESS_COOPERATION)) {
                file = ResourceUtils.getFile("classpath:static/images/business-cooperation.png");
            } else if (eventKey.equals(WeChatConstant.CustomEventKey.AFTER_SALE_SERVICE)) {
                file = ResourceUtils.getFile("classpath:static/images/after-sale-service.png");
            }
            boolean flag = false;
            String mediaId ="";
            String fileName = file.getName();
            logger.info("fileName:{}", fileName);
            Material material = materialService.queryByFileName(fileName);

            logger.info("查询永久素材数据:{}", JSON.toJSONString(material));
            String accessToken = this.getAccessToken().getAccessToken();
            if(!Objects.isNull(material)){
                mediaId = material.getMediaId();
                String url = String.format(WeChatApi.MEDIA_GET.getUrl(), accessToken);
                String requestBody = "{ \"media_id\": \"" + mediaId + "\" }";
                String res = weChatApiRestTemplate.postForOther(url, requestBody);
                if(res.contains("errcode")){
                    flag = true;
                }
            }else {
                flag = true;
            }

            if(flag) {
                //在数据库和公众号服务器上未查到图片素材
                String url = String.format(WeChatApi.MEDIA_UPLOAD.getUrl(), accessToken);
                //String result = weChatApiRestTemplate.doPostByFile(url, null, file, "");
                String result = weChatApiRestTemplate.postByStream(url, file);

                JSONObject resObj = JSON.parseObject(result);
                mediaId = resObj.getString("media_id");
            }

            if(Objects.isNull(material)){
                long length = file.length();
                material = new Material();
                material.setMediaId(mediaId);
                material.setFileName(fileName);
                material.setFilePath(file.getPath());
                material.setFileSize(length);
                material.setFileType(WeChatConstant.XmlMsgType.IMAGE);
                material.setCreateTime(DateUtil.formatDate(new Date()));

                logger.info("添加永久素材数据:{}", JSON.toJSONString(material));
                materialService.save(material);
            }else {
                if(!mediaId.equals(material.getMediaId())) {
                    material.setMediaId(mediaId);
                    material.setModTime(DateUtil.formatDate(new Date()));

                    logger.info("修改永久素材数据:{}", JSON.toJSONString(material));
                    materialService.update(material);
                }
            }
            return mediaId;

        } catch (Exception e) {
            logger.error("上传公众号永久素材异常:", e);
        }
        return "";
    }

}
