package com.zbkj.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.zbkj.common.config.SmsConfig;
import com.zbkj.common.constants.Constants;
import com.zbkj.common.constants.NotifyConstants;
import com.zbkj.common.constants.SmsConstants;
import com.zbkj.common.dto.HuaWeiSmsContent;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.sms.SmsTemplate;
import com.zbkj.common.model.system.SystemNotification;
import com.zbkj.common.utils.*;
import com.zbkj.service.service.SmsService;
import com.zbkj.service.service.SmsTemplateService;
import com.zbkj.service.service.SystemConfigService;
import com.zbkj.service.service.SystemNotificationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * huawei sms service实现类
 */
@Service
@Primary
public class HuaweiSmsServiceImpl implements SmsService {

    private static final Logger logger = LoggerFactory.getLogger(HuaweiSmsServiceImpl.class);

    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private SmsTemplateService smsTemplateService;
    @Autowired
    private SystemNotificationService systemNotificationService;


    /**
     * 发短信之前的校验
     */
    private void beforeSendMessage() {
        // do nothing
    }

    /**
     * 发送公共验证码
     *
     * @param phone 手机号
     * @return Boolean
     * 1.校验后台是否配置一号通
     * 2.一号通是否剩余短信条数
     * 3.发送短信
     */
    @Override
    public Boolean sendCommonCode(String phone) {
        ValidateFormUtil.isPhone(phone, "手机号码错误");
//        beforeSendMessage();
        DateTime dateTime = DateUtil.date();
        String clientIp = RequestUtil.getClientIp();
        beforeSendCommonCodeCheck(phone, clientIp, dateTime);
        //获取短信验证码过期时间
        String codeExpireStr = systemConfigService.getValueByKey(SmsConstants.CONFIG_KEY_SMS_CODE_EXPIRE);
        if (StrUtil.isBlank(codeExpireStr) || Integer.parseInt(codeExpireStr) == 0) {
            codeExpireStr = Constants.NUM_FIVE + "";// 默认5分钟过期
        }
        Integer code = CrmebUtil.randomCount(111111, 999999);

        Boolean success = false;
        if (SmsConfig.isSendSwitch()) {
            List<String> params = new ArrayList<>();
            params.add("本次验证码：" + code + " " + codeExpireStr + "分钟后过期");
            HuaWeiSmsContent huaWeiSmsContent = new HuaWeiSmsContent();
            huaWeiSmsContent.setMobile(phone);
            huaWeiSmsContent.setParams(JSONArray.toJSONString(params));
            huaWeiSmsContent.setSmsCode(SmsConfig.getCode());
            success = MessageUtil.sendHuaWeiSMS(huaWeiSmsContent);
            if (!success) {
                throw new CrmebException("发送短信失败，请联系后台管理员");
            }
        } else {
            logger.info("SmsConfig.isSendSwitch短信开关没有打开，本次短信发送取消");
        }


        // 将验证码存入redis
        redisUtil.set(SmsConstants.SMS_VALIDATE_PHONE + phone, code, Long.valueOf(codeExpireStr), TimeUnit.MINUTES);
        redisUtil.set(SmsConstants.SMS_VALIDATE_PHONE_NUM + phone, 1, 60L);
//        redisUtil.incrAndCreate(StrUtil.format(SmsConstants.SMS_PHONE_HOUR_NUM, phone, dateTime.toDateStr() + dateTime.hour(true)));
//        redisUtil.incrAndCreate(StrUtil.format(SmsConstants.SMS_PHONE_DAY_NUM, phone, dateTime.toDateStr()));
//        redisUtil.incrAndCreate(StrUtil.format(SmsConstants.SMS_IP_HOUR_NUM, clientIp, dateTime.toDateStr() + dateTime.hour(true)));
        return success;
    }

