package com.cusc.nirvana.user.rnr.fp.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.cache.CacheFactory;
import com.cusc.nirvana.common.encrypt.sign.HMAC;
import com.cusc.nirvana.common.result.Response;
import com.cusc.nirvana.user.exception.CuscUserException;
import com.cusc.nirvana.user.rnr.fp.common.ResponseCode;
import com.cusc.nirvana.user.rnr.fp.common.cloud.SignConstants;
import com.cusc.nirvana.user.rnr.fp.common.config.SmsPropertyConfig;
import com.cusc.nirvana.user.rnr.fp.common.util.DateUtil;
import com.cusc.nirvana.user.rnr.fp.constants.RedisConstant;
import com.cusc.nirvana.user.rnr.fp.dto.SmsResponseDTO;
import com.cusc.nirvana.user.rnr.fp.dto.SmsSendDTO;
import com.cusc.nirvana.user.rnr.fp.service.ISmsService;
import com.cusc.nirvana.user.util.CuscStringUtils;
import com.cusc.nirvana.user.util.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

/**
 * Description: 短信service
 * <br />
 * CreateDate 2021-11-02 20:25:49
 *
 * @author yuyi
 **/
@Service
@Slf4j
public class SmsServiceImpl implements ISmsService {

    private static final Logger LOGGER = LoggerFactory.getLogger(SmsServiceImpl.class);

    @Autowired
    private RestTemplate noBalanceRestTemplateRnrFp;

    @Autowired
    private SmsPropertyConfig smsPropertyConfig;

    @Value("${sms.cusc.strategyCode:}")
    private String strategyCode;

	@Value("${sms.cusc.interval:60000}")
	private Integer intervalTime;

	@Value("${sms.cusc.limit:20}")
	private Integer maxLimit;

	private static final Integer ONE_DAY_SEC = 24 * 60 * 60;

	@Resource
	private CacheFactory cacheFactory;

    @Override
    public Response<SmsResponseDTO> sendSms(String phone, List<String> paramterList, String smsTemplate) {
		try {
			//判断当前验证码是否达到发送间隔 60s
			String intervalKey = RedisConstant.SMS_RNR_CAPTCHA_SEND_INTERVAL_KEY+phone;
			log.info("sendSms intervalKey = {}",intervalKey);
			if (!cacheFactory.getLockService().lock(intervalKey,intervalTime)) {
				throw new CuscUserException(ResponseCode.SMS_CAPTCHA_INTERVAL_FAIL.getCode(),ResponseCode.SMS_CAPTCHA_INTERVAL_FAIL.getMsg());
			}


			//判断短信是否发到最大次数
			String maxTimesKey = RedisConstant.SMS_RNR_CAPTCHA_LIMIT_TIMES+DateUtils.formatDate(LocalDate.now(),DateUtil.YYMM_DD_MM)+phone;
			log.info("sendSms maxTimesKey = {},maxLimit = {}",intervalKey,maxLimit);
			if (cacheFactory.getExpireStringService().setExpireValueIncr(maxTimesKey,1L,ONE_DAY_SEC) > maxLimit) {
				throw new CuscUserException(ResponseCode.SMS_OVER_MAX_LIMIT.getCode(),ResponseCode.SMS_OVER_MAX_LIMIT.getMsg());
			}
		} catch (CuscUserException e) {
			throw e;
		} catch (Exception e) {
			throw new CuscUserException(ResponseCode.SYSTEM_ERROR.getCode(),ResponseCode.SYSTEM_ERROR.getMsg());
		}

        SmsSendDTO send = new SmsSendDTO();
        List<String> phoneList = new ArrayList<>();
        phoneList.add(phone);
        send.setPhoneNumbers(phoneList);
        send.setTemplateParams(paramterList);
        send.setSignatureCode(smsPropertyConfig.getSignatureCode());
        send.setAccesskey(smsPropertyConfig.getAccessKey());
        send.setStrategyCode(strategyCode);
        send.setTemplateCode(smsTemplate);
        Response<SmsResponseDTO> retResp;
        try {
           /* retResp = RestTemplateUtils.postForResponse(noBalanceRestTemplateRnrFp,
                    smsPropertyConfig.getSmsUrl() + smsPropertyConfig.getSendUrl(),
                    send,
                    SmsResponseDTO.class);*/
            HttpEntity httpEntity = new HttpEntity(JSON.toJSONString(send), headers());
            String sendSmdUrl = smsPropertyConfig.getSmsUrl() + smsPropertyConfig.getSendUrl();

            log.info("SmsServiceImpl sendSms request url : {}", sendSmdUrl);
            long startTime = System.currentTimeMillis();
            ResponseEntity<String> entity =
                    noBalanceRestTemplateRnrFp.exchange(sendSmdUrl, HttpMethod.POST, httpEntity, String.class);
            retResp = JSON.parseObject(entity.getBody(),
                    new TypeReference<Response<SmsResponseDTO>>(SmsResponseDTO.class) {
                    }.getType());
            if (null != retResp && null != retResp.getData()) {
                //置空短信为空
                retResp.getData().setCaptcha("");
            }
            log.info("SmsServiceImpl sendSms response url : {} , result : {}, cost: {} ms ", sendSmdUrl,
                    JSON.toJSONString(retResp), System.currentTimeMillis() - startTime);
        } catch (Exception e) {
            LOGGER.error("短信发送失败： ", e);
            retResp = Response.createError(ResponseCode.SMS_CAPTCHA_SEND_FAIL.getMsg(),
                    ResponseCode.SMS_CAPTCHA_SEND_FAIL.getCode());
        }

        return retResp;
    }

