package com.hys.app.service.base.plugin.sms;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hys.app.framework.exception.ServiceException;
import com.hys.app.framework.logs.Debugger;
import com.hys.app.model.base.message.SmsSendCallbackMsg;
import com.hys.app.model.base.rabbitmq.AmqpExchange;
import com.hys.app.model.base.vo.ConfigItem;
import com.hys.app.model.base.vo.SmsSendVO;
import com.hys.app.model.errorcode.SystemErrorCode;
import com.hys.app.model.system.dos.SmsSendRecord;
import com.hys.app.model.system.enums.AuditStatusEnum;
import com.hys.app.model.system.enums.SmsRecordStatusEnum;
import com.hys.app.model.system.enums.SmsTemplateServiceTypeEnum;
import com.hys.app.service.system.SmsPlatformManager;
import com.hys.app.service.system.SmsSendRecordManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.hys.app.framework.rabbitmq.MessageSender;
import com.hys.app.framework.rabbitmq.MqMessage;
import com.hys.app.framework.util.DateUtil;
import com.hys.app.framework.util.HttpUtils;
import com.hys.app.framework.util.JsonUtil;
import com.hys.app.framework.util.StringUtil;
import com.hys.app.mapper.system.SmsTemplateMapper;
import com.hys.app.model.system.dos.SmsTemplate;
import com.hys.app.model.system.enums.SmsTemplateTypeEnum;
import com.hys.app.service.base.plugin.express.util.MD5;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 助通短信 插件
 *
 * @author zh
 * @version v1.0
 * @since v1.0
 * 2018年3月25日 下午2:42:20
 */
@Component
public class SmsZtPlugin implements SmsPlatform {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private Debugger debugger;

    @Autowired
    private SmsTemplateMapper smsTemplateMapper;

    @Autowired
    private SmsPlatformManager smsPlatformManager;

    @Autowired
    private MessageSender messageSender;

    @Autowired
    private SmsSendRecordManager smsSendRecordManager;

    /**
     * 获取短信啊模板中的变量
     *
     * @param model
     * @return
     */
    private Map getTemplateVariable(SmsTemplate model) {

        Integer ztTypeCode = SmsTemplateTypeEnum.valueOf(model.getTemplateType()).ztTypeCode();
        //如果模板为了为推广不支持变量
        if (SmsTemplateTypeEnum.PROMOTE.ztTypeCode().equals(ztTypeCode)) {
            return null;
        }
        String paramType = "others";
        //判断模板类型如果是验证码的话  变量类型为验证码
        if (SmsTemplateTypeEnum.CODE.ztTypeCode().equals(ztTypeCode)) {
            paramType = "valid_code";
        }

        String pattern = "\\{(.*?)\\}";
        Pattern r = Pattern.compile(pattern);
        // 现在创建 matcher 对象
        HashMap<String, String> paramJson = new HashMap<>(12);
        Matcher m = r.matcher(model.getTemplateContent());
        while (m.find()) {
            String key = m.group().replaceAll("(\\{)|(\\})", "");
            paramJson.put(key, paramType);
        }
        return paramJson;
    }