    /**
     * 发送公共验证码前校验
     *
     * @param phone    手机号
     * @param clientIp IP
     * @param dateTime 时间
     */
    private void beforeSendCommonCodeCheck(String phone, String clientIp, DateTime dateTime) {
        if (redisUtil.exists(SmsConstants.SMS_VALIDATE_PHONE_NUM + phone)) {
            throw new CrmebException("您的短信发送过于频繁，请稍后再试");
        }
//        Object phoneHourNumObject = redisUtil.get(StrUtil.format(SmsConstants.SMS_PHONE_HOUR_NUM, phone, dateTime.toDateStr() + dateTime.hour(true)));
//        if (ObjectUtil.isNotNull(phoneHourNumObject)) {
//            Integer phoneHourNum = (Integer) phoneHourNumObject;
//            if (phoneHourNum >= 7) {
//                throw new CrmebException(StrUtil.format("同一手机号1小时最多发送{}条短信，您的短信发送过于频繁，请稍后再试", 7));
//            }
//        }
//        Object phoneDayNumObject = redisUtil.get(StrUtil.format(SmsConstants.SMS_PHONE_DAY_NUM, phone, DateUtil.date().toDateStr()));
//        if (ObjectUtil.isNotNull(phoneDayNumObject)) {
//            Integer phoneDayNum = (Integer) phoneDayNumObject;
//            if (phoneDayNum >= 24) {
//                throw new CrmebException(StrUtil.format("同一手机号一天最多发送{}条短信，您的短信发送过于频繁，请明天再试", 24));
//            }
//        }
//        Object ipHourNumObject = redisUtil.get(StrUtil.format(SmsConstants.SMS_IP_HOUR_NUM, clientIp, dateTime.toDateStr() + dateTime.hour(true)));
//        if (ObjectUtil.isNotNull(ipHourNumObject)) {
//            Integer ipHourNum = (Integer) ipHourNumObject;
//            if (ipHourNum >= 10) {
//                throw new CrmebException(StrUtil.format("同一IP地址1小时最多发送{}条短信，您的短信发送过于频繁，请稍后再试", 10));
//            }
//        }
    }

    /**
     * 发送支付成功短信
     *
     * @param phone    手机号
     * @param orderNo  订单编号
     * @param payPrice 支付金额
     * @return Boolean
     */
    @Override
    public Boolean sendPaySuccess(String phone, String orderNo, BigDecimal payPrice) {
        SmsTemplate temp;
        try {
            beforeSendMessage();
            temp = getSmsTemp(NotifyConstants.PAY_SUCCESS_MARK);
        } catch (Exception e) {
            logger.error("发送短信失败，{}", e.getMessage());
            return false;
        }

        HashMap<String, Object> map = CollUtil.newHashMap();
        map.put("pay_price", payPrice);
        map.put("order_id", orderNo);
        String message = PlaceHolderReplaceUtils.replaceWithMap(temp.getContent(), map);
        return sendHuaweiSms(message, phone);
    }

    @Override
    public Boolean sendMessage(String phone, String message) {
        return sendHuaweiSms(message, phone);
    }

    public Boolean sendHuaweiSms(String message, String phone) {
        Boolean success = false;
        if (SmsConfig.isSendSwitch()) {
            List<String> params = new ArrayList<>();
            params.add(message);
            HuaWeiSmsContent huaWeiSmsContent = new HuaWeiSmsContent();
            huaWeiSmsContent.setMobile(phone);
            huaWeiSmsContent.setParams(JSONArray.toJSONString(params));
            huaWeiSmsContent.setSmsCode(SmsConfig.getCode());
            success = MessageUtil.sendHuaWeiSMS(huaWeiSmsContent);
            if (!success) {
                throw new CrmebException("发送短信失败，请联系后台管理员");
            }
        } else {
            logger.info("SmsConfig.isSendSwitch短信开关没有打开，本次短信发送取消");
        }
        return success;
    }

