package com.xinelu.manage.service.messagepush.Impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.xinelu.common.config.AppletChatConfig;
import com.xinelu.common.config.AppletPageConfig;
import com.xinelu.common.constant.Constants;
import com.xinelu.common.entity.AppletAccessToken;
import com.xinelu.common.entity.MessageValueEntity;
import com.xinelu.common.enums.AppletSubscriptionMessageEnum;
import com.xinelu.common.enums.CouponTypeEnum;
import com.xinelu.common.enums.MessageTemplateType;
import com.xinelu.common.enums.MessageTypePath;
import com.xinelu.common.enums.SettingsTypeEnum;
import com.xinelu.common.enums.SubscribeStatusEnum;
import com.xinelu.common.utils.AppletChatUtil;
import com.xinelu.common.utils.http.HttpUtils;
import com.xinelu.common.utils.map.MapUtil;
import com.xinelu.common.utils.uuid.IdUtils;
import com.xinelu.manage.domain.subscribemessagerecord.SubscribeMessageRecord;
import com.xinelu.manage.domain.systemsettingsinfo.SystemSettingsInfo;
import com.xinelu.manage.dto.chatrecord.ChatRecordDTO;
import com.xinelu.manage.dto.messagepush.FDMessagePushDto;
import com.xinelu.manage.dto.messagepush.FDWxMegDto;
import com.xinelu.manage.dto.messagepush.TemplateData;
import com.xinelu.manage.mapper.subscribemessagerecord.SubscribeMessageRecordMapper;
import com.xinelu.manage.mapper.systemsettingsinfo.SystemSettingsInfoMapper;
import com.xinelu.manage.service.chatrecord.IChatRecordService;
import com.xinelu.manage.service.messagepush.MessagePushService;
import com.xinelu.manage.service.patientinfo.IPatientInfoService;
import com.xinelu.manage.vo.patientcouponreceive.PatientCouponReceiveInfoVO;
import com.xinelu.manage.vo.patientinfo.PatientInfoVO;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

/**
 * @Description 消息推送实现层
 * @Author zh
 * @Date 2023-03-17
 */
@Slf4j
@Service
public class MessagePushServiceImpl implements MessagePushService {

    @Resource
    private AppletChatConfig appletChatConfig;
    @Resource
    private SubscribeMessageRecordMapper subscribeMessageRecordMapper;
    @Resource
    private SystemSettingsInfoMapper systemSettingsInfoMapper;
    @Resource
    private AppletPageConfig appletPageConfig;
    @Resource
    private IPatientInfoService patientInfoService;
    @Resource
    private IChatRecordService chatRecordService;

    /**
     * 微信消息推送url
     */
    private static final String MESSAGE_PUSH_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=";

    /**
     * 签到消息推送
     *
     * @param patientId 用户ID
     * @param days      天数
     */
    @Override
    @Async("asyncThreadServiceExecutor")
    public void integralMessage(Long patientId, Integer days) {
        //获取AppletAccessToken的值
        AppletAccessToken appletAccessToken = AppletChatUtil.getAppletAccessToken(appletChatConfig.getAppletId(), appletChatConfig.getSecret());
        if (Objects.isNull(appletAccessToken)) {
            log.error("获取微信小程序accessToken信息失败！");
            return;
        }
        if (Objects.nonNull(appletAccessToken.getErrcode()) && appletAccessToken.getErrcode() != AppletSubscriptionMessageEnum.SUCCESS_ERRCODE.getValue()) {
            log.error("获取微信小程序accessToken信息失败，失败信息为：" + appletAccessToken.getErrmsg(), 201);
            return;
        }
        if (StringUtils.isBlank(appletAccessToken.getAccessToken())) {
            log.error("accessToken信息为空！");
            return;
        }
        //获取用户信息、订阅消息记录、规则信息
        SubscribeMessageRecord subscribeMessageRecord = subscribeMessageRecordMapper.selectSubscribeMessageRecordByPatientId(patientId, null, appletChatConfig.getSignTemplateId());
        if (Objects.isNull(subscribeMessageRecord) || StringUtils.isBlank(subscribeMessageRecord.getOpenid()) || StringUtils.isBlank(subscribeMessageRecord.getSubscribeStatus()) || !SubscribeStatusEnum.ACCEPT.getInfo().equals(subscribeMessageRecord.getSubscribeStatus())) {
            return;
        }
        SystemSettingsInfo systemSettingsInfo = systemSettingsInfoMapper.getSystemSettingsInfoByType(SettingsTypeEnum.SIGN_IN_RULE.getInfo());
        if (Objects.isNull(systemSettingsInfo) || Objects.isNull(systemSettingsInfo.getIntegralCount()) || Objects.isNull(systemSettingsInfo.getTotalSignInDays())) {
            return;
        }
        this.sendIntegralMessage(appletAccessToken, systemSettingsInfo, subscribeMessageRecord, days);
    }


