package com.ywt.outpatient.service.rpc;

import com.google.gson.JsonObject;
import com.ywt.biz.common.enums.TerminalEnum;
import com.ywt.biz.common.util.DateUtil;
import com.ywt.biz.common.util.StringHelper;
import com.ywt.biz.common.util.serializers.JsonSerializer;
import com.ywt.gapi.message.SendTemplateMessageRequest;
import com.ywt.gapi.message.SendTemplateMessageResponse;
import com.ywt.gapi.message.WeChatMessageService;
import com.ywt.outpatient.domain.entity.center.SnsUserInfo;
import com.ywt.outpatient.domain.entity.center.SnsUserInfoRepository;
import com.ywt.outpatient.domain.wechat.Keyword;
import com.ywt.outpatient.service.rpc.common.ServiceResult;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
@SuppressWarnings({"javadoc", "UnusedReturnValue"})
public class WeChatServiceProvider {
    private static Logger logger = LoggerFactory.getLogger(WeChatServiceProvider.class);

    @Autowired
    private SnsUserInfoRepository snsUserInfoRepository;

    @DubboReference
    private WeChatMessageService weChatMessageServiceBlockingStub;

    /**
     * 微信小程序（患者端）模板消息
     *
     * @param openId
     * @param page
     * @param formid
     * @param data
     * @return
     */
    public ServiceResult sendWxAppTplMsg(String openId, String page, String formid, String data) {
        ServiceResult serviceResult = new ServiceResult();
        final String tplId = "TPL_1025";

        try {
            JsonObject object = new JsonObject();
            object.addProperty("appid", formid);// 所需跳转到的小程序appid
            object.addProperty("pagepath", page);// 所需跳转到小程序的具体页面路径
            SendTemplateMessageRequest req = SendTemplateMessageRequest.newBuilder()
                    .setToUser(openId)
                    .setTemplateCode(tplId)
                    .setMiniProgram(object.toString())
                    .setData(data)
                    .build();
            SendTemplateMessageResponse res = weChatMessageServiceBlockingStub.sendTemplateMessage(req);
            if (res.getCode() == 0) {
                return serviceResult.succeed("发送模板消息成功");
            }

            return serviceResult.failed(res.getInfo());
        } catch (Exception e) {
            logger.error("sendWxAppTplMsg(): {}", e.getMessage(), e);
            return serviceResult.failed(String.format("发送模板消息出错，信息：%s", e.getMessage()));
        }
    }

    /**
     * 预约申请提醒
     *
     * @param userId
     * @param patientName
     * @param mobile
     * @param first
     * @param remark
     * @param url
     * @return
     */
    //兼容旧的代码保留此方法，默认接收终端是南方医务通。根据不同的公众号，应该多接收一个`terminal`区分
    @Deprecated
    public ServiceResult sendOfficialTplMsgApplication(
            int userId, String patientName, String mobile, String first, String remark, String url) {
        ServiceResult serviceResult = getOfficialOpenId(userId);

        if (serviceResult.success()) {
            return sendOfficialTplMsgApplication(serviceResult.getData().get("openId").toString(), patientName, mobile,
                    first, remark, url, "TPL_1018");

        }
        return serviceResult;
    }

    /**
     * 发送格式为预约申请的公众号模板消息，需要根据不同终端指定模板代码
     *
     * @param userId
     * @param patientName
     * @param mobile
     * @param first
     * @param remark
     * @param url
     * @param terminal    要接收消息的公众号终端
     * @return
     */
    public ServiceResult sendOfficialTplMsgApplication(int userId, String patientName, String mobile, String first,
                                                       String remark, String url, int terminal, String miniProgram) {
        ServiceResult serviceResult = getOfficialOpenIdByTerminal(userId, terminal);
        String tplCode;
        //根据接收的终端选择模板号
        switch (TerminalEnum.valueOf(terminal)) {
            case PatientWxApp:
            default:
                tplCode = "TPL_1018";
                break;
            case TAI_HE_INTERNET_HOSPITAL_PATIENT_WX_OFFICIAL:
                tplCode = "TPL_1030";
                break;
        }
        logger.info("sendOfficialTplMsgApplication: terminal {}, tplCode {}, userId {}, mini {}", terminal, tplCode,
                userId, miniProgram);
        if (serviceResult.success()) {
            return sendOfficialTplMsgApplication(serviceResult.getData().get("openId").toString(), patientName, mobile,
                    first, remark, url, tplCode, miniProgram);
        } else {
            logger.error("getOfficialOpenIdByTerminal失败:{}", serviceResult.getMsg());
        }
        return serviceResult;
    }

