package com.ruoyi.system.service.impl;

import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.QRCodeUtils;
import com.ruoyi.common.utils.SendSmsUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.MiniprogramQueryLog;
import com.ruoyi.system.domain.QueryConfig;
import com.ruoyi.system.domain.ReportDetail;
import com.ruoyi.system.domain.ReportQueryLog;
import com.ruoyi.system.mapper.MiniprogramQueryLogMapper;
import com.ruoyi.system.mapper.QueryConfigMapper;
import com.ruoyi.system.mapper.ReportDetailMapper;
import com.ruoyi.system.mapper.ReportQueryLogMapper;
import com.ruoyi.system.service.IQueryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;


import java.util.Calendar;
import java.util.concurrent.TimeUnit;

import static com.ruoyi.common.core.domain.AjaxResult.MSG_TAG;
import static com.ruoyi.common.utils.SecurityUtils.getUsername;

/**
 * @author tjf
 * @Date: 2021/12/27/11:37
 */
@Service
public class QueryServiceImpl implements IQueryService {

    @Autowired
    private ReportDetailMapper reportDetailMapper;

    @Autowired
    private ReportQueryLogMapper reportQueryLogMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private QueryConfigMapper queryConfigMapper;

    @Autowired
    private MiniprogramQueryLogMapper miniprogramQueryLogMapper;


    //短信参数
    @Value("${sms_aliyun_accessKeyId}")
    String accessKeyId;// accessKeyId
    @Value("${sms_aliyun_accessKeySecret}")
    String accessKeySecret;// accessKeySecret
    @Value("${sms_aliyun_signName}")
    String signName;
    @Value("${sms_aliyun_templateCode}")
    String templateCode;

    @Value("${sms_aliyun_signNameQuery}")
    String signNameQuery;
    @Value("${sms_aliyun_templateCodeQuery}")
    String templateCodeQuery;


    /**
     * 门户查询报告信息
     *
     * @param reportQueryLog
     * @return
     */
    @Override
    public AjaxResult selectReport(ReportQueryLog reportQueryLog) {
        //通用校验
        AjaxResult validateResult = queryPublic(reportQueryLog,true);
        if (!UserConstants.QUERY_SUCCESS.equals(validateResult.get(MSG_TAG))) {
            return validateResult;
        }
        //获取查询方式
        String queryMode = reportQueryLog.getQueryMode();
        //二维码查询
        if (UserConstants.QUERY_MODE_QR.equals(queryMode)) {
            return queryByQr(reportQueryLog);
            //粗略查询
        } else if (UserConstants.QUERY_MODE_ROUGH.equals(queryMode)) {
            return queryByRough(reportQueryLog);
            //详细查询
        } else if (UserConstants.QUERY_MODE_DETAIL.equals(queryMode)) {
            return queryByDetail(reportQueryLog);
        }
        return AjaxResult.success();
    }