    /**
     * 签到消息推送
     *
     * @param appletAccessToken      令牌
     * @param systemSettingsInfo     规则信息
     * @param subscribeMessageRecord 订阅消息记录
     * @param days                   天数
     */
    public void sendIntegralMessage(AppletAccessToken appletAccessToken, SystemSettingsInfo systemSettingsInfo, SubscribeMessageRecord subscribeMessageRecord, Integer days) {
        //模板参数、用户openid、推送消息模板id
        Map<String, Object> paramsMap = new LinkedHashMap<>();
        paramsMap.put("touser", subscribeMessageRecord.getOpenid());
        paramsMap.put("template_id", appletChatConfig.getSignTemplateId());
        paramsMap.put("page", appletPageConfig.getIntegralPageUrl());
        //模板内容
        Map<String, MessageValueEntity> messageValueEntityMap = new LinkedHashMap<>();
        messageValueEntityMap.put("thing1", new MessageValueEntity("每日签到"));
        //如果签到天数满足规则
        if (days.equals(systemSettingsInfo.getTotalSignInDays())) {
            messageValueEntityMap.put("thing2", new MessageValueEntity("今日已签到，已领取" + systemSettingsInfo.getIntegralCount() + "积分"));
        } else {
            messageValueEntityMap.put("thing2", new MessageValueEntity(LocalDate.now().getYear() + "年" + LocalDate.now().getMonthValue() + "月" + LocalDate.now().getDayOfMonth() + "日签到成功"));
        }
        messageValueEntityMap.put("thing3", new MessageValueEntity("累计签到" + systemSettingsInfo.getTotalSignInDays() + "天，可获得" + systemSettingsInfo.getIntegralCount() + "积分"));
        paramsMap.put("data", messageValueEntityMap);
        //发送
        this.sendPosts(appletAccessToken, paramsMap);
    }