    @Override
    public boolean onSend(SmsSendVO smsSendVO, Map config) {
        String phone = smsSendVO.getMobile();
        try {
            if (StringUtil.isEmpty(phone) || StringUtil.isEmpty(config)) {
                logger.error("发送短信参数异常,请检查phone={} ,content={} ,param={} ", phone, config);
                return false;
            }
            debugger.log("调起SmsZtPlugin", "配置为：", config.toString());
            String urls = "https://api.mix2.zthysms.com/v2/sendSmsTp";
            Map<String, Object> param = new HashMap<>(12);
            String signature = config.get("signature").toString();
            //tpId 模板id
            param.put("tpId", smsSendVO.getTemplateCode());
            //t模板签名
            param.put("signature", signature);
            //模板变量信息
            ArrayList<Map<String, Object>> records = new ArrayList<>();
            HashMap<String, Object> record = new HashMap<>(2);
            //手机号
            record.put("mobile", phone);

            if (StringUtil.notEmpty(smsSendVO.getTemplateParam())) {

                Map map = JSON.parseObject(smsSendVO.getTemplateParam(), Map.class);
                //内容
                record.put("tpContent", map);
            }
            records.add(record);
            param.put("records", records);
            logger.info("向ztsms.cn发出请求，请求url为：", urls);
            Map result = this.createClient(param, urls);
            smsSendVO.setBizId(result.get("msgId").toString());
            //code  为4025是传入的参数变量不正确  进行自定义短信发送
            if (StringUtil.equals(result.get("code").toString(), "4025")) {
                logger.info("进入短信自定义发送");
                //封装模板内容
                String content = this.getContent(smsSendVO.getContent(), smsSendVO.getTemplateParam());
                result = sendSms(signature, phone, content);
            }
            //判断异常
            if (!StringUtil.equals(result.get("code").toString(), "200")) {
                throw new ServiceException(SystemErrorCode.E931.code(), result.get("msg") + ",具体错误信息描述请参考https://doc.zthysms.com/web/#/1?page_id=11");
            }
            return true;
        } catch (Exception e) {
            logger.error("发送短信异常", e);
            return false;
        }

    }

    /**
     * 替换模板中的变量内容
     *
     * @param content
     * @param templateParam
     * @return
     */
    private String getContent(String content, String templateParam) {
        if (StringUtil.isEmpty(templateParam)) {
            return content;
        }
        Map<String, String> map = JSON.parseObject(templateParam, Map.class);

        for (Map.Entry<String, String> entry : map.entrySet()) {
            content = content.replace("{" + entry.getKey() + "}", entry.getValue());
        }
        return content;

    }

    /**
     * @param signature 短信签名
     * @param phone     手机号
     * @param content   内容
     * @return JSONObject
     */
    private Map sendSms(String signature, String phone, String content) {
        String url = "https://api.mix2.zthysms.com/v2/sendSms";
        Map<String, Object> param = new HashMap<>(12);
        param.put("mobile", phone);
        param.put("content", signature + content);
        return this.createClient(param, url);

    }

    @Override
    public String getPluginId() {
        return "smsZtPlugin";
    }

    @Override
    public String getPluginName() {
        return "助通网关短信";
    }

    @Override
    public List<ConfigItem> definitionConfigItem() {
        List<ConfigItem> list = new ArrayList();
        ConfigItem name = new ConfigItem();
        name.setType("text");
        name.setName("username");
        name.setText("用户名");

        ConfigItem password = new ConfigItem();
        password.setType("text");
        password.setName("password");
        password.setText("密码");

        ConfigItem signature = new ConfigItem();
        signature.setType("text");
        signature.setName("signature");
        signature.setText("模板签名");
        list.add(name);
        list.add(password);
        list.add(signature);

        return list;
    }

    @Override
    public Integer getIsOpen() {
        return 0;
    }

    @Override
    public void templateUpdateCheck(SmsTemplate oldModel) {
        return;
    }

    @Override
    public void updateTemplate(SmsTemplate oldModel, SmsTemplate newModel) {

        if (AuditStatusEnum.WAITING.description().equals(oldModel.getAuditStatus())) {
            return;
        }
        //判断助通模板状态
        String auditStatus = this.getTemplateAuditStatus(oldModel.getTemplateCode());

        if (StringUtil.notEmpty(auditStatus) && AuditStatusEnum.ZT_PASS.description().equals(auditStatus)) {
            throw new ServiceException(SystemErrorCode.E931.code(), "已经审核通过的模本不允许修改,请在https://mix2.zthysms.com/TemplateManagement该平台进行删除");
        }

        //审核通过后修改模板需要将模板编码删除
        if (AuditStatusEnum.PASS.name().equals(oldModel.getAuditStatus())) {
            newModel.setTemplateCode(null);
            //状态设置为审核中
            newModel.setAuditStatus(AuditStatusEnum.WAITING.value());
        }
        oldModel.setTemplateContent(newModel.getTemplateContent());


    }

