package com.cm.manager.sms.service.impl;

import com.cm.common.base.AbstractService;
import com.cm.common.exception.ParamsException;
import com.cm.common.exception.RemoveException;
import com.cm.common.exception.SearchException;
import com.cm.common.exception.base.SystemException;
import com.cm.common.pojo.ListPage;
import com.cm.common.result.SuccessResult;
import com.cm.common.result.SuccessResultList;
import com.cm.common.utils.DateUtil;
import com.cm.common.utils.HashMapUtil;
import com.cm.common.utils.UUIDUtil;
import com.cm.manager.sms.config.properties.SmsDefaultProperties;
import com.cm.manager.sms.config.properties.SmsProperties;
import com.cm.manager.sms.config.properties.SmsTencentProperties;
import com.cm.manager.sms.dao.sms.ISmsDao;
import com.cm.manager.sms.manager.VerificationCodeManager;
import com.cm.manager.sms.pojo.dtos.sms.SmsDTO;
import com.cm.manager.sms.pojo.vos.sms.SmsVO;
import com.cm.manager.sms.service.ISmsService;
import com.cm.manager.sms.utils.DefaultSmsUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.qcloudsms.SmsMultiSender;
import com.github.qcloudsms.SmsMultiSenderResult;
import com.github.qcloudsms.httpclient.HTTPException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: VerificationCodeServiceImpl
 * @Description: 验证码
 * @Author: WangGeng
 * @Date: 2020/3/4 7:44 下午
 * @Version: 1.0
 **/
@Service
public class SmsServiceImpl extends AbstractService implements ISmsService {

    @Autowired
    private SmsProperties smsProperties;

    @Autowired
    private ISmsDao smsDao;

    @Override
    public SuccessResult saveSms(SmsVO smsVO) throws Exception {
        saveSmsInfo(null, smsVO);
        return new SuccessResult();
    }

    @Override
    public SuccessResult saveSmsByToken(String token, SmsVO smsVO) throws Exception {
        saveSmsInfo(token, smsVO);
        return new SuccessResult();
    }

    /**
     * 新增短信
     *
     * @param token
     * @param smsVO
     * @throws Exception
     */
    private void saveSmsInfo(String token, SmsVO smsVO) throws Exception {
        Map<String, Object> params = HashMapUtil.beanToMap(smsVO);
        String currentDate = DateUtil.getTime();
        params.put("smsId", UUIDUtil.getUUID());
        params.put("creator", 1);
        params.put("gmtCreate", currentDate);
        params.put("modifier", 1);
        params.put("gmtModified", currentDate);
        params.put("isDelete", 0);
        smsDao.saveSms(params);
    }

    @Override
    public SuccessResult removeSms(String ids) throws RemoveException {
        removeSmsInfo(null, ids);
        return new SuccessResult();
    }

    @Override
    public SuccessResult removeSmsByToken(String token, String ids) throws RemoveException {
        removeSmsInfo(token, ids);
        return new SuccessResult();
    }

    /**
     * 删除短信
     *
     * @param token
     * @param ids
     */
    private void removeSmsInfo(String token, String ids) {
        Map<String, Object> params = getHashMap(3);
        params.put("smsIds", Arrays.asList(ids.split("_")));
        if (token != null) {
            setUpdateInfo(token, params);
        } else {
            setUpdateInfo(params);
        }
        smsDao.removeSms(params);
    }

    @Override
    public SuccessResult updateSms(String smsId, SmsVO smsVO) throws Exception {
        updateSmsInfo(null, smsId, smsVO);
        return new SuccessResult();
    }

    @Override
    public SuccessResult updateSmsByToken(String token, String smsId, SmsVO smsVO) throws Exception {
        updateSmsInfo(token, smsId, smsVO);
        return new SuccessResult();
    }

    /**
     * 修改短信
     *
     * @param token
     * @param smsId
     * @param smsVO
     */
    private void updateSmsInfo(String token, String smsId, SmsVO smsVO) throws Exception {
        Map<String, Object> params = HashMapUtil.beanToMap(smsVO);
        params.put("smsId", smsId);
        if (token != null) {
            setUpdateInfo(token, params);
        } else {
            setUpdateInfo(params);
        }
        smsDao.updateSms(params);
    }

    @Override
    public SmsDTO getSmsById(String smsId) throws SearchException {
        Map<String, Object> params = super.getHashMap(1);
        params.put("smsId", smsId);
        return smsDao.getSms(params);
    }

    @Override
    public List<SmsDTO> listSms(Map<String, Object> params) throws SearchException {
        return smsDao.listSms(params);
    }

    @Override
    public SuccessResultList<List<SmsDTO>> listPageSms(ListPage page) throws SearchException {
        PageHelper.startPage(page.getPage(), page.getRows());
        List<SmsDTO> smsDTOs = smsDao.listSms(page.getParams());
        PageInfo<SmsDTO> pageInfo = new PageInfo<>(smsDTOs);
        return new SuccessResultList<>(smsDTOs, pageInfo.getPageNum(), pageInfo.getTotal());
    }