    /**
     * 完善信息优惠券领取与优惠券领取共用异步发送订阅信息
     *
     * @param subscribeMessageRecord 微信小程序订阅消息记录表
     * @param couponReceive          用户优惠券
     **/
    @Override
    @Async("asyncThreadServiceExecutor")
    public void messageCouponReceiveThread(SubscribeMessageRecord subscribeMessageRecord, PatientCouponReceiveInfoVO couponReceive) {
        if (StringUtils.equals(CouponTypeEnum.FULL_REDUCTION_COUPON.getInfo(), couponReceive.getCouponType())) {
            couponReceive.setCouponType("满减券");
        }
        if (StringUtils.equals(CouponTypeEnum.CASH_COUPON.getInfo(), couponReceive.getCouponType())) {
            couponReceive.setCouponType("代金券");
        }
        if (StringUtils.equals(CouponTypeEnum.EXCHANGE_COUPON.getInfo(), couponReceive.getCouponType())) {
            couponReceive.setCouponType("兑换券");
        }
        if (StringUtils.equals(CouponTypeEnum.DISCOUNT_COUPON.getInfo(), couponReceive.getCouponType())) {
            couponReceive.setCouponType("折扣卷");
        }
        //获取AppletAccessToken的值
        AppletAccessToken appletAccessToken = AppletChatUtil.getAppletAccessToken(appletChatConfig.getAppletId(), appletChatConfig.getSecret());
        if (Objects.isNull(appletAccessToken)) {
            log.error("获取微信小程序accessToken信息失败！");
        }
        if (Objects.nonNull(appletAccessToken.getErrcode()) && appletAccessToken.getErrcode() != AppletSubscriptionMessageEnum.SUCCESS_ERRCODE.getValue()) {
            log.error("获取微信小程序accessToken信息失败，失败信息为：" + appletAccessToken.getErrmsg(), 201);
        }
        if (StringUtils.isBlank(appletAccessToken.getAccessToken())) {
            log.error("accessToken信息为空！");
        }
        //构建微信小程序消息推送参数
        Map<String, Object> paramsMap = new LinkedHashMap<>();
        paramsMap.put("template_id", StringUtils.isBlank(subscribeMessageRecord.getTemplateId()) ? "" : subscribeMessageRecord.getTemplateId());
        paramsMap.put("page", appletPageConfig.getCouponPageUrl());
        paramsMap.put("touser", StringUtils.isBlank(subscribeMessageRecord.getOpenid()) ? "" : subscribeMessageRecord.getOpenid());
        paramsMap.put("lang", "zh_CN");
        //构建微信小程序消息推送内容参数
        Map<String, MessageValueEntity> amountParamMap = new HashMap<>();
        //优惠券名称
        amountParamMap.put("thing3", new MessageValueEntity(StringUtils.isBlank(couponReceive.getCouponTitle()) ? "" : couponReceive.getCouponTitle()));
        //优惠券金额
        BigDecimal couponPrice = Objects.isNull(couponReceive.getCouponPrice()) ? BigDecimal.ZERO : couponReceive.getCouponPrice();
        amountParamMap.put("amount2", new MessageValueEntity(couponPrice + "元"));
        //优惠券类型
        amountParamMap.put("thing4", new MessageValueEntity(StringUtils.isBlank(couponReceive.getCouponType()) ? "" : couponReceive.getCouponType()));
        //发布时间
        amountParamMap.put("time6", new MessageValueEntity(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(couponReceive.getReceiveTime())));
        //温馨提示
        amountParamMap.put("thing1", new MessageValueEntity("优惠券来啦，您可进入小程序进行使用"));
        paramsMap.put("data", amountParamMap);
        //发送
        this.sendPosts(appletAccessToken, paramsMap);
    }