    /**
     * 预约申请提醒
     * <p>
     * 详细内容：
     * {{first.DATA}}
     * 姓名：{{keyword1.DATA}}
     * 电话：{{keyword2.DATA}}
     * 期望日期：{{keyword3.DATA}}
     * {{remark.DATA}}
     *
     * @param openId
     * @param patientName
     * @param mobile
     * @param first
     * @param remark
     * @param url
     * @return
     */
    public ServiceResult sendOfficialTplMsgApplication(String openId, String patientName, String mobile, String first,
                                                       String remark, String url, String tplId) {
        return sendOfficialTplMsgApplication(openId, patientName, mobile, first, remark, url, tplId, "");
    }


    /**
     * 预约申请提醒
     * <p>
     * 详细内容：
     * {{first.DATA}}
     * 姓名：{{keyword1.DATA}}
     * 电话：{{keyword2.DATA}}
     * 期望日期：{{keyword3.DATA}}
     * {{remark.DATA}}
     *
     * @param openId
     * @param patientName
     * @param mobile
     * @param first
     * @param remark
     * @param url
     * @param miniProgram
     * @return
     */
    public ServiceResult sendOfficialTplMsgApplication(String openId, String patientName, String mobile, String first,
                                                       String remark, String url, String tplId, String miniProgram) {
        Map<String, Object> map = new HashMap<>();
        map.put("first", new Keyword(first));
        map.put("keyword1", new Keyword(patientName));
        map.put("keyword2", new Keyword(mobile));
        map.put("keyword3", new Keyword("--"));
        map.put("remark", new Keyword(remark));

        return sendOfficialTemplateMessage(openId, map, tplId, url, miniProgram);
    }

    /**
     * 随访提醒
     *
     * @param userId
     * @param first
     * @param patientName
     * @param createTime
     * @param remark
     * @param url
     * @return
     */
    public ServiceResult sendOfficialTplMsgFollowUp(
            int userId, String first, String patientName, Date createTime, String remark, String url) {
        ServiceResult serviceResult = getOfficialOpenId(userId);
        if (serviceResult.success()) {
            return sendOfficialTplMsgFollowUp(
                    serviceResult.getData().get("openId").toString(), first, patientName, createTime, remark, url);
        }

        return serviceResult;
    }

    /**
     * 随访提醒
     * <p>
     * 详细内容：
     * {{first.DATA}}
     * 姓名：{{keyword1.DATA}}
     * 随访时间：{{keyword2.DATA}}
     * 随访内容：{{keyword3.DATA}}
     * {{remark.DATA}}
     *
     * @param openId
     * @param first
     * @param patientName
     * @param createTime
     * @param remark
     * @param url
     * @return
     */
    public ServiceResult sendOfficialTplMsgFollowUp(String openId, String first, String patientName, Date createTime, String remark, String url) {
        String tplId = "TPL_1021";
        remark = "";

        Map<String, Object> map = new HashMap<>();
        map.put("first", new Keyword(first));
        map.put("keyword1", new Keyword(patientName));
        map.put("keyword2", new Keyword(DateUtil.convertToString(createTime, "yyyy-MM-dd HH:mm")));
        map.put("keyword3", new Keyword("点击查看！"));
        map.put("remark", new Keyword(remark));

        return sendOfficialTemplateMessage(openId, map, tplId, url, "");
    }

    /**
     * 报告生成提醒
     *
     * @param userId
     * @param createTime
     * @param patientName
     * @param doctorName
     * @param title
     * @param url
     * @return
     */
    public ServiceResult sendOfficialTplMsgReport(
            int userId, Date createTime, String patientName, String doctorName, String title, String url) {
        ServiceResult serviceResult = getOfficialOpenId(userId);

        if (serviceResult.success()) {
            return sendOfficialTplMsgReport(serviceResult.getData().get("openId").toString(), createTime, patientName, doctorName, title, url);
        }
        return serviceResult;
    }

