package com.bonus.sgzb.system.service.impl;

import cn.hutool.http.HttpRequest;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.bonus.sgzb.common.core.constant.UserConstants;
import com.bonus.sgzb.common.core.exception.ServiceException;
import com.bonus.sgzb.common.core.utils.GlobalConstants;
import com.bonus.sgzb.common.core.web.domain.AjaxResult;
import com.bonus.sgzb.common.redis.service.RedisService;
import com.bonus.sgzb.system.api.domain.SysUser;
import com.bonus.sgzb.system.config.TencentSmsConfig;
import com.bonus.sgzb.system.mapper.SysUserMapper;
import com.bonus.sgzb.system.service.ISysSmsService;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import com.tencentcloudapi.sms.v20210111.models.SendStatus;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import static com.bonus.sgzb.common.core.web.domain.AjaxResult.success;

/**
 * Description: 短信发送
 *
 * @Author 阮世耀
 * @Create 2023/12/11 15:49
 * @Version 1.0
 */
@Service
@Slf4j
public class SysSmsServiceImpl implements ISysSmsService {

    @Resource
    private RedisService redisService;
    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private TencentSmsConfig tencentSmsConfig;


    /**
     * 短信URL
     */
    private static final String URL = "http://api.ktsms.cn/sms_token?ddtkey=bonus&secretkey=KtyBns@Admin2023!";

    /**
     * 验收通知短信
     *
     * @param phone 手机号
     * @param msg   内容
     * @return
     */
    @Override
    public AjaxResult sendSms(String phone, String msg) {
        if (phone == null || StringUtils.isEmpty(msg)) {
            return AjaxResult.error("手机号码或短信内容不能为空");
        }
        if (phone.length() != UserConstants.PHONE_DEFAULT_LENGTH_LOGIN) {
            return AjaxResult.error("手机号格式不正确");
        }
       /* try {
            String[] args = msg.split(",");
            String body =  sendMessageNew(phone,tencentSmsConfig.getTemplateId().get(0),args);
            return success("发送手机号码：" + phone + "，内容：" + msg + "，返回结果：" + body);
        } catch (Exception e) {
            return AjaxResult.error("发送失败:" + e.getMessage());
        }*/
        return sendMsgByPhone(phone, msg);
    }

    /**
     * 登录短信验证码
     *
     * @param phone 手机号
     * @return
     */
    @Override
    public AjaxResult codeLogin(String phone) {

        /*try {
            //获取六位验证码
            String code = getSixBitCode();
            //调用发送短信的方法
            String body =  sendMessageNew(phone,tencentSmsConfig.getTemplateId().get(1),code);
            // 存储验证码至Redis中，键值为：code_15588886157 , 有效期5，时间颗粒度为MINUTES:分钟
            redisService.setCacheObject("code_" + phone, code, 5L, TimeUnit.MINUTES);
            return success("手机号：" + phone + "，用户登录验证码：" + code + "，返回结果：" + body);
        } catch (Exception e) {
            return AjaxResult.error("发送失败:" + e.getMessage());
        }*/
        return sendCodeByPhone(phone, null);
    }


    /**
     * 发送消息msg到手机
     *
     * @param phone 手机号码
     * @return AjaxResult对象
     */
    private AjaxResult sendMsgByPhone(String phone, String msg) {
        // 校验手机号码
        if (phone == null || phone.length() != UserConstants.PHONE_DEFAULT_LENGTH_LOGIN) {
            return AjaxResult.error("手机号码不正确");
        }
        // 发送短信
        try {
//            String URL = "http://106.ihuyi.common/webservice/sms.php?method=Submit";
            String content = URL + "&mobile=" + phone + "&content=【智慧仓储】" + msg + "。";
            String body = HttpRequest.post(content).execute(false).body();
            System.out.println("发送手机号码：" + phone + "，内容：" + msg + "，返回结果：" + body);
            if (body == null || !body.contains(GlobalConstants.STRING_OK)) {
                return AjaxResult.error("发送失败");
            }
            return success("发送手机号码：" + phone + "，内容：" + msg + "，返回结果：" + body);
        } catch (Exception e) {
            return AjaxResult.error("发送失败:" + e.getMessage());
        }
    }


