package com.miaxis.wx.service.impl;

import cn.hutool.json.XML;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.miaxis.common.constant.Constants;
import com.miaxis.common.core.domain.entity.UserInfo;
import com.miaxis.common.utils.StringUtils;
import com.miaxis.common.utils.wx.MessageUtil;
import com.miaxis.feign.service.IWxSendService;
import com.miaxis.school.domain.SchoolInfo;
import com.miaxis.school.mapper.SchoolInfoMapper;
import com.miaxis.school.service.ISchoolInfoService;
import com.miaxis.system.service.ISysUserService;
import com.miaxis.user.service.IUserInfoService;
import com.miaxis.wx.domain.WxForeverCode;
import com.miaxis.wx.dto.QueryParams;
import com.miaxis.wx.service.IWxForeverCodeService;
import com.miaxis.wx.service.IWxGzhService;
import com.miaxis.wx.service.IWxMessageEvenService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 微信公众号业务层
 * @author wwl
 * @version 1.0
 * @date 2021/10/20 14:57
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class WxGzhServiceImpl implements IWxGzhService {

    private final RedisTemplate redisTemplate;

    private final IWxSendService wxSendService;

    private final ISysUserService userService;

    private final IUserInfoService userInfoService;

    private final IWxMessageEvenService wxMessageEvenService;

    private final IWxForeverCodeService wxForeverCodeService;

    private final SchoolInfoMapper schoolInfoMapper;

    private final ISchoolInfoService schoolInfoService;

    @Value("${app.appid}")
    private String appid;

    @Value("${app.appSecret}")
    private String secret;


    /**
     * 获取微信公众号token
     * @return
     */
    @Override
    public String getGzhToken() {
        String token = "";
        Integer expiresIn;
        if (redisTemplate.hasKey(Constants.GZH_MESSAGE_TOKEN)){
            token = (String)redisTemplate.opsForValue().get(Constants.GZH_MESSAGE_TOKEN);
        }
        if (StringUtils.isEmpty(token)){
            String result = wxSendService.getAccessToken("client_credential",appid,secret);
            JSONObject json = JSONObject.parseObject(result);
            token = json.getString("access_token");
            expiresIn = json.getIntValue("expires_in");
            if (expiresIn <= 0){
                expiresIn = 7000;
            }

            redisTemplate.opsForValue().set(Constants.GZH_MESSAGE_TOKEN,token,expiresIn, TimeUnit.SECONDS);
        }

        return token;
    }



    /**
     * 微信推送消息处理
     * @param request
     * @return
     */
    @Override
    public String handlePublicMsg(HttpServletRequest request) {
        try {
            log.info("1....");
            cn.hutool.json.JSONObject decryptMap = XML.toJSONObject(IOUtils.toString(request.getInputStream()));
            cn.hutool.json.JSONObject jsonObjectData = decryptMap.getJSONObject("xml");


            //cn.hutool.json.JSONObject jsonObjectData = new cn.hutool.json.JSONObject("{\"CreateTime\":1639474955,\"EventKey\":\"https://jpcj-h5.zzxcx.net\",\"ToUserName\":\"gh_628da25a95e5\",\"MsgType\":\"event\",\"MenuId\":442656773,\"Event\":\"VIEW\",\"FromUserName\":\"ovKTX50v7OAEPI_ERofpUvrNQCJU\"}");
            log.info("2-----jsonObjectData------"+jsonObjectData);



            //开发者微信号
            String toUserName = jsonObjectData.getStr("ToUserName");
            //发送方帐号（一个OpenID）
            String fromUserName = jsonObjectData.getStr("FromUserName");
            // 区分消息类型
            String msgType = jsonObjectData.getStr("MsgType");
            //获取用户信息
//            String userInfoResult = wxSendService.userInfo(this.getGzhToken(), fromUserName, "zh_CN");
//            JSONObject jsonObj = JSONObject.parseObject(userInfoResult);

            // 普通消息
            if (MessageUtil.MESSAGE_TEXT.equals(msgType)) { // 文本消息
                log.info("2.1...");
                String content = jsonObjectData.getStr("Content");
                String bizmsgmenuid = jsonObjectData.getStr("bizmsgmenuid");
                //如果是选择驾校事件
                if (bizmsgmenuid != null){
                    return dealSchoolMsg(bizmsgmenuid,content,fromUserName,toUserName);
                }
                WxForeverCode wxForeverCode = wxForeverCodeService.getOne(new QueryWrapper<WxForeverCode>().eq("code", content).isNull("openid"));
                //若该口令为未使用的口令
                if (wxForeverCode != null){
                    log.info("2.1.1:口令有效，生成永久二维码");
                    String mediaId = wxMessageEvenService.gainTicketEvent(fromUserName, this.getGzhToken(),true,wxForeverCode);
                    return MessageUtil.initImage(fromUserName,toUserName,mediaId);
                }
                else if (content.startsWith("你好")){
                    return MessageUtil.initText(fromUserName, toUserName, "你好啊");
                }else if (content.startsWith("重置驾校")){
                    UserInfo userInfo = userService.getStudentByOpenId(fromUserName);
                    userInfo.setAreaName("");
                    userInfo.setCityName("");
                    userInfo.setSchoolName("");
                    userInfoService.updateById(userInfo);
                    return MessageUtil.initText(fromUserName, toUserName, "重置驾校成功，请重新生成二维码！");
                }else {
                    return MessageUtil.initText(fromUserName, toUserName, "金牌车教，您的学车好伙伴！");
                }

            } else if (MessageUtil.MESSAGE_IMAGE.equals(msgType)) { // 图片消息
                log.info("2.2...");
                return MessageUtil.initText(fromUserName, toUserName, "抱歉，暂时无法识别图片信息！");
            }else if (MessageUtil.MESSAGE_EVENT.equals(msgType)) { // 事件消息
                log.info("3....");
                String result = null ;
                // 区分事件推送
                String event = jsonObjectData.getStr("Event");
                if (MessageUtil.MESSAGE_SUBSCRIBE.equals(event)) { // 关注事件 或 扫描二维码关注事件
                    log.info("3.1...");
                    UserInfo user = userService.getStudentByOpenId(fromUserName);
                    UserInfo userInfo = new UserInfo();
                    userInfo.setOpenid(fromUserName);

                    //存在Ticket为扫码关注
                    if (org.apache.commons.lang3.StringUtils.isNotEmpty(jsonObjectData.getStr("Ticket"))){
                        log.info("3.1.2..");
                        //根据Ticket  绑定信息到上级用户
                        String subscribeEvent = wxMessageEvenService.scanSubscribeEvent(fromUserName, jsonObjectData.getStr("EventKey").substring(8),this.getGzhToken(),userInfo.getNickName());
                        //根据父级销售类型更新当前用户类型和驾校信息
                        String parentOpenid = jsonObjectData.getStr("EventKey").substring(8);
                        UserInfo parentUserInfo = userService.getStudentByOpenId(parentOpenid);
                        if (parentUserInfo != null && (parentUserInfo.getSaleType() ==1 || parentUserInfo.getSaleType() ==3 )){
                            userInfo.setSaleType(1);
                            user.setSaleType(1);
                            if (!StringUtils.isEmpty(parentUserInfo.getSchoolName())){
                                userInfo.setCityName(parentUserInfo.getCityName());
                                userInfo.setSchoolName(parentUserInfo.getSchoolName());
                                userInfo.setAreaName(parentUserInfo.getAreaName());
                                user.setCityName(parentUserInfo.getCityName());
                                user.setSchoolName(parentUserInfo.getSchoolName());
                                user.setAreaName(parentUserInfo.getAreaName());
                            }
                        }
                        result =  MessageUtil.initText(fromUserName,toUserName,subscribeEvent);

                    }else {
                        result =  MessageUtil.initText(fromUserName, toUserName, "欢迎关注金牌车教，您的学车好伙伴！");
                    }

                    if (user == null){
                        //保存用户信息
                       userInfoService.save(userInfo);

                    }else{
                        userInfoService.updateById(user);
                    }
                    return result;



                }  else if (MessageUtil.MESSAGE_UNSUBSCRIBE.equals(event)) { // 取消订阅事件
                    // todo 处理取消订阅事件

                } else if (MessageUtil.MESSAGE_SCAN.equals(event)) { // 已关注扫描二维码事件
                    log.info("3.2...");
                    //根据Ticket  绑定信息到上级用户
                    String subscribeEvent = wxMessageEvenService.scanSubscribeEvent(fromUserName, jsonObjectData.getStr("EventKey"),this.getGzhToken(),"");
                    //根据父级销售类型更新当前用户类型
                    String parentOpenid = jsonObjectData.getStr("EventKey");
                    UserInfo parentUserInfo = userService.getStudentByOpenId(parentOpenid);
                    if (parentUserInfo != null && (parentUserInfo.getSaleType() ==1 || parentUserInfo.getSaleType() ==3 )){
                        UserInfo userInfo = userService.getStudentByOpenId(fromUserName);
                        userInfo.setSaleType(1);
                        if (!StringUtils.isEmpty(parentUserInfo.getSchoolName())){
                            userInfo.setCityName(parentUserInfo.getCityName());
                            userInfo.setSchoolName(parentUserInfo.getSchoolName());
                            userInfo.setAreaName(parentUserInfo.getAreaName());
                        }
                        userInfoService.updateById(userInfo);
                    }
                    return  MessageUtil.initText(fromUserName,toUserName,subscribeEvent);

                } else if (MessageUtil.MESSAGE_LOCATION.equals(event)) { // 上报地理位置事件
                    // todo 处理上报地理位置事件

                } else if (MessageUtil.MESSAGE_CLICK.equals(event)) { // 点击菜单拉取消息时的事件推送事件
                    log.info("3.3.....click:" + jsonObjectData.get("EventKey"));
                    //判断事件KEY值，与自定义菜单接口中KEY值对应
                    if ("generateTicket".equals(jsonObjectData.get("EventKey"))){ //获取分销二维码
                        //先判定之前是否存在永久码，若存在，则返回相应的素材id
                        WxForeverCode wxForeverCode = wxForeverCodeService.getOne(new QueryWrapper<WxForeverCode>().eq("openid",fromUserName));
                        if (wxForeverCode!=null){
                            log.info("3.4:返回永久码图片");
                            String mediaId = wxMessageEvenService.gainTicketEvent(fromUserName, this.getGzhToken(),true,wxForeverCode);
                            return MessageUtil.initImage(fromUserName,toUserName,mediaId);
                        }
                        //判定是否需要填写驾校信息
                        //查询该用户的销售类型
                        UserInfo userInfo = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("openid", fromUserName));
                        //查询该用户的上级
                        UserInfo upUserInfo = userInfoService.getUpUserInfo(fromUserName);
                        //当用户销售类型为 普通用户(含驾校分成) 并且他的父级不是代理商(含驾校分成)时，且未填写驾校信息时则需要填写驾校信息
                       if (userInfo.getSaleType() ==1 && upUserInfo!= null &&upUserInfo.getSaleType()!=3 && StringUtils.isEmpty(userInfo.getSchoolName()) ){
                           return choseSchoolName(userInfo,fromUserName,toUserName);
                       }
                        String mediaId = wxMessageEvenService.gainTicketEvent(fromUserName, this.getGzhToken(), false, wxForeverCode);
                        return MessageUtil.initImage(fromUserName,toUserName,mediaId);
                    }

                } else if (MessageUtil.MESSAGE_VIEW.equals(event)) { // 点击菜单跳转链接时的事件推送
                    // todo 处理点击菜单跳转链接时的事件推送
                }
            }
        } catch (Exception e) {
            log.error("处理微信公众号请求信息，失败", e);
        }
        return null;
    }

    private String dealSchoolMsg(String bizmsgmenuid, String content, String fromUserName, String toUserName) throws Exception {
        UserInfo userInfo = userInfoService.getOne(new QueryWrapper<UserInfo>().eq("openid", fromUserName));
        // 1选择城市 2选择区 3选择学校
        if ("1".equals(bizmsgmenuid)) {
            StringBuffer buffer = new StringBuffer();
            if (!StringUtils.isEmpty(userInfo.getCityName())){
                buffer.append("抱歉，城市已选择,操作无效!");
            }else{
                userInfo.setCityName(content);
                userInfoService.updateById(userInfo);
                QueryParams queryParamsArea = new QueryParams();
                queryParamsArea.setChoseColumName("area_name");
                queryParamsArea.setChoseColumCode("area_code");
                queryParamsArea.setConditionColumName1("city_name");
                queryParamsArea.setValue1(content);
                List<Map> areas = schoolInfoMapper.queryNames(queryParamsArea);
                buffer.append("请选择驾校所在区:").append("\n\n");
                for (Map area : areas) {
                    String name = (String) area.get("name");
                    buffer.append("<a href=\"weixin://bizmsgmenu?msgmenuid=2&msgmenucontent=" + name + "\">" + name + "</a>").append("\n");
                }
            }

            return MessageUtil.initText(fromUserName, toUserName, buffer.toString());
        } else if ("2".equals(bizmsgmenuid)) {
            StringBuffer buffer = new StringBuffer();
            if (!StringUtils.isEmpty(userInfo.getAreaName())){
                buffer.append("抱歉，区已选择,操作无效!");
            }else{
                userInfo.setAreaName(content);
                userInfoService.updateById(userInfo);
                QueryParams queryParamsArea = new QueryParams();
                queryParamsArea.setChoseColumName("short_name");
                queryParamsArea.setChoseColumCode("school_no");
                queryParamsArea.setConditionColumName1("city_name");
                queryParamsArea.setValue1(userInfo.getCityName());
                queryParamsArea.setConditionColumName2("area_name");
                queryParamsArea.setValue2(userInfo.getAreaName());
                List<Map> schools = schoolInfoMapper.queryNames(queryParamsArea);
                buffer.append("请选择驾校:").append("\n\n");
                for (Map school : schools) {
                    String name = (String) school.get("name");
                    String code = (String) school.get("code");
                    buffer.append("<a href=\"weixin://bizmsgmenu?msgmenuid=" + code + "&msgmenucontent=选好了\">" + name + "</a>").append("\n");

                }
            }

            return MessageUtil.initText(fromUserName, toUserName, buffer.toString());
            //如果输出的是驾校，则返回二维码
        }else {
                SchoolInfo schoolInfo = schoolInfoService.getOne(new QueryWrapper<SchoolInfo>().eq("school_no", bizmsgmenuid));
                userInfo.setSchoolName(schoolInfo.getSchoolName());
                userInfoService.updateById(userInfo);
                String mediaId = wxMessageEvenService.gainTicketEvent(fromUserName, this.getGzhToken(), false, null);
                return MessageUtil.initImage(fromUserName, toUserName, mediaId);
        }



    }

    private String choseSchoolName(UserInfo userInfo,String fromUserName,String toUserName) throws Exception {
        //城市未填写
        if (StringUtils.isEmpty(userInfo.getCityName())){
            QueryParams queryParams = new QueryParams();
            queryParams.setChoseColumName("city_name");
            queryParams.setChoseColumCode("city_code");
            List<Map> cities = schoolInfoMapper.queryNames(queryParams);
            StringBuffer buffer = new StringBuffer();
            buffer.append("请选择驾校所在城市:").append("\n\n");
            for (Map city: cities){
                String name = (String) city.get("name");
                buffer.append("<a href=\"weixin://bizmsgmenu?msgmenuid=1&msgmenucontent="+name+"\">"+name+"</a>").append("\n");
            }
            return MessageUtil.initText(fromUserName, toUserName, buffer.toString());
        }else if (StringUtils.isEmpty(userInfo.getAreaName())) {
            QueryParams queryParamsArea = new QueryParams();
            queryParamsArea.setChoseColumName("area_name");
            queryParamsArea.setChoseColumCode("area_code");
            queryParamsArea.setConditionColumName1("city_name");
            queryParamsArea.setValue1(userInfo.getCityName());
            List<Map> areas = schoolInfoMapper.queryNames(queryParamsArea);
            StringBuffer buffer = new StringBuffer();
            buffer.append("请选择驾校所在区:").append("\n\n");
            for (Map area: areas){
                String name = (String) area.get("name");
                buffer.append("<a href=\"weixin://bizmsgmenu?msgmenuid=2&msgmenucontent="+name+"\">"+name+"</a>").append("\n");
            }
            return MessageUtil.initText(fromUserName, toUserName, buffer.toString());
        }
        else if (StringUtils.isEmpty(userInfo.getSchoolName())) {
            QueryParams queryParamsArea = new QueryParams();
            queryParamsArea.setChoseColumName("short_name");
            queryParamsArea.setChoseColumCode("school_no");
            queryParamsArea.setConditionColumName1("city_name");
            queryParamsArea.setValue1(userInfo.getCityName());
            queryParamsArea.setConditionColumName2("area_name");
            queryParamsArea.setValue2(userInfo.getAreaName());
            List<Map> schools = schoolInfoMapper.queryNames(queryParamsArea);
            StringBuffer buffer = new StringBuffer();
            buffer.append("请选择驾校:").append("\n\n");
            for (Map school: schools){
                String name = (String) school.get("name");
                String code = (String)school.get("code");
                buffer.append("<a href=\"weixin://bizmsgmenu?msgmenuid="+code+"&msgmenucontent=选好了\">"+name+"</a>").append("\n");
            }
            return MessageUtil.initText(fromUserName, toUserName, buffer.toString());

        }

        return null;
    }




}