    @Override
    public Response<SmsResponseDTO> sendSms(String phone, String parameter, String smsTemplate) {
        List<String> list = new ArrayList<>();
        list.add(parameter);
        return sendSms(phone, list, smsTemplate);
    }

    /**
     * 生成请求头
     *
     * @return
     */
    public HttpHeaders headers() {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add(SignConstants.APP_ID, smsPropertyConfig.getAPPID());
        httpHeaders.add(SignConstants.NONCE_STR, CuscStringUtils.generateUuid());
        httpHeaders.add(SignConstants.TIMESTAMP, String.valueOf(System.currentTimeMillis()));
        httpHeaders.add(SignConstants.VERSION, smsPropertyConfig.getVERSION());
        httpHeaders.setContentType(MediaType.parseMediaType("application/json; charset=UTF-8"));
        StringBuilder sb = new StringBuilder();
        sb.append(SignConstants.APP_ID + smsPropertyConfig.getAPPID());
        sb.append(SignConstants.NONCE_STR + httpHeaders.get(SignConstants.NONCE_STR).get(0));
        sb.append(SignConstants.TIMESTAMP + httpHeaders.get(SignConstants.TIMESTAMP).get(0));
        sb.append(SignConstants.VERSION + httpHeaders.get(SignConstants.VERSION).get(0));
        log.info("SmsServiceImpl headers param : {}, appScret:{}", sb, smsPropertyConfig.getAPPSCRET());
        String scret = HMAC.sign(sb.toString(), smsPropertyConfig.getAPPSCRET(), HMAC.Type.HmacSHA256);
        httpHeaders.add(SignConstants.SIGN, scret);
        return httpHeaders;
    }

//    @Override
//    public boolean checkSmsConfigNotNull(SmsSendConfig bean) {
//        return bean != null && CuscStringUtils.isNotEmpty(bean.getSmsTemplateCode());
//    }
//
//    @Override
//    public void convertToSmsConfig(ApplicationDTO fromBean, SmsSendConfig toBean) {
//        //短信配置为空，从应用配置中取
//        if (!checkSmsConfigNotNull(toBean)) {
//            throw new CuscUserException(ResponseCode.SMS_SEND_CONFIG_NOT_NULL.getCode() + "",
//                    ResponseCode.SMS_SEND_CONFIG_NOT_NULL.getMsg());
//        }
//
//        if (toBean.getSmsTotalLimit() == null) {
//            if (fromBean.getSmsTotalLimit() == null) {
//                log.warn("sms config smsTotalLimit is null");
//                throw new CuscUserException(ResponseCode.SMS_SEND_CONFIG_NOT_NULL.getCode() + "",
//                        ResponseCode.SMS_SEND_CONFIG_NOT_NULL.getMsg());
//            }
//            toBean.setSmsTotalLimit(fromBean.getSmsTotalLimit());
//        }
//
//        if (toBean.getSmsIntervalLimit() == null) {
//            if (fromBean.getSmsIntervalLimit() == null) {
//                log.warn("sms config smsIntervalLimit is null");
//                throw new CuscUserException(ResponseCode.SMS_SEND_CONFIG_NOT_NULL.getCode() + "",
//                        ResponseCode.SMS_SEND_CONFIG_NOT_NULL.getMsg());
//            }
//            toBean.setSmsIntervalLimit(fromBean.getSmsIntervalLimit());
//        }
//
//        if (toBean.getSmsPlatformKey() == null) {
//            if (fromBean.getSmsPlatformKey() == null) {
//                log.warn("sms config smsPlatformKey is null");
//                throw new CuscUserException(ResponseCode.SMS_SEND_CONFIG_NOT_NULL.getCode() + "",
//                        ResponseCode.SMS_SEND_CONFIG_NOT_NULL.getMsg());
//            }
//            toBean.setSmsPlatformKey(fromBean.getSmsPlatformKey());
//        }
//
//        if (toBean.getSmsSignatureCode() == null) {
//            if (fromBean.getSmsSignatureCode() == null) {
//                log.warn("sms config smsSignatureCode is null");
//                throw new CuscUserException(ResponseCode.SMS_SEND_CONFIG_NOT_NULL.getCode() + "",
//                        ResponseCode.SMS_SEND_CONFIG_NOT_NULL.getMsg());
//            }
//            toBean.setSmsSignatureCode(fromBean.getSmsSignatureCode());
//        }
//    }


//    /**
//     * Description: 短信发送限制检查
//     * <br />
//     * CreateDate 2022-01-27 14:43:41
//     *
//     * @author yuyi
//     **/
//    @Override
//    public void checkSmsSendLimit(String phone, SmsSendConfig bean) {
//        try {
//            if (bean.getSmsTotalLimit() != null && bean.getSmsTotalLimit() > 0 && CuscStringUtils.isNotEmpty(
//                    bean.getTotalLimitKey())) {
//                //记录发送总次数限制
//                Integer smsTotal = cacheFactory.getExpireStringService()
//                        .getValue(bean.getTotalLimitKey() + phone  + "_" + bean.getTenantNo() + "_" + bean.getAppId(),
//                                Integer.class);
//                if (smsTotal != null && smsTotal >= bean.getSmsTotalLimit()) {
//                    throw new CuscUserException(ResponseCode.SMS_TOTAL_LIMIT_OVERRUN.getCode(),
//                            ResponseCode.SMS_TOTAL_LIMIT_OVERRUN.getMsg());
//                }
//            }
//
//            if (bean.getSmsIntervalLimit() != null && bean.getSmsIntervalLimit() > 0 && CuscStringUtils.isNotEmpty(
//                    bean.getIntervalLimitKey())) {
//                //记录发送间隔限制
//                boolean isExists =
//                        cacheFactory.getExpireStringService()
//                                .containsKey(bean.getIntervalLimitKey() + phone  + "_" + bean.getTenantNo() + "_" +
//                                bean.getAppId());
//                if (isExists) {
//                    throw new CuscUserException(ResponseCode.SMS_INTERVAL_LIMIT_OVERRUN.getCode(),
//                            ResponseCode.SMS_INTERVAL_LIMIT_OVERRUN.getMsg());
//                }
//            }
//        } catch (Exception e) {
//            //只记录，不抛出异常，屏蔽对业务的影响
//            log.error("检查短信发送限制信息时访问redis 异常：", e);
//        }
//    }

//    //----------------私有方法区域--------------------------
//
//    /**
//     * Description: 保存短信发送限制信息到redis
//     * <br />
//     * CreateDate 2022-02-16 09:50:25
//     *
//     * @author yuyi
//     **/
//    private void saveSmsSendLimitToRedis(String phone, SmsSendConfig bean) {
//        try {
//            if (bean.getSmsTotalLimit() != null && bean.getSmsTotalLimit() > 0 && CuscStringUtils.isNotEmpty(
//                    bean.getTotalLimitKey())) {
//                //记录发送总次数限制
//                Integer smsTotal =
//                        cacheFactory.getExpireStringService().getValue(
//                                bean.getTotalLimitKey() + phone + "_" + bean.getTenantNo() + "_" + bean.getAppId(),
//                                Integer.class);
//                Long expireTime;
//                if (smsTotal == null) {
//                    smsTotal = 1;
//                    LocalDateTime begin = LocalDateTime.now();
//                    expireTime = DateUtils.secondBetween(begin, DateUtils.getDayEnd(begin));
//                } else {
//                    smsTotal++;
//                    expireTime =
//                            cacheFactory.getExpireStringService().getKeyExpireTime(bean.getTotalLimitKey() + phone
//                            + "_" + bean.getTenantNo() + "_" + bean.getAppId());
//                }
//                cacheFactory.getExpireStringService().setExpireValue(bean.getTotalLimitKey() + phone + "_" + bean
//                .getTenantNo() + "_" + bean.getAppId(), smsTotal,
//                        expireTime.intValue());
//            }
//
//            if (bean.getSmsIntervalLimit() != null && bean.getSmsIntervalLimit() > 0 && CuscStringUtils.isNotEmpty(
//                    bean.getIntervalLimitKey())) {
//                //记录发送间隔限制
//                cacheFactory.getExpireStringService()
//                        .setExpireValue(bean.getIntervalLimitKey() + phone + "_" + bean.getTenantNo() + "_" + bean
//                        .getAppId(), 1, bean.getSmsIntervalLimit());
//            }
//        } catch (CacheException e) {
//            //只记录，不抛出异常，屏蔽对业务的影响
//            log.error("保存短信发送限制信息到redis 异常：", e);
//        }
//    }
}