    /**
     * 发送
     *
     * @param appletAccessToken 令牌
     * @param paramsMap         模板
     **/
    @Override
    public void sendPosts(AppletAccessToken appletAccessToken, Map<String, Object> paramsMap) {
        //拼接请求地址并发送
        String messageUrl = MESSAGE_PUSH_URL + appletAccessToken.getAccessToken();
        String param = JSON.toJSONString(paramsMap);
        String result = HttpUtils.sendPostJson(messageUrl, param);
        //返回参数映射
        AppletAccessToken errCode = JSON.parseObject(result, AppletAccessToken.class);
        if (Objects.nonNull(errCode) && Objects.nonNull(errCode.getErrcode())) {
            switch (errCode.getErrcode()) {
                case Constants.SUCCESS_ERRCODE:
                    log.info("发送消息成功！");
                    break;
                case Constants.INVALID_CREDENTIAL_ACCESS_TOKEN_ISINVALID_OR_NOT_LATEST:
                    log.error("取 access_token 时 AppSecret 错误，或者 access_token 无效！");
                    break;
                case Constants.INVALID_OPENID:
                    log.error("不合法的 OpenId！");
                    break;
                case Constants.INVALID_ACCESS_TOKEN:
                    log.error("合法的 access_token！");
                    break;
                case Constants.INVALID_TEMPLATE_ID:
                    log.error("不合法的 template_id！");
                    break;
                case Constants.ARGUMENT_INVALID:
                    log.error("参数无效！{}", result);
                    break;
                case Constants.DENY_SUBSCRIPTION:
                    log.error("用户拒接订阅！");
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * @return void
     * @Author mengkuiliang
     * @Description 家医申请审批结果订阅消息推送
     * @Date 2023-10-18 018 14:03
     * @Param [appletAccessToken, paramsMap, busType]
     **/
    @Override
    @Async("asyncThreadServiceExecutor")
    public void fdApprovePush(JSONObject body) {
        if (body.containsKey("cardNo") && !StringUtils.isBlank(body.getString("cardNo"))) {
            PatientInfoVO patientInfo = patientInfoService.selectPatientInfoByCardNo(body.getString("cardNo"));
            if (patientInfo == null) {
                log.error("接收方未注册 {}", body.getString("cardNo"));
            }
            AppletAccessToken appletAccessToken = AppletChatUtil.getAppletAccessToken(appletChatConfig.getAppletId(), appletChatConfig.getSecret());
            if (Objects.isNull(appletAccessToken)) {
                log.error("获取微信小程序accessToken信息失败！");
            }
            if (Objects.nonNull(appletAccessToken.getErrcode()) && appletAccessToken.getErrcode() != AppletSubscriptionMessageEnum.SUCCESS_ERRCODE.getValue()) {
                log.error("获取微信小程序accessToken信息失败，失败信息为：" + appletAccessToken.getErrmsg(), 201);
            }
            if (StringUtils.isBlank(appletAccessToken.getAccessToken())) {
                log.error("accessToken信息为空！");
            }
            ChatRecordDTO chatRecord = new ChatRecordDTO();
            // 查询居民注册信息
            if(!body.containsKey("patientId") || body.getLong("patientId") == null) {
                chatRecord.setRecipientId(patientInfo.getId());
            } else {
                chatRecord.setRecipientId(body.getLong("patientId"));
            }

            //模板内容
            Map<String, MessageValueEntity> messageValueEntityMap = new LinkedHashMap<>();
            switch (body.getString("busType")) {
                // 申请
                case "10":
                    messageValueEntityMap.put("name2", new MessageValueEntity(body.getString("receiveName")));
                    messageValueEntityMap.put("thing6", new MessageValueEntity(body.getString("text1")));
                    messageValueEntityMap.put("thing5", new MessageValueEntity(body.getString("text2")));
                    messageValueEntityMap.put("thing8", new MessageValueEntity(body.getString("sendTime")));
                    messageValueEntityMap.put("thing9", new MessageValueEntity(body.getString("sendContent")));
                    chatRecord.setContent(body.getString("receiveName") + "在" + body.getString("text1") + "提交服务申请，服务内容：" + (body.containsKey("text3") && !StringUtils.isBlank(body.getString("text3"))? body.getString("text3"): body.getString("text2")));
                    chatRecord.setRecipientName(body.getString("receiveName"));
                    chatRecord.setSenderName(body.getString("text1"));
                    break;
                // 用药
                case "9":
                    messageValueEntityMap.put("thing1", new MessageValueEntity(body.getString("text1")));
                    messageValueEntityMap.put("thing2", new MessageValueEntity(body.getString("text2")));
                    messageValueEntityMap.put("time3", new MessageValueEntity(body.getString("sendTime")));
                    messageValueEntityMap.put("thing4", new MessageValueEntity(body.getString("sendContent")));
                    chatRecord.setContent(body.getString("sendContent"));
                    chatRecord.setRecipientName(body.getString("receiveName"));
                    chatRecord.setSenderName(body.getString("senderName"));
                    break;
                // 默认
                default:
                    messageValueEntityMap.put("thing1", new MessageValueEntity(body.getString("senderName")));
                    messageValueEntityMap.put("time2", new MessageValueEntity(body.getString("sendTime")));
                    messageValueEntityMap.put("thing3", new MessageValueEntity(body.getString("sendContent")));
					if (body.containsKey("contentId")) {
						chatRecord.setContentId(body.getString("contentId"));
					}
	                if (body.containsKey("sourceType")) {
		                chatRecord.setSourceType(body.getString("sourceType"));
	                }
                    chatRecord.setContent(body.getString("sendContent"));
                    chatRecord.setRecipientName(body.getString("receiveName"));
                    chatRecord.setSenderName(body.getString("senderName"));
                    break;
            }

            Map<String, Object> paramsMap = new HashMap<>();
            paramsMap.put("touser", body.getString("openid"));
            paramsMap.put("template_id", MessageTemplateType.getFolllowupTypeByCode(body.getString("busType")).getTemplateId());

			if (StringUtils.isNotBlank(body.getString("sourceType"))) {
				switch (body.getString("sourceType")) {
					case "1": // 1：筛查页面
						paramsMap.put("page", appletPageConfig.getScreeningRecordPageUrl());
						break;
					case "2": // 2：订单页面
						paramsMap.put("page", appletPageConfig.getAppointOrderPageUrl());
						break;
					default:
						paramsMap.put("page", appletPageConfig.getIntegralPageUrl());
						break;
				}
			}
            paramsMap.put("data", messageValueEntityMap);
            //发送
            this.sendPosts(appletAccessToken, paramsMap);

            // 记录通知消息
            if(body.containsKey("messageCategory") && !StringUtils.isBlank(body.getString("messageCategory"))) {
                chatRecord.setMessageType("1");
                chatRecord.setTitle(body.getString("sendTitle"));
                chatRecord.setMessageNo(IdUtils.fastSimpleUUID());
                chatRecord.setSendTime(new Date());
                chatRecord.setMessageCategory(body.getString("messageCategory"));
                chatRecordService.insertChatRecord(chatRecord);
            }
        }
    }

    /**
     * @return void
     * @Author mengkuiliang
     * @Description 家医推送订阅消息
     * @Date 2023-10-19 019 10:20
     * @Param [body]
     **/
    @Override
    @Async("asyncThreadServiceExecutor")
    public void FdPushMessage(JSONObject req) throws Exception {
        log.info("订阅消息-请求参数：{}", JSON.toJSONString(req));
        FDMessagePushDto body = JSONObject.parseObject(req.toJSONString()).toJavaObject(FDMessagePushDto.class);
        if (!StringUtils.isBlank(body.getRecipientIdentity())) {
            PatientInfoVO patientInfo = patientInfoService.selectPatientInfoByCardNo(body.getRecipientIdentity());
            if (patientInfo == null) {
                log.error("接收方未注册 {}", body.getRecipientIdentity());
            }
            AppletAccessToken appletAccessToken = AppletChatUtil.getAppletAccessToken(appletChatConfig.getAppletId(), appletChatConfig.getSecret());
            if (Objects.isNull(appletAccessToken)) {
                log.error("获取微信小程序accessToken信息失败！");
            }
            if (Objects.nonNull(appletAccessToken.getErrcode()) && appletAccessToken.getErrcode() != AppletSubscriptionMessageEnum.SUCCESS_ERRCODE.getValue()) {
                log.error("获取微信小程序accessToken信息失败，失败信息为：" + appletAccessToken.getErrmsg(), 201);
            }
            if (StringUtils.isBlank(appletAccessToken.getAccessToken())) {
                log.error("accessToken信息为空！");
            }
            ChatRecordDTO chatRecord = new ChatRecordDTO();
            // 查询居民注册信息
            if(!req.containsKey("patientId") || req.getLong("patientId") == null) {
                chatRecord.setRecipientId(patientInfo.getId());
            } else {
                chatRecord.setRecipientId(req.getLong("patientId"));
            }

            FDWxMegDto wxMegDto = new FDWxMegDto();
            wxMegDto.setTouser(patientInfo.getBindOpenid());
            wxMegDto.setTemplate_id(MessageTemplateType.getFolllowupTypeByCode(body.getTemplateType()).getTemplateId());
            Map<String, TemplateData> meg = new HashMap<>();
            switch (body.getTemplateType()) {
                // 用药提醒
                case "9":
                    meg.put("thing1", new TemplateData(body.getDrugName()));
                    meg.put("thing2", new TemplateData(body.getDrugUsage()));
                    meg.put("time3", new TemplateData(body.getHandleDate()));
                    meg.put("thing4", new TemplateData((!StringUtils.isBlank(body.getRecipientName())? body.getRecipientName(): "") + body.getContent()));
                    break;
                // 筛查预约成功
                case "10":
                    meg.put("name2", new TemplateData(body.getRecipientName()));
                    meg.put("thing5", new TemplateData(body.getApplyContent()));
                    meg.put("thing6", new TemplateData(body.getHospitalName()));
                    meg.put("thing8", new TemplateData(body.getHandleDate()));
                    meg.put("thing9", new TemplateData(body.getContent()));
                    break;
                // 家庭医生消息通知
                default:
                    meg.put("thing1", new TemplateData(body.getDoctorName()));
                    meg.put("time2", new TemplateData(body.getSendTime()));
                    meg.put("thing3", new TemplateData(body.getContent()));
                    break;
            }
            wxMegDto.setPage(MessageTypePath.getPathByType(body.getMessageType()).getPath() + (StringUtils.isBlank(body.getContentId()) ? "" : body.getContentId()));
            wxMegDto.setData(meg);

            //发送
            this.sendPosts(appletAccessToken, MapUtil.object2Map(wxMegDto));

            // 记录通知消息
            if(req.containsKey("messageCategory") && !StringUtils.isBlank(req.getString("messageCategory")) && req.containsKey("chatRecord")) {
                ChatRecordDTO chat = req.getJSONObject("chatRecord").toJavaObject(ChatRecordDTO.class);
                if(chat != null) {
                    chatRecord.setMessageType("1");
                    chatRecord.setMessageNo(IdUtils.fastSimpleUUID());
                    chatRecord.setSendTime(new Date());
                    chatRecord.setTitle(chat.getTitle());
                    chatRecord.setContent(chat.getContent());
                    chatRecord.setSenderName(chat.getSenderName());
                    chatRecord.setRecipientName(patientInfo.getPatientName());
                    chatRecord.setMessageCategory(req.getString("messageCategory"));
                    chatRecordService.insertChatRecord(chatRecord);
                }
            }
        }
    }

    /**
     * 配置消息模版请求参数
     */
    private FDWxMegDto getTemplate(FDMessagePushDto message, String openid) {
        FDWxMegDto wxMegDto = new FDWxMegDto();
        wxMegDto.setTouser(openid);
        wxMegDto.setTemplate_id(MessageTemplateType.getFolllowupTypeByCode(message.getTemplateType()).getTemplateId());
        Map<String, TemplateData> meg = new HashMap<>();
        switch (message.getTemplateType()) {
            // 用药提醒
            case "9":
                meg.put("thing1", new TemplateData(message.getDrugName()));
                meg.put("thing2", new TemplateData(message.getDrugUsage()));
                meg.put("time3", new TemplateData(message.getHandleDate()));
                meg.put("thing4", new TemplateData((!StringUtils.isBlank(message.getRecipientName())? message.getRecipientName(): "") + message.getContent()));
                break;
            // 筛查预约成功
            case "10":
                meg.put("name2", new TemplateData(message.getRecipientName()));
                meg.put("thing5", new TemplateData(message.getApplyContent()));
                meg.put("thing6", new TemplateData(message.getHospitalName()));
                meg.put("thing8", new TemplateData(message.getHandleDate()));
                meg.put("thing9", new TemplateData(message.getContent()));
                break;
            // 家庭医生消息通知
            default:
                meg.put("thing1", new TemplateData(message.getDoctorName()));
                meg.put("time2", new TemplateData(message.getSendTime()));
                meg.put("thing3", new TemplateData(message.getContent()));
                break;
        }
        wxMegDto.setPage(MessageTypePath.getPathByType(message.getMessageType()).getPath() + (StringUtils.isBlank(message.getContentId()) ? "" : message.getContentId()));
        wxMegDto.setData(meg);
        return wxMegDto;
    }
}