    /**
     * 发送验证码到手机
     *
     * @param phone 手机号码
     * @return AjaxResult对象
     */
    private AjaxResult sendCodeByPhone(String phone, String msg) {
        // 校验手机号码
        if (phone == null || phone.length() != UserConstants.PHONE_DEFAULT_LENGTH_LOGIN) {
            return AjaxResult.error("手机号格式错误，请输入11位数字号码");
        }
        // 校验是否存在该手机号
        SysUser sysUser = sysUserMapper.checkPhoneUnique(phone);
        if (sysUser == null) {
            return AjaxResult.error("该手机号未绑定用户，请重新确认");
        }
        String code = getSixBitCode();
        // 校验验证码
        if (code.length() != UserConstants.CODE_MIN_LENGTH_LOGIN) {
            return AjaxResult.error("验证码格式不正确，生成错误！请联系后台管理员");
        }
        // 发送短信
        try {
            String content = URL + "&mobile=" + phone + "&content=【智慧仓储】您正在进行短信验证，验证码:" + code + "，请在5分钟内完成验证。";
            String body = HttpRequest.post(content).execute(false).body();
            System.out.println("发送短信：" + phone + "，验证码：" + code + "，返回结果：" + body);
            if (body == null || !body.contains(GlobalConstants.STRING_OK)) {
                return AjaxResult.error("发送失败");
            }
            // 存储验证码至Redis中，键值为：code_15588886157 , 有效期5，时间颗粒度为MINUTES:分钟
            redisService.setCacheObject("code_" + phone, code, 5L, TimeUnit.MINUTES);
//            return success("手机号：" + phone + "，用户登录验证码：" + code + "，返回结果：" + body);
            return success("验证码发送成功:" + body);
        } catch (Exception e) {
            return AjaxResult.error("发送失败:" + e.getMessage());
        }
    }


    /**
     * 判断验证码是否存在Redis中
     *
     * @param phone 手机号码
     * @param code  用户填入的验证码
     * @return 校验结果
     * @throws ServiceException 异常信息
     */
    @Override
    public boolean checkCode(String phone, String code) {
        String redisCode = redisService.getCacheObject("code_" + phone);
        if (StringUtils.isEmpty(redisCode)) {
            throw new ServiceException("验证码失效", 403);
        }
        if (!StringUtils.equals(redisCode.split(GlobalConstants.STRING_UNDERLINE)[0], code)) {
            throw new ServiceException("验证码错误", 401);
        } else {
            redisService.deleteObject("code_" + phone);
            return true;
        }
    }

    public static void main(String[] args) {
        System.out.println(getSixBitCode());
    }

    /**
     * 随机生成6位验证码
     */
    private static String getSixBitCode() {
        //随机数
        Random random = new Random();
        return String.valueOf(random.nextInt(900000) + 100000);
    }

    /**
     * 腾讯sms短信
     *
     * @param mobilePhone
     * @param templateId
     * @param args
     * @return
     * @throws Exception
     */
    public String sendMessageNew(String mobilePhone, String templateId, String... args) throws Exception {

        try {
            // 实例化一个认证对象，入参需要传入腾讯云账户secretId，secretKey,此处还需注意密钥对的保密
            Credential cred = new Credential(tencentSmsConfig.getAccessKeyId(), tencentSmsConfig.getAccessKeySecret());
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(tencentSmsConfig.getEndpoint());
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的  第二个参数是地域信息
            SmsClient client = new SmsClient(cred, tencentSmsConfig.getRegion(), clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            SendSmsRequest req = new SendSmsRequest();
            //设置固定的参数
            req.setSmsSdkAppId(tencentSmsConfig.getSdkAppId());// 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId
            req.setSignName(tencentSmsConfig.getSmsSign());//短信签名内容: 使用 UTF-8 编码，必须填写已审核通过的签名
            req.setTemplateId(templateId);//模板 ID: 必须填写已审核通过的模板 ID
            //设置发送相关的参数
            //发送对象（最多200个）
            String[] phoneNumberSet1 = mobilePhone.split(",");
            for (int i = 0; i < phoneNumberSet1.length; i++) {
                phoneNumberSet1[i] = "+86" + phoneNumberSet1[i];
            }
            req.setPhoneNumberSet(phoneNumberSet1);//发送的手机号
            if (null != args && args.length > 0 && Arrays.stream(args)
                    .noneMatch(s -> s == null || s.trim().isEmpty())) {
                String[] templateParamSet1 = args;//模板的参数
                req.setTemplateParamSet(templateParamSet1);//发送验证码
            }
            // 返回的resp是一个SendSmsResponse的实例，与请求对象对应
            log.info("腾讯云平台短信发送请求参数：{}", JSONObject.toJSONString(req));
            SendSmsResponse resp = client.SendSms(req);
            // 输出json格式的字符串回包
            log.info("腾讯云平台短信发送响应结果：{}", JSONObject.toJSONString(resp));
            SendStatus[] sendStatusSet = resp.getSendStatusSet();
            List<SendStatus> sendStatuses = Arrays.asList(sendStatusSet);
            if (CollectionUtils.isNotEmpty(sendStatuses)) {
                for (SendStatus sendStatus : sendStatuses) {
                    if (!"OK".equalsIgnoreCase(sendStatus.getCode())) {
                        throw new ServiceException(sendStatus.getMessage(), Integer.valueOf(sendStatus.getCode()));
                    }
                }
            }

            return resp.getRequestId();
        } catch (TencentCloudSDKException e) {
            e.printStackTrace();
            log.error("短信发送失败：{}", e.getMessage());
            throw new ServiceException(e.getMessage(), Integer.valueOf(e.getErrorCode()));
        }
    }
}