    /**
     * 小程序根据二维码查询
     * @param reportQueryLog
     * @return
     */
    @Override
    public AjaxResult queryQr(ReportQueryLog reportQueryLog) {
        String qrImage = reportQueryLog.getQrImage();
        String remark = "";
        if (StringUtils.isBlank(qrImage)) {
            remark = "未接收到二维码";
            return AjaxResult.error(remark);
        }
        try {
            //解析二维码
            String reportNumber = QRCodeUtils.decode(qrImage);
            if (StringUtils.isBlank(reportNumber)) {
                remark = "二维码解析失败";
                return AjaxResult.error(remark);
            }
/*            //查询二维码有效期
            String verifyKey = UserConstants.QR_IMAGE + reportNumber;
            Object cacheObject = redisCache.getCacheObject(verifyKey);
            if (cacheObject == null) {
                remark = "二维码已过期";
                reportQueryLog.setRemark(remark);
                reportQueryLogMapper.insertReportQueryLog(reportQueryLog);
                return AjaxResult.error(remark);
            }*/
            ReportDetail reportDetail = reportDetailMapper.selectReportDetailByReportNumber(reportNumber);
            if (reportDetail != null) {
                reportDetail.setReportUrl(null);
                MiniprogramQueryLog miniprogramQueryLog = new MiniprogramQueryLog();
                miniprogramQueryLog.setReportNumber(reportNumber);
                miniprogramQueryLog.setQueryPhone(reportQueryLog.getQueryPhone());
                miniprogramQueryLog.setCreateTime(DateUtils.getNowDate());
                miniprogramQueryLog.setCreateBy(reportQueryLog.getQueryPhone());
                miniprogramQueryLog.setQueryMode("1");
                miniprogramQueryLogMapper.insertMiniprogramQueryLog(miniprogramQueryLog);
                return AjaxResult.success(reportDetail);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("未查询到对应信息");
        }
        return AjaxResult.error("未查询到对应信息");
    }

    /**
     * 小程序根据编号查询
     * @param reportQueryLog
     * @return
     */
    @Override
    public AjaxResult queryReportNum(ReportQueryLog reportQueryLog) {
        String reportNumber = reportQueryLog.getReportNumber();
        ReportDetail reportDetail = reportDetailMapper.selectReportDetailByReportNumber(reportNumber);
        if (reportDetail != null) {
            reportDetail.setReportUrl(null);
            MiniprogramQueryLog miniprogramQueryLog = new MiniprogramQueryLog();
            miniprogramQueryLog.setReportNumber(reportNumber);
            miniprogramQueryLog.setQueryPhone(reportQueryLog.getQueryPhone());
            miniprogramQueryLog.setCreateTime(DateUtils.getNowDate());
            miniprogramQueryLog.setCreateBy(reportQueryLog.getQueryPhone());
            miniprogramQueryLog.setQueryMode("2");
            miniprogramQueryLogMapper.insertMiniprogramQueryLog(miniprogramQueryLog);
            return AjaxResult.success(reportDetail);
        }
        return AjaxResult.error("查询的文档编号不存在");
    }

    /**
     * 发送短信验证码
     *
     * @param reportQueryLog
     * @return
     */
    @Override
    public AjaxResult sendSms(ReportQueryLog reportQueryLog) {
        //判断该手机号是否超过查询次数
        //获取查询主体
        String queryType = reportQueryLog.getQueryType();
        String queryMode = reportQueryLog.getQueryMode();
        //查询手机号
        String phone = "";
        QueryConfig queryConfig = new QueryConfig();
        queryConfig.setQueryType(queryType);
        queryConfig.setQueryMode(queryMode);
        if (UserConstants.QUERY_TYPE_PEOPLE.equals(queryType)) {
            phone = reportQueryLog.getQueryPhone();
        } else if (UserConstants.QUERY_TYPE_UNIT.equals(queryType)) {
            phone = reportQueryLog.getCompanyPhone();
        }
        String verifyKey = UserConstants.QUERY_CODE_KEY + phone;
        String codeNotConsume = redisCache.getCacheObject(verifyKey);
        if (StringUtils.isNotBlank(codeNotConsume)) {
            //说明有未消费的验证码
            return AjaxResult.error("请勿重复获取验证码");
        }
        //如果没有验证码判断今天是否有查询次数
        //校验查询次数
        QueryConfig queryConfigRough = queryConfigMapper.selectQueryConfig(queryConfig);
        String resultQueryNumber = validateQueryNumber(phone, queryConfigRough);
        if (!UserConstants.QUERY_SUCCESS.equals(resultQueryNumber)) {
            return AjaxResult.error(resultQueryNumber);
        }
        //发送短信验证码
        if (StringUtils.isNotBlank(phone)) {
            try {
                String code = SendSmsUtils.getCode(6);
                SendSmsResponse sendSmsResponse = SendSmsUtils.sendSms(phone, "{\"code\":\"" + code + "\"}", accessKeyId, accessKeySecret, signName, templateCode);
                QuerySendDetailsResponse querySendDetailsResponse = SendSmsUtils.querySendDetails(sendSmsResponse.getBizId(), phone, accessKeyId, accessKeySecret);
                String ok = querySendDetailsResponse.getCode();
                if ("OK".equals(ok)) {
                    //设置验证码10分钟有效期
                    redisCache.setCacheObject(UserConstants.QUERY_CODE_KEY + phone, code, 10, TimeUnit.MINUTES);
                    return AjaxResult.success("发送成功");
                } else {
                    return AjaxResult.error(querySendDetailsResponse.getMessage());
                }
            } catch (ClientException e) {
                e.printStackTrace();
            }
        }
        return AjaxResult.error("未发现手机号");
    }

    /**
     * 给档案拥有者发送询问短信
     *
     * @param reportQueryLog
     * @return
     */
    @Override
    public AjaxResult sendQueryNum(ReportQueryLog reportQueryLog) {
        //发送查询码前,先校验验证码是否通过,且不删除redis中key
        AjaxResult result = queryPublic(reportQueryLog,false);
        if (!UserConstants.QUERY_SUCCESS.equals(result.get(MSG_TAG))) {
            return result;
        }
        //验证码通过后,给文档原始人,发送询问查询码的短信
        String reportNumber = reportQueryLog.getReportNumber();
        if (StringUtils.isNotBlank(reportNumber)) {
            ReportDetail reportDetail = reportDetailMapper.selectReportDetailByReportNumberDetail(reportNumber);
            if (reportDetail != null){
                //档案拥有者的手机号码
                String phonenumber = reportDetail.getPhonenumber();
                if (StringUtils.isNotBlank(phonenumber)) {
                    //给文档创建人发送询问短信
                    try {
                        String queryType = reportQueryLog.getQueryType();
                        StringBuilder sb = new StringBuilder();
                        String phone = "";
                        if (UserConstants.QUERY_TYPE_PEOPLE.equals(queryType)) {
                            sb.append(reportQueryLog.getQueryName()).append("(个人)");
                            phone = reportQueryLog.getQueryPhone();
                        }
                        if (UserConstants.QUERY_TYPE_UNIT.equals(queryType)) {
                            sb.append(reportQueryLog.getCompanyName()).append("(单位)");
                            phone = reportQueryLog.getCompanyPhone();
                        }
                        //"{\"code\":\"" + code + "\"}"
                        SendSmsResponse sendSmsResponse = SendSmsUtils.sendSms(phonenumber, "{\"name\":\"" + sb.toString() + "\",\"reportNumber\":\"" + reportNumber + "\"}", accessKeyId, accessKeySecret, signNameQuery, templateCodeQuery);
                        QuerySendDetailsResponse querySendDetailsResponse = SendSmsUtils.querySendDetails(sendSmsResponse.getBizId(), phonenumber, accessKeyId, accessKeySecret);
                        String ok = querySendDetailsResponse.getCode();
                        if ("OK".equals(ok)) {
                            //redis存储查询人的手机号码
                            redisCache.setCacheObject(UserConstants.QUERY_NUM_CREATE + phonenumber, phone, 30, TimeUnit.MINUTES);
                            return AjaxResult.success("发送成功,请等待对方回复");
                        } else {
                            return AjaxResult.error(querySendDetailsResponse.getMessage());
                        }
                    } catch (ClientException e) {
                        e.printStackTrace();
                    }
                }else {
                    return AjaxResult.error("文档拥有者暂未填写手机号,无法获得查询码");
                }
            }else {
                return AjaxResult.error("查询的文档编号不存在");
            }
        }
        return AjaxResult.error("未填写查询报告编号");
    }

    /**
     * 查询方式是二维码
     *
     * @param reportQueryLog
     * @return
     */
    private AjaxResult queryByQr(ReportQueryLog reportQueryLog) {
        String qrImage = reportQueryLog.getQrImage();
        String remark = "";
        if (StringUtils.isBlank(qrImage)) {
            remark = "未接收到二维码";
            reportQueryLog.setRemark(remark);
            reportQueryLogMapper.insertReportQueryLog(reportQueryLog);
            return AjaxResult.error(remark);
        }
        try {
            //解析二维码
            String reportNumber = QRCodeUtils.decode(qrImage);
            if (StringUtils.isBlank(reportNumber)) {
                remark = "二维码解析失败";
                reportQueryLog.setRemark(remark);
                reportQueryLogMapper.insertReportQueryLog(reportQueryLog);
                return AjaxResult.error(remark);
            }
            //查询二维码有效期
            String verifyKey = UserConstants.QR_IMAGE + reportNumber;
            Object cacheObject = redisCache.getCacheObject(verifyKey);
            if (cacheObject == null) {
                remark = "二维码已过期";
                reportQueryLog.setRemark(remark);
                reportQueryLogMapper.insertReportQueryLog(reportQueryLog);
                return AjaxResult.error(remark);
            }
            ReportDetail reportDetail = reportDetailMapper.selectReportDetailByReportNumber(reportNumber);
            if (reportDetail != null) {
                reportDetail.setReportUrl(null);
                reportQueryLog.setIsSuccess("Y");
                reportQueryLog.setRemark(UserConstants.QUERY_SUCCESS);
                reportQueryLogMapper.insertReportQueryLog(reportQueryLog);
                return AjaxResult.success(reportDetail);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("未查询到对应信息");
        }
        return AjaxResult.error("未查询到对应信息");
    }


    /**
     * 查询方式是粗查
     *
     * @param reportQueryLog
     * @return
     */
    private AjaxResult queryByRough(ReportQueryLog reportQueryLog) {
        String reportNumber = reportQueryLog.getReportNumber();
        ReportDetail reportDetail = reportDetailMapper.selectReportDetailByReportNumber(reportNumber);
        if (reportDetail != null) {
            reportDetail.setReportUrl(null);
            reportQueryLog.setRemark(UserConstants.QUERY_SUCCESS);
            reportQueryLog.setIsSuccess("Y");
            reportQueryLogMapper.insertReportQueryLog(reportQueryLog);
            return AjaxResult.success(reportDetail);
        }
        reportQueryLog.setRemark("查询的文档编号不存在");
        reportQueryLogMapper.insertReportQueryLog(reportQueryLog);
        return AjaxResult.error("查询的文档编号不存在");
    }

    /**
     * 查询方式是详情
     *
     * @param reportQueryLog
     * @return
     */
    private AjaxResult queryByDetail(ReportQueryLog reportQueryLog) {
        //查询手机号
        String phone = "";
        //获取查询主体
        String queryType = reportQueryLog.getQueryType();
        if (UserConstants.QUERY_TYPE_PEOPLE.equals(queryType)) {
            phone = reportQueryLog.getQueryPhone();
        } else if (UserConstants.QUERY_TYPE_UNIT.equals(queryType)) {
            phone = reportQueryLog.getCompanyPhone();
        }
        //校验查询码
        String resultNum = validateNum(phone, reportQueryLog.getQueryNum());
        if (!UserConstants.QUERY_SUCCESS.equals(resultNum)) {
            reportQueryLog.setRemark(resultNum);
            reportQueryLogMapper.insertReportQueryLog(reportQueryLog);
            return AjaxResult.error(resultNum);
        }
        String reportNumber = reportQueryLog.getReportNumber();
        ReportDetail reportDetail = reportDetailMapper.selectReportDetailByReportNumber(reportNumber);
        if (reportDetail != null) {
            reportQueryLog.setIsSuccess("Y");
            reportQueryLog.setRemark(UserConstants.QUERY_SUCCESS);
            reportQueryLogMapper.insertReportQueryLog(reportQueryLog);
            return AjaxResult.success(reportDetail);
        }
        reportQueryLog.setRemark("查询的文档编号不存在");
        reportQueryLogMapper.insertReportQueryLog(reportQueryLog);
        return AjaxResult.error("查询的文档编号不存在");
    }


    /**
     * 查询通用校验模块
     */
    private AjaxResult queryPublic(ReportQueryLog reportQueryLog,Boolean isDelKey) {
        //获取查询主体
        String queryType = reportQueryLog.getQueryType();
        String queryMode = reportQueryLog.getQueryMode();
        //查询手机号
        String phone = "";
        QueryConfig queryConfig = new QueryConfig();
        queryConfig.setQueryType(queryType);
        queryConfig.setQueryMode(queryMode);
        queryConfig.setQueryMode(UserConstants.QUERY_MODE_ROUGH);
        if (UserConstants.QUERY_TYPE_PEOPLE.equals(queryType)) {
            phone = reportQueryLog.getQueryPhone();
        } else if (UserConstants.QUERY_TYPE_UNIT.equals(queryType)) {
            phone = reportQueryLog.getCompanyPhone();
        }
        //校验查询次数
        QueryConfig queryConfigRough = queryConfigMapper.selectQueryConfig(queryConfig);
        String resultQueryNumber = validateQueryNumber(phone, queryConfigRough);
        if (!UserConstants.QUERY_SUCCESS.equals(resultQueryNumber)) {
            reportQueryLog.setRemark(resultQueryNumber);
            reportQueryLogMapper.insertReportQueryLog(reportQueryLog);
            return AjaxResult.error(resultQueryNumber);
        }

        //校验验证码
        String resultCaptcha = validateCaptcha(phone, reportQueryLog.getCode(),isDelKey);
        if (!UserConstants.QUERY_SUCCESS.equals(resultCaptcha)) {
            reportQueryLog.setRemark(resultCaptcha);
            reportQueryLogMapper.insertReportQueryLog(reportQueryLog);
            return AjaxResult.error(resultCaptcha);
        }
        return AjaxResult.success(UserConstants.QUERY_SUCCESS);
    }

    /**
     * 校验验证码
     *
     * @param queryPhone 查询者手机号
     * @return 结果
     */
    public String validateCaptcha(String queryPhone, String code,Boolean isDelKey) {
        String verifyKey = UserConstants.QUERY_CODE_KEY + queryPhone;
        String captcha = redisCache.getCacheObject(verifyKey);
        if (captcha == null) {
            return "验证码不存在或已过期,请重新获取";
        }
        if (!code.equalsIgnoreCase(captcha)) {
            return "验证码不正确,请检查";
        }
        if (isDelKey){
            redisCache.deleteObject(verifyKey);
        }
        return UserConstants.QUERY_SUCCESS;
    }

    /**
     * 校验查询码
     *
     * @param queryPhone 查询者手机号
     * @return 结果
     */
    public String validateNum(String queryPhone, String code) {
        String verifyKey = UserConstants.QUERY_NUM_KEY + queryPhone;
        String captcha = redisCache.getCacheObject(verifyKey);
        if (captcha == null) {
            return "查询码不存在或已过期,请重新获取";
        }
        if (!code.equalsIgnoreCase(captcha)) {
            return "查询码不正确,请检查";
        }
        redisCache.deleteObject(verifyKey);
        return UserConstants.QUERY_SUCCESS;
    }

    /**
     * 校验查询次数
     *
     * @param queryPhone 查询的手机号
     * @return
     */
    public String validateQueryNumber(String queryPhone, QueryConfig queryConfigRough) {
        Integer queryNumber = 0;
        if (queryConfigRough != null) {
            //可用的查询次数
            queryNumber = queryConfigRough.getQueryNumber();
        }
        String verifyKey = UserConstants.QUERY_CODE_NUMBER + queryPhone;
        Object queryNum = redisCache.getCacheObject(verifyKey);
        if (queryNum == null) {
            //说明一次没查询判断可用的查询次数是否设置等于0就是不限制查询
            redisCache.setCacheObject(verifyKey, 1, getSecondsNextEarlyMorning(), TimeUnit.SECONDS);
            return UserConstants.QUERY_SUCCESS;
        } else {
            //判断如果设置的查询次数是0
            if (queryNumber == 0) {
                redisCache.setCacheObject(verifyKey, Integer.parseInt(queryNum.toString()) + 1, getSecondsNextEarlyMorning(), TimeUnit.SECONDS);
                return UserConstants.QUERY_SUCCESS;
            } else {
                if (queryNumber >= Integer.parseInt(queryNum.toString())) {
                    return "当前没有查询次数";
                } else {
                    redisCache.setCacheObject(verifyKey, Integer.parseInt(queryNum.toString()) + 1, getSecondsNextEarlyMorning(), TimeUnit.SECONDS);
                    return UserConstants.QUERY_SUCCESS;
                }
            }
        }
    }


    /**
     * 判断当前时间距离第二天凌晨的秒数
     *
     * @return 返回值单位为[s:秒]
     */
    public int getSecondsNextEarlyMorning() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_YEAR, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return (int) (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000;
    }
}
