package com.fengqi.wechat.controller.base;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fengqi.wechat.entity.MessageConstant;
import com.fengqi.wechat.entity.dto.AppGiftCodeDto;
import com.fengqi.wechat.entity.dto.WechatClickEventXmlDto;
import com.fengqi.wechat.entity.dto.WechatSignatureDto;
import com.fengqi.wechat.entity.vo.WechatMessageReturnVo;
import com.fengqi.wechat.entity.vo.inner.ResponseData;
import com.fengqi.wechat.enums.WechatEnum;
import com.fengqi.wechat.remote.ManageClient;
import com.fengqi.wechat.remote.WechatClient;
import com.fengqi.wechat.utils.EasyStr;
import com.fengqi.wechat.utils.HttpEntityUtil;
import com.fengqi.wechat.utils.JsonUtils;
import com.fengqi.wechat.utils.WechatUtil;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.client.RestTemplate;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@Slf4j
public abstract class AbstractWechatController {

    private static final String token = WechatEnum.FENGQI.name().toLowerCase();

    @Autowired
    protected ManageClient manageClient;

    @Autowired
    protected StringRedisTemplate stringRedisTemplate;

    @Autowired
    protected WechatClient wechatClient;

    /**
     * REST api 请求
     */
    @Autowired
    protected RestTemplate restTemplate;

    @Value("${fengqi.inner.host}")
    private String innerHost;

    /**
     * redis key
     */
    public interface RedisKey {

        /**
         * 订阅公众号的key
         *
         * @return
         */
        String getSubscribeKey();

        /**
         * 自动回复的key
         *
         * @return
         */
        String getMessageKey();
    }

    protected abstract String getAccessTokenRedisKey();

    protected abstract String getAppId();

    protected abstract String getSecret();

    protected abstract RedisKey getRedisKey();


    public static final String FORMAT = "%s\n" +
            "%s\n" +
            "礼包码:%s";

    public static final String NOCODE = "礼包已领取完";

    /**
     * 微信认证api
     *
     * @param dto
     * @return
     */
    @GetMapping(value = "/wechat_api")
    public String checkWechatService(WechatSignatureDto dto) {
        return WechatUtil.checkSignature(dto, token);
    }

