package com.ruoyi.xq.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.xq.domain.SmsVerify;
import com.ruoyi.xq.domain.User;
import com.ruoyi.xq.domain.UserLogin;
import com.ruoyi.xq.enums.common.CodeEnum;
import com.ruoyi.xq.enums.common.SystemConfigEnum;
import com.ruoyi.xq.kit.AliSmsKit;
import com.ruoyi.xq.manager.SystemConfigManager;
import com.ruoyi.xq.mapper.SmsVerifyMapper;
import com.ruoyi.xq.service.SmsVerifyService;
import com.ruoyi.xq.service.UserInfoService;
import com.ruoyi.xq.service.UserLoginService;
import com.ruoyi.xq.service.UserService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 短信验证码Service业务层处理
 *
 * @author 77
 * @date 2024-01-01
 */
@Service
public class SmsVerifyServiceImpl extends ServiceImpl<SmsVerifyMapper, SmsVerify> implements SmsVerifyService {

    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private UserLoginService userLoginService;
    @Autowired
    private UserService userService;
    @Autowired
    private AliSmsKit aliSmsKit;
    @Autowired
    private SystemConfigManager systemConfigManager;

    @Override
    public boolean check(CodeEnum codeEnum, String mobile, String code){
        String smsAdmin = systemConfigManager.getSystemConfig(SystemConfigEnum.SMS_CODE_ADMIN);
        if(StringUtils.isNotEmpty(smsAdmin) && smsAdmin.equals(code)){
            return true;
        }
        SmsVerify one = this.getOne(Wrappers.lambdaQuery(SmsVerify.class)
                .eq(SmsVerify::getType, codeEnum)
                .eq(SmsVerify::getReceivePhone, mobile)
                .eq(SmsVerify::getStatus, 1)
                .gt(SmsVerify::getOverTime, LocalDateTime.now())
                .orderByDesc(SmsVerify::getId)
                .last("limit 1"));
        if(one == null){
            return false;
        }
        if(one.getVerifyCode().equals(code)){
            return true;
        }
//        codeManager.check(codeEnum,mobile,code);
        return false;
    }

    @Override
    public void put(CodeEnum codeEnum,String mobile){
        String clientIP = ServletUtils.getClientIP();
        if(codeEnum == CodeEnum.RESET_PASSWORD){
            boolean exists = userService.exists(Wrappers.lambdaQuery(User.class)
                    .eq(User::getMobile, mobile));
            if(!exists){
                throw new ServiceException("手机号未注册!");
            }
        }
        LocalDateTime now = LocalDateTime.now();
        SmsVerify one = this.getOne(Wrappers.lambdaQuery(SmsVerify.class)
                .eq(SmsVerify::getType, codeEnum.name())
                .eq(SmsVerify::getReceivePhone, mobile)
                .eq(SmsVerify::getStatus, 1)
                .gt(SmsVerify::getOverTime, now)
                .last("limit 1"));
        if(one != null){
            long diff = one.getCreateTime().until(now, ChronoUnit.SECONDS);
            if(diff < 100){
                throw new ServiceException("请"+(100-diff)+"秒之后再重试发送!");
            }
        }
        long count = userLoginService.count(Wrappers.lambdaQuery(UserLogin.class).eq(UserLogin::getRegIp, clientIP));
        if(count > 3){
            throw new ServiceException("验证码发送失败！2"+count);
        }
        String code = RandomUtil.randomNumbers(6);
        SmsVerify smsVerify = new SmsVerify();
        smsVerify.setType(codeEnum.name());
        smsVerify.setReceivePhone(mobile);
        smsVerify.setVerifyCode(code);
        smsVerify.setSendInterface("阿里云");
        smsVerify.setOperateIp(clientIP);
        smsVerify.setOverTime(LocalDateTime.now().plus(1, ChronoUnit.MINUTES));
        this.save(smsVerify);
        boolean boo = aliSmsKit.sendMessage(mobile, codeEnum.getAliTemplate(), code, false);
        if(!boo){
            this.removeById(smsVerify);
        }
    }

    @Override
    public void clearSmsVerify(int days) {
        int index = 0;
        LocalDateTime deleteTimeFlag = LocalDateTime.now().plusDays(-days);
        while (true){
            List<SmsVerify> list = this.list(Wrappers.lambdaUpdate(SmsVerify.class)
                    .lt(SmsVerify::getCreateTime, deleteTimeFlag)
                    .last("limit 100"));
            if(index > 500 || CollectionUtils.isEmpty(list)){
                break;
            }
            index++;
            List<Long> ids = list.stream().map(SmsVerify::getId).collect(Collectors.toList());
            this.removeBatchByIds(ids);
        }
    }

}