    /**
     * 报告生成提醒
     * <p>
     * 详细内容：
     * {{first.DATA}}
     * 申请时间：{{keyword1.DATA}}
     * 患者姓名：{{keyword2.DATA}}
     * 预约专家：{{keyword3.DATA}}
     * {{remark.DATA}}
     *
     * @param openId
     * @param createTime
     * @param patientName
     * @param doctorName
     * @param title
     * @param url
     * @return
     */
    public ServiceResult sendOfficialTplMsgReport(
            String openId, Date createTime, String patientName, String doctorName, String title, String url) {
        String tplId = "TPL_1022";
        String first = "您好，您的远程会诊专家报告生成！";
        String remark = "";

        Map<String, Object> map = new HashMap<>();
        map.put("first", new Keyword(first));
        map.put("keyword1", new Keyword(DateUtil.convertToString(createTime, "yyyy年MM月dd日 HH:mm:ss")));
        map.put("keyword2", new Keyword(patientName));
        map.put("keyword3", new Keyword(String.format("%s %s", doctorName, title)));
        map.put("remark", new Keyword(remark));

        return sendOfficialTemplateMessage(openId, map, tplId, url, "");
    }

    /**
     * 订单支付成功通知
     *
     * @param userId
     * @param first
     * @param orderNo
     * @param amount
     * @param remark
     * @param url
     * @return
     */
    public ServiceResult sendOfficialTplMsgPaid(int userId, String first, String orderNo, int amount, String remark, String url) {
        ServiceResult serviceResult = getOfficialOpenId(userId);

        if (serviceResult.success()) {
            return sendOfficialTplMsgPaid(serviceResult.getData().get("openId").toString(), first, orderNo, amount, remark, url);
        }
        return serviceResult;
    }

    /**
     * 订单支付成功通知
     * <p>
     * 详细内容：
     * {{first.DATA}}
     * 订单号：{{keyword1.DATA}}
     * 就诊人姓名：{{keyword2.DATA}}
     * 就诊时间：{{keyword3.DATA}}
     * {{remark.DATA}}
     *
     * @param openId
     * @param first
     * @param orderNo
     * @param amount
     * @param remark
     * @param url
     * @return
     */
    public ServiceResult sendOfficialTplMsgPaid(String openId, String first, String orderNo, int amount, String remark, String url) {
        String tplId = "TPL_1023";
        remark = "3个工作日内将收到远程会诊专家报告！";

        Map<String, Object> map = new HashMap<>();
        map.put("first", new Keyword(first));
        map.put("keyword1", new Keyword(orderNo));
        map.put("keyword2", new Keyword("--"));
        map.put("keyword3", new Keyword(String.format("%.2f元", amount / 100d)));
        map.put("remark", new Keyword(remark));

        return sendOfficialTemplateMessage(openId, map, tplId, url, "");
    }


    /**
     * 医生回复通知
     *
     * @param userId
     * @param first
     * @param doctorName
     * @param date
     * @param remark
     * @param url
     * @return
     */
    public ServiceResult sendOfficialTplMsgReply(int userId, String first, String doctorName, Date date, String remark, String url) {
        ServiceResult serviceResult = getOfficialOpenId(userId);

        if (serviceResult.success()) {
            sendOfficialTplMsgReply(serviceResult.getData().get("openId").toString(), first, doctorName, date, remark, url);
        }

        return serviceResult;
    }

    /**
     * 医生回复通知
     * 详细内容：
     * <p>
     * {{first.DATA}}
     * 服务医生：{{keyword1.DATA}}
     * 回复时间：{{keyword2.DATA}}
     * {{remark.DATA}}
     *
     * @param openId
     * @param first
     * @param doctorName
     * @param date
     * @param remark
     * @param url
     * @return
     */
    public ServiceResult sendOfficialTplMsgReply(String openId, String first, String doctorName, Date date, String remark, String url) {
        String tplId = "TPL_1024";
        first = String.format("%s医生有回复", doctorName);
        remark = "请点击查看";

        Map<String, Object> map = new HashMap<>();
        map.put("first", new Keyword(first));
        map.put("keyword1", new Keyword(doctorName));
        map.put("keyword2", new Keyword(DateUtil.convertToString(date, "yyyy-MM-dd")));
        map.put("remark", new Keyword(remark));

        return sendOfficialTemplateMessage(openId, map, tplId, url, "");
    }