    @RequestMapping(value = "/wechat_api", method = RequestMethod.POST)
    public Object getWeiXinMessage(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String, String[]> parameterMap = request.getParameterMap();
        log.info("微信调用了接口：{}", JsonUtils.ObjToString(parameterMap));
        RedisKey redisKey = getRedisKey();

        // 微信服务器POST消息时用的是UTF-8编码，在接收时也要用同样的编码，否则中文会乱码；
        request.setCharacterEncoding("UTF-8");
        // 在响应消息（回复消息给用户）时，也将编码方式设置为UTF-8，原理同上；
        response.setCharacterEncoding("UTF-8");
        ServletInputStream inputStream = request.getInputStream();
        String read = IoUtil.read(inputStream, "UTF-8");
        log.info("微信调用了接口：{}", read);

        XmlMapper xmlMapper = new XmlMapper();
        WechatClickEventXmlDto wechatClickEventXmlDto = xmlMapper.readValue(read, WechatClickEventXmlDto.class);

        System.out.println(wechatClickEventXmlDto);


        WechatMessageReturnVo wechatMessageReturnVo = WechatUtil.ConvertToVo(wechatClickEventXmlDto);


        String event = wechatClickEventXmlDto.getEvent();
        if (event != null && event.equals("subscribe")) {//关注
            String eventKey = wechatClickEventXmlDto.getEventKey();
            if (eventKey != null && eventKey.length() > 0) {
                wechatMessageReturnVo.setContent(getInnerContent(wechatClickEventXmlDto.getFromUserName(), eventKey.split("_")[1]));
                return xmlMapper.writeValueAsString(wechatMessageReturnVo);
            }
        } else if (event != null && event.equals("SCAN")) {//扫描
            String eventKey = wechatClickEventXmlDto.getEventKey();
            if (eventKey != null && eventKey.length() > 0) {
                wechatMessageReturnVo.setContent(getInnerContent(wechatClickEventXmlDto.getFromUserName(), eventKey));
                return xmlMapper.writeValueAsString(wechatMessageReturnVo);
            }
        } else if (event != null && event.equals("unsubscribe")) {//取消关注
            wechatMessageReturnVo.setContent(getInnerContent(wechatClickEventXmlDto.getFromUserName(), "unsubscribe"));
            return xmlMapper.writeValueAsString(wechatMessageReturnVo);
        }
        //获取礼包id
        String content = stringRedisTemplate.opsForValue().get(redisKey.getMessageKey() + wechatClickEventXmlDto.getContent());
        if (StrUtil.isBlank(content)) {
            return "";
        }

        JSONObject giftJson = JSONUtil.parseObj(content);
        Object rGift = manageClient.getGift(Integer.parseInt(giftJson.getStr(MessageConstant.MESSAGE_CONTENT))).get(MessageConstant.R_DATA);
        JSONObject gift = JSONUtil.parseObj(rGift);

        //礼包码
        //已领取的礼包码

        //获取礼包码
        String openid = wechatClickEventXmlDto.getFromUserName();
        Object unionidTemp = getUnionId(openid).get("unionid");
        final String unionid = (unionidTemp == null || StrUtil.isBlank(unionidTemp.toString())) ? openid : unionidTemp.toString();

        JSONArray usedCodeList = (JSONArray) manageClient.getByOpenid(unionid).get(MessageConstant.R_DATA);

        //是否已领取
        List<Object> collect = WechatUtil.isReceive(usedCodeList, unionid, giftJson);
        //未领取
        if (!collect.isEmpty()) {
            wechatMessageReturnVo.setContent(String.format(FORMAT, gift.getStr("giftName"), gift.getStr("giftContent"), JSONUtil.parseObj(collect.get(0)).getStr("giftCode")));
            return xmlMapper.writeValueAsString(wechatMessageReturnVo);
        }

        Map<String, Object> giftCode = manageClient.getCode(new AppGiftCodeDto()
                .setOpenid(unionid)
                .setGiftId(Integer.parseInt(giftJson.getStr(MessageConstant.MESSAGE_CONTENT))));

        //礼包已领取完
        if (ObjectUtil.toString(giftCode.get(MessageConstant.R_DATA)).equals("null")) {
            wechatMessageReturnVo.setContent(NOCODE);
            return xmlMapper.writeValueAsString(wechatMessageReturnVo);
        }

        //返回礼包
        wechatMessageReturnVo.setContent(String.format(FORMAT, gift.getStr("giftName"), gift.getStr("giftContent"), giftCode.get(MessageConstant.R_DATA).toString()));
        return xmlMapper.writeValueAsString(wechatMessageReturnVo);
//
//
//
//        System.out.println(wechatMessageReturnVo);
//
//        return xmlMapper.writeValueAsString(wechatMessageReturnVo);
        //  TimeUnit.SECONDS.sleep(4);
        //发送消息自动回复

//        if (wechatClickEventXmlDto.getMsgType().equals(MessageTypeEnum.TEXT.name().toLowerCase())) {
//
//            String content = stringRedisTemplate.opsForValue().get(redisKey.getMessageKey() + wechatClickEventXmlDto.getContent());
//            if (StrUtil.isBlank(content)) {
//                return "";
//            }
//
//            JSONObject obj = JSONUtil.parseObj(content);
//            WechatMessageReturnVo wechatMessageReturnVo = WechatUtil.setMessageReturn(obj, wechatClickEventXmlDto);
//            log.info("触发自动回复:{}",wechatMessageReturnVo);
//            return xmlMapper.writeValueAsString(wechatMessageReturnVo);
//
//        }else if(wechatClickEventXmlDto.getMsgType().equals(MessageTypeEnum.EVENT.name().toLowerCase())) {
//            log.info("redis_key:{}",redisKey.getMessageKey() + wechatClickEventXmlDto.getEventKey());
//            String content = stringRedisTemplate.opsForValue().get(redisKey.getMessageKey() + wechatClickEventXmlDto.getEventKey());
//            log.info("redis:{}",content);
//            if (StrUtil.isBlank(content)) {
//                return "";
//            }
//
//            if (MessageConstant.EVENT_CLICK.equals(wechatClickEventXmlDto.getEvent().toLowerCase())) {
//                JSONObject obj = JSONUtil.parseObj(content);
//                WechatMessageReturnVo wechatMessageReturnVo = WechatUtil.setMessageReturn(obj, wechatClickEventXmlDto);
//                log.info("触发菜单点击回复:{}",wechatMessageReturnVo);
//                return xmlMapper.writeValueAsString(wechatMessageReturnVo);
//            }else if (MessageConstant.MESSAGE_SUBSCRIBE.equals(wechatClickEventXmlDto.getEvent().toLowerCase())) {
//                String staticContent = "您终于来啦，小编在此恭候多时[咖啡]\n" +
//                        "小编会不定期推送游戏活动预告、攻略玩法以及相关游戏福利\n" +
//                        "☞【吕布传iOS下载】☜\n" +
//                        "<a href='https://ad.funcheergame.com/1167/339109zebt4e.html?weixin=1'>☞【三国乱世霸王安卓下载】☜</a>\n" +
//                        "<a href='https://mp.weixin.qq.com/mp/homepage?__biz=Mzg5NTEzMjgzOA==&hid=1&sn=1cbe9911cb625653b79a11d4f58cd9d0&scene=18=1'>☞【玩法攻略】☜</a>";

//                content = stringRedisTemplate.opsForValue().get(redisKey.getSubscribeKey());
//
//                if (StrUtil.isBlank(content)) {
//                    content = staticContent;
//                }
//
//                WechatMessageReturnVo wechatMessageReturnVo = new WechatMessageReturnVo()
//                        .setFromUserName(wechatClickEventXmlDto.getToUserName())
//                        .setToUserName(wechatClickEventXmlDto.getFromUserName())
//                        .setCreateTime(wechatClickEventXmlDto.getCreateTime())
//                        .setMsgType(MessageConstant.MESSAGE_TYPE_TEXT)
//                        .setContent(content);
//                return xmlMapper.writeValueAsString(wechatMessageReturnVo);
//            }
//
//        }else {
//            return "";
//        }
//
//
//        return "";
    }