    @Override
    public boolean isNeedAudit() {
        return true;
    }

    @Override
    public void templateSubmitAudit(SmsTemplate model) {
        //获取配置信息
        Map<String, String> configMap = this.getConfigMap();
        logger.info("调起SmsZtPlugin", "参数为：{}", configMap.toString());
        String urls = "https://api.mix2.zthysms.com/sms/v2/template";
        HashMap<String, Object> param = new HashMap<>(12);

        if (SmsTemplateServiceTypeEnum.MEMBER.value().equals(model.getServiceType())) {
            //模板名称
            param.put("temName", "M" + model.getTemplateName());
        } else {
            //模板名称
            param.put("temName", "S" + model.getTemplateName());
        }

        //模本类型
        param.put("temType", SmsTemplateTypeEnum.valueOf(model.getTemplateType()).ztTypeCode().toString());

        param.put("temContent", configMap.get("signature") + model.getTemplateContent());
        //模板code
        param.put("temId", model.getTemplateCode());

        //获取模板中的变量值
        Map map = this.getTemplateVariable(model);
        if (!StringUtil.isEmpty(map)) {
            param.put("paramJson", map);
        }
        Map result = this.createClient(param, urls);
        //判断异常
        if (!StringUtil.equals(result.get("code").toString(), "200")) {
            throw new ServiceException(SystemErrorCode.E931.code(), result.get("msg") + ",具体错误信息描述请参考https://doc.zthysms.com/web/#/1?page_id=11");
        }
        //设置模板编码
        model.setTemplateCode(result.get("temId").toString());
    }