    /**
     * 咨询回复提醒
     *
     * @param userId
     * @param first
     * @param doctorName
     * @param content
     * @param url
     * @return
     */
    public ServiceResult sendOfficialTplMsgConsult(int userId, String first, String doctorName, String content, String url) {
        ServiceResult serviceResult = getOfficialOpenId(userId);

        if (serviceResult.success()) {
            sendOfficialTplMsgConsult(serviceResult.getData().get("openId").toString(), first, doctorName, content, url);
        }

        return serviceResult;
    }


    /**
     * 咨询回复提醒
     * <p>
     * 详细内容：
     * {{first.DATA}}
     * 咨询内容：{{keyword1.DATA}}
     * 回复内容：{{keyword2.DATA}}
     * 医生名：{{keyword3.DATA}}
     * {{remark.DATA}}
     *
     * @param openId
     * @param first
     * @param doctorName
     * @param content
     * @param url
     * @return
     */
    public ServiceResult sendOfficialTplMsgConsult(String openId, String first, String doctorName, String content, String url) {
        String tplId = "TPL_1016";
        first = String.format("您咨询的%s医生已接诊", doctorName);
        String remark = "";

        Map<String, Object> map = new HashMap<>();
        map.put("first", new Keyword(first));
        map.put("keyword1", new Keyword(content));
        map.put("keyword2", new Keyword("请点击查看！"));
        map.put("keyword3", new Keyword(doctorName));
        map.put("remark", new Keyword(remark));

        return sendOfficialTemplateMessage(openId, map, tplId, url, "");
    }

    /**
     * 获取南方医务通公众号用户openid
     *
     * @param userId
     * @return
     */
    private ServiceResult getOfficialOpenId(int userId) {
        ServiceResult serviceResult = new ServiceResult();
        SnsUserInfo snsUserInfo = snsUserInfoRepository.getSnsUserInfoByUserId(userId, TerminalEnum.PatientWxOfficial.getValue());
//        SnsUser snsUser = snsUserRepository.getSnsUserByUserId(userId);

        if (snsUserInfo == null || StringHelper.isNullOrWhiteSpace(snsUserInfo.getOpenId())) {
            return serviceResult.failed("公众号用户信息不存在");
        }

        Map<String, Object> map = new HashMap<>();
        map.put("openId", snsUserInfo.getOpenId());
        return serviceResult.succeed("处理成功", map);
    }


    /**
     * 根据terminal 和 userId获取openId
     *
     * @param userId
     * @param terminal
     * @return
     */
    private ServiceResult getOfficialOpenIdByTerminal(int userId, int terminal) {
        ServiceResult serviceResult = new ServiceResult();
        SnsUserInfo snsUserInfo = snsUserInfoRepository.getSnsUserInfoByUserId(userId, terminal);
        if (snsUserInfo == null || StringHelper.isNullOrWhiteSpace(snsUserInfo.getOpenId())) {
            return serviceResult.failed("公众号用户信息不存在");
        }

        Map<String, Object> map = new HashMap<>();
        map.put("openId", snsUserInfo.getOpenId());
        return serviceResult.succeed("处理成功", map);
    }


    /**
     * 发送公众号模板消息
     *
     * @param openId  微信公众号openid
     * @param tplCode 模板Id
     * @param url     跳转链接
     * @param data    模板参数
     * @return
     */
    public ServiceResult sendOfficialTemplateMessage(String openId, Map<String, Object> data, String tplCode, String url, String miniProgram) {
        ServiceResult serviceResult = new ServiceResult();

        if (StringHelper.isNullOrEmpty(tplCode)) {
            return serviceResult.failed("模板消息编号有误！");
        }

        try {
            SendTemplateMessageRequest req = SendTemplateMessageRequest.newBuilder()
                    .setData(JsonSerializer.toJson(data))
                    .setTemplateCode(tplCode)
                    .setUrl(url)
                    .setMiniProgram(miniProgram)
                    .setToUser(openId)
                    .build();
            SendTemplateMessageResponse res = weChatMessageServiceBlockingStub.sendTemplateMessage(req);

            if (res.getCode() == 0) {
                return serviceResult.succeed("发送成功");
            }

            return serviceResult.failed(res.getInfo());
        } catch (Exception e) {
            logger.error("sendOfficialTemplateMessage({}, {}, {}, {}, {}): {}", openId, tplCode, url, data, miniProgram,
                    e.getMessage(), e);
            return serviceResult.failed(String.format("发送模板消息出错，信息：%s", e.getMessage()));
        }
    }
}