    /**
     * 发送订单发货提醒短信
     *
     * @param phone     手机号
     * @param nickName  用户昵称
     * @param storeName 商品名称
     * @param orderNo   订单编号
     */
    @Override
    public Boolean sendOrderDeliverNotice(String phone, String nickName, String storeName, String orderNo) {
        SmsTemplate temp;
        try {
            beforeSendMessage();
            temp = getSmsTemp(NotifyConstants.DELIVER_GOODS_MARK);
        } catch (Exception e) {
            logger.error("发送短信失败，{}", e.getMessage());
            return false;
        }
        HashMap<String, Object> map = CollUtil.newHashMap();
        map.put("nickname", nickName);
        map.put("store_name", storeName);
        map.put("order_id", orderNo);
        String message = PlaceHolderReplaceUtils.replaceWithMap(temp.getContent(), map);
        return sendHuaweiSms(message, phone);
    }

    /**
     * 发送入驻审核通过通知短信
     *
     * @param phone    手机号
     * @param date     日期，yyyy-MM-dd
     * @param merName  商户名
     * @param merPhone 商户店长手机号
     * @param pwd      商户店长密码
     * @param siteName 站点名称
     * @return Boolean
     */
    @Override
    public Boolean sendMerchantAuditSuccessNotice(String phone, String date, String merName, String merPhone, String pwd, String siteName) {
        SmsTemplate temp;
        try {
            beforeSendMessage();
            temp = getSmsTemp(NotifyConstants.AUDIT_SUCCESS_MARK);
        } catch (Exception e) {
            logger.error("发送短信失败，{}", e.getMessage());
            return false;
        }
        HashMap<String, Object> map = CollUtil.newHashMap();
        map.put("date", date);
        map.put("mer", merName);
        map.put("phone", merPhone);
        map.put("pwd", pwd);
        map.put("site_name", siteName);
        String message = PlaceHolderReplaceUtils.replaceWithMap(temp.getContent(), map);
        return sendHuaweiSms(message, phone);
    }

    /**
     * 发送入驻审核未通过通知短信
     *
     * @param phone    手机号
     * @param date     日期，yyyy-MM-dd
     * @param merName  商户名
     * @param siteName 站点名称
     * @return Boolean
     */
    @Override
    public Boolean sendMerchantFileSuccessNotice(String phone, String date, String merName, String siteName) {
        SmsTemplate temp;
        try {
            beforeSendMessage();
            temp = getSmsTemp(NotifyConstants.AUDIT_FAIL_MARK);
        } catch (Exception e) {
            logger.error("发送短信失败，{}", e.getMessage());
            return false;
        }
        HashMap<String, Object> map = CollUtil.newHashMap();
        map.put("date", date);
        map.put("mer", merName);
        map.put("site", siteName);
        String message = PlaceHolderReplaceUtils.replaceWithMap(temp.getContent(), map);
        return sendHuaweiSms(message, phone);
    }

    /**
     * 发送生日礼短信
     * @param phone 手机号
     * @param name 祝福内容
     * @return Boolean
     */
    @Override
    public Boolean sendBirthdayPresent(String phone, String name) {
        SmsTemplate temp;
        try {
            beforeSendMessage();
            temp = getSmsTemp(NotifyConstants.BIRTHDAY_PRESENT_MARK);
        } catch (Exception e) {
            logger.error("发送短信失败，{}", e.getMessage());
            return false;
        }

        HashMap<String, Object> map = CollUtil.newHashMap();
        map.put("name", name);
        String message = PlaceHolderReplaceUtils.replaceWithMap(temp.getContent(), map);
        return sendHuaweiSms(message, phone);
    }

    private SmsTemplate getSmsTemp(String mark) {
        SystemNotification notification = systemNotificationService.getByMark(mark);
        if (ObjectUtil.isNull(notification)) {
            throw new CrmebException("未找到消息通知配置");
        }
        if (!notification.getIsSms().equals(NotifyConstants.SWITCH_OPEN)) {
            throw new CrmebException(notification.getDescription() + "未配置短信相关或已关闭");
        }
        SmsTemplate smsTemplate = smsTemplateService.getDetail(notification.getSmsId());
        return smsTemplate;
    }
}