    @Override
    public Map templateAuditCallback(String json) {
        logger.info("助通模板回调");
        HashMap<String, Object> result = new HashMap<>(1);
        result.put("code", 200);
        try {
            Map<String, Object> map = JSON.parseObject(json, Map.class);
            Map data = (Map) map.get("data");
            SmsTemplate model = smsTemplateMapper.selectOne(new QueryWrapper<SmsTemplate>().eq("template_code", data.get("temId")));
            if (Objects.isNull(model)) {
                logger.error("未找到编号：" + data.get("temId") + "的模板");
                return result;
            }
            //审核结果
            String auditStatus = data.get("auditResult").toString();
            //判断审核通过还是未通过 审核状态( 2.审核通过 3.审核不通过)
            if (AuditStatusEnum.ZT_PASS.description().equals(auditStatus)) {
                model.setAuditStatus(AuditStatusEnum.PASS.value());
            } else if (AuditStatusEnum.ZT_NOT_PASS.description().equals(auditStatus)) {
                model.setAuditStatus(AuditStatusEnum.NOT_PASS.value());
                model.setFailReason(data.get("auditMsg").toString());
            }
            smsTemplateMapper.updateById(model);
        } catch (Exception e) {
            logger.error("助通回调模板信息出错");
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public Map smsSendCallback(String json) {
        List<Map> list = JSON.parseArray(json, Map.class);
        for (Map<String, String> map : list) {
            //短信回执id
            String bizId = map.get("msgId");
            //用户接收是否成功
            String isSuccess = map.get("code");
            SmsSendCallbackMsg smsSendCallbackMsg = new SmsSendCallbackMsg();
            smsSendCallbackMsg.setBizId(bizId);
            smsSendCallbackMsg.setIsSuccess(isSuccess);
            //设置发送状态
            if (StringUtil.notEmpty(isSuccess) && "DELIVRD".equals(isSuccess)) {
                smsSendCallbackMsg.setIsSuccess("true");
            }
            this.messageSender.send(new MqMessage(AmqpExchange.SMS_SEND_CALLBACK, AmqpExchange.SMS_SEND_CALLBACK + "_ROUTING", smsSendCallbackMsg));
        }
        //必须要应答的数据，否则阿里云后台保存回调地址会失败
        Map<String, Object> map = new HashMap(1);
        map.put("code", 200);
        return map;
    }

    /**
     * 获取配置信息
     *
     * @return
     */
    private Map<String, String> getConfigMap() {

        //获取配置参数
        Map<String, String> configMap = smsPlatformManager.getConfigMap(this.getPluginId());
        if (StringUtil.isEmpty(configMap.get("signature"))) {
            throw new ServiceException(SystemErrorCode.E931.code(), "短信签名未配置，请联系管理员");
        }
        if (StringUtil.isEmpty(configMap.get("username"))) {
            throw new ServiceException(SystemErrorCode.E931.code(), "用户名称未配置，请联系管理员");
        }
        if (StringUtil.isEmpty(configMap.get("password"))) {
            throw new ServiceException(SystemErrorCode.E931.code(), "用户密码未配置，请联系管理员");
        }
        return configMap;
    }

    /**
     * 获取模板信息
     *
     * @return
     */
    private String getTemplateAuditStatus(String temId) {

        if (StringUtil.isEmpty(temId)) {
            return null;
        }
        String urls = "https://api.mix2.zthysms.com/sms/v2/template/query";
        Map<String, Object> param = new HashMap<>(12);
        //模板名称
        param.put("temId", temId);
        Map map = this.createClient(param, urls);
        //模板不存在  不属于异常
        if (!StringUtil.equals(map.get("code").toString(), "200") && !StringUtil.equals(map.get("code").toString(), "4047")) {
            throw new ServiceException(SystemErrorCode.E931.code(), map.get("msg") + ",具体错误信息描述请参考https://doc.zthysms.com/web/#/1?page_id=11");
        }

        return Objects.isNull(map.get("auditResult")) ? null : map.get("auditResult").toString();
    }

    /**
     * @param param 请求入参
     * @param urls  请求地址
     * @return
     */
    private Map createClient(Map<String, Object> param, String urls) {

        //获取配置参数
        Map<String, String> configMap = smsPlatformManager.getConfigMap(this.getPluginId());
        long tKey = System.currentTimeMillis() / 1000;
        //用户
        param.put("username", configMap.get("username"));
        //密码
        param.put("password", MD5.encode(MD5.encode(configMap.get("password")) + tKey));
        //tKey
        param.put("tKey", tKey + "");

        logger.info("向ztsms.cn发出请求，请求url为：{}", urls);
        // 返回发送结果
        logger.info("助通入参" + JSON.toJSONString(param));
        String result = HttpUtils.doPostWithJson(urls, param);
        return JsonUtil.jsonToObject(result, Map.class);
    }

    @Override
    public void insertRecord(SmsSendVO smsSendVO, Map config) {
        SmsSendRecord record = new SmsSendRecord();
        record.setSignName(String.valueOf(config.get("signature")));
        record.setBizId(smsSendVO.getBizId());
        record.setPhone(smsSendVO.getMobile());
        String content = smsSendVO.getContent();
        //替换遍历变量
        String param = smsSendVO.getTemplateParam();
        if (StringUtil.notEmpty(param)) {
            Map<String, String> map = JSON.parseObject(param, Map.class);
            Set<String> keySet = map.keySet();
            for (String key : keySet) {
                content = content.replace("{" + key + "}", map.get(key));
            }
        }
        record.setSendContent(content);
        record.setSendStatus(SmsRecordStatusEnum.WAIT_RECEIPT.value());
        record.setSendTime(DateUtil.getDateline());
        record.setServiceType(smsSendVO.getServiceType());
        record.setTemplateId(smsSendVO.getTemplateId());
        smsSendRecordManager.add(record);
    }


}