    private String getInnerContent(String fromUserName, String eventKey) {
        Map<String, String> innerMap = Maps.newHashMap();
        innerMap.put("action", eventKey);
        innerMap.put("openId", fromUserName);
        ResponseData<Map<String, String>> res = restTemplate.postForObject(innerHost
                + "/api/inner/user/mpapi", HttpEntityUtil.getHttpEntity(EasyStr.changeMap(innerMap)), ResponseData.class);
        if (StringUtils.equals("00000", res.getHead().getResponseCode())) {
            Map<String, String> map = res.getBody();
            String msg = map.get("msg");
            if (!StringUtils.isEmpty(msg)) {
                return msg;
            } else {
                return "操作失败，请稍后再试！";
            }

        } else {
            return "操作失败，请稍后再试！！";
        }
    }

    /**
     * 网页授权
     *
     * @param code
     * @return
     */
    @GetMapping("/get_token/{code}")
    public Object getToken(@PathVariable String code) {
        String authorization_code = wechatClient.getToken(getAppId(), getSecret(), code, "authorization_code");
        String openid = JSONUtil.parseObj(authorization_code).getStr(MessageConstant.USER_OPENID);
        Map<String, Object> userInfo = getUnionId(openid);
        userInfo.put("access_token", "access_token");
        return userInfo;
    }

    private Map<String, Object> getUnionId(String openid) {
        Map<String, Object> userInfo = wechatClient.getUserInfo(getToken(), openid, "zh_CN");
        log.info("unionid: {}", userInfo);
        return userInfo;
    }

    protected String getToken() {
        String token = stringRedisTemplate.opsForValue().get(getAccessTokenRedisKey());
        if (StrUtil.isBlank(token)) {
            System.out.println(getAppId());
            System.out.println(getSecret());
            Map<String, Object> client_credential = wechatClient.getToken("client_credential", getAppId(), getSecret());
            System.out.println(client_credential);
            String access_token = client_credential.get("access_token").toString();
            System.out.println(access_token);
            stringRedisTemplate.opsForValue().set(getAccessTokenRedisKey(), access_token, 110, TimeUnit.MINUTES);
            return access_token;
        } else {
            return token;
        }
    }


//    @GetMapping("/getButtonList")
//    public Object get() {
//        return manageClient.getMenuList().replace("data", "button")
//                .replace("children", "sub_button")
//                .replace("data", "button")
//                .replace("sname", "name")
//                .replace("skey", "key");
//    }


}