    @Override
    public SuccessResult saveVerificationCode(String phone) throws Exception {
        VerificationCodeManager verificationCodeManager = VerificationCodeManager.getInstance();
        long timeRemaining = verificationCodeManager.effectiveVerificationCodeTimeRemaining(phone);
        if (timeRemaining > 0) {
            throw new ParamsException(String.format("验证码已发送，若没有收到，请在%d秒后重试", (timeRemaining / 1000)));
        }
        String currentTimeStr = String.valueOf(System.currentTimeMillis());
        String code = currentTimeStr.substring(currentTimeStr.length() - 6);
        sendCode(phone, code);
        verificationCodeManager.setVerificationCode(phone, code);
        return new SuccessResult();
    }

    @Override
    public void saveSms(String phone, String content) throws Exception {
        LOG.info(">>>>> 向手机号：{}，发送短信：{}", phone, content);
        if (!smsProperties.getActive()) {
            return;
        }
        if (StringUtils.equals(TENCENT_TYPE, smsProperties.getType())) {
            tencentSms(phone, content);
        } else {
            defaultSms(phone, content);
        }
    }

    /**
     * 默认验证码
     *
     * @param phone
     * @param content
     */
    private void defaultSms(String phone, String content) throws Exception {
        SmsDefaultProperties smsDefaultProperties = smsProperties.getDefaultSms();
        StringBuilder contentSB = new StringBuilder(smsDefaultProperties.getSign()).append(content);
        String url = "https://dx.ipyy.net/sms.aspx?action=send&userid=&account={account}&password={password}&mobile={mobile}&content={content}&sendTime=&extno={extno}";
        String[] paramArray = new String[]{
                smsDefaultProperties.getAccount(),
                smsDefaultProperties.getPassword(),
                phone,
                contentSB.toString(),
                phone
        };
        sendMessage(url, paramArray, phone, contentSB.toString());
    }

    /**
     * 腾讯验证码
     *
     * @param phone
     * @param content
     */
    private void tencentSms(String phone, String content) {
        throw new SystemException("短信发送失败，未配置腾讯短信服务");
    }

    private void sendCode(String phone, String code) throws Exception {
        LOG.info(">>>>> 向手机号：{}，发送验证码：{}", phone, code);
        if (!smsProperties.getActive()) {
            return;
        }
        if (StringUtils.equals(TENCENT_TYPE, smsProperties.getType())) {
            tencentSmsCode(phone, code);
        } else {
            defaultSmsCode(phone, code);
        }
    }

    /**
     * 默认验证码
     *
     * @param phone
     * @param code
     */
    private void defaultSmsCode(String phone, String code) throws Exception {
        SmsDefaultProperties smsDefaultProperties = smsProperties.getDefaultSms();
        String content = smsDefaultProperties.getTemplate().getVerificationCode().replace("{sign}", smsDefaultProperties.getSign()).replace("{content}", code);
        String url = "https://dx.ipyy.net/sms.aspx?action=send&userid=&account={account}&password={password}&mobile={mobile}&content={content}&sendTime=&extno={extno}";
        String[] paramArray = new String[]{
                smsDefaultProperties.getAccount(),
                smsDefaultProperties.getPassword(),
                phone,
                content,
                phone
        };
        sendMessage(url, paramArray, phone, content);
    }

    private void sendMessage(String url, String[] paramArray, String phone, String content) throws Exception {
        SmsVO smsVO = new SmsVO();
        smsVO.setPhone(phone);
        smsVO.setContent(content);
        try {
            DefaultSmsUtil.sendSms(url, paramArray);
            smsVO.setSendStatus(1);
            saveSms(smsVO);
        } catch (SystemException e) {
            String errorMessage = e.getMessage();
            smsVO.setSendStatus(0);
            smsVO.setErrorMessage(errorMessage);
            saveSms(smsVO);
            throw new SystemException("短信发送失败");
        }
    }


    /**
     * 腾讯验证码
     *
     * @param phone
     * @param code
     */
    private void tencentSmsCode(String phone, String code) {
        String[] params = {code};
        SmsTencentProperties smsTencentProperties = smsProperties.getTencentSms();
        SmsMultiSender sender = new SmsMultiSender(Integer.parseInt(smsTencentProperties.getAppId()), smsTencentProperties.getAppKey());
        try {
            SmsMultiSenderResult result = sender.sendWithParam("86", new String[]{phone}, Integer.parseInt(smsTencentProperties.getVerificationCodeTemplateId()), params, smsTencentProperties.getSmsSign(), "", "");
            LOG.debug("Tencent sms result: {}", result);
        } catch (HTTPException e) {
            LOG.error(e.getMessage(), e);
            throw new SystemException("发送验证码失败");
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
            throw new SystemException("发送验证码失败");
        }
    }

}
