package com.storlead.sms.service.impl;

import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.storlead.framework.common.constant.RedisKeySaltConstant;
import com.storlead.framework.common.enums.ErrorMsgCode;
import com.storlead.framework.common.result.Result;
import com.storlead.framework.common.util.RandomCodeUtil;
import com.storlead.framework.redis.RedisService;
import com.storlead.sms.constants.SmsTemplateConstants;
import com.storlead.sms.mapper.SmsLogMapper;
import com.storlead.sms.pojo.entity.SmsLogEntity;
import com.storlead.sms.spi.SmsCaptchaScene;
import com.storlead.sms.spi.SmsCaptchaService;
import com.storlead.sms.spi.SmsLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 短信日志与验证码（发送/校验）
 */
@Slf4j
@Service
public class SmsLogServiceImpl extends ServiceImpl<SmsLogMapper, SmsLogEntity>
        implements SmsLogService, SmsCaptchaService {

    @Resource
    private RedisService redisService;

    @Override
    public Result<?> sendCaptcha(String mobile, SmsCaptchaScene scene) {
        if (!StringUtils.hasText(mobile)) {
            return Result.error(ErrorMsgCode.D_400009);
        }
        if (scene == null) {
            return Result.error(ErrorMsgCode.PARAMETER_FAIL);
        }
        int type = scene.getSmsLogType();
        int count = this.count(new LambdaQueryWrapper<SmsLogEntity>()
                .eq(SmsLogEntity::getMobile, mobile)
                .eq(SmsLogEntity::getType, type)
                .apply(" TO_DAYS(send_time) = TO_DAYS(NOW()) "));
        if (count >= SmsTemplateConstants.SEND_MAXIMIZE) {
            return Result.error(ErrorMsgCode.D_400001);
        }
        String cacheKey = captchaRedisKey(scene, mobile);
        Object cached = redisService.getCacheObject(cacheKey);
        if (Objects.nonNull(cached)) {
            SmsLogEntity smsLog = (SmsLogEntity) cached;
            Long currentTime = System.currentTimeMillis();
            Long sendTime = smsLog.getSendTime().getTime();
            if ((currentTime - sendTime) / 1000 < smsLog.getValidTime()) {
                return Result.error(ErrorMsgCode.D_400002);
            }
        }
        int checkCode = RandomCodeUtil.RandomCheckCode();
        try {
            boolean res = sendMobileVerifyCode(mobile, checkCode);
            if (!res) {
                return Result.error(ErrorMsgCode.D_400003);
            }
            log.error("SmsLog ---- = " + checkCode);
            SmsLogEntity smsLog = new SmsLogEntity();
            smsLog.setVerifyCode(String.valueOf(checkCode));
            smsLog.setMobile(mobile);
            smsLog.setType(type);
            smsLog.setUserId(null);
            smsLog.setValidTime(60);
            smsLog.setSendTime(new Date());
            smsLog.setStatus(1);
            this.baseMapper.insert(smsLog);
            redisService.setCacheObject(cacheKey, smsLog, 120L, TimeUnit.MINUTES);
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
        return Result.ok();
    }

    @Override
    public Result<?> verifyCaptcha(String mobile, String code, SmsCaptchaScene scene, boolean consumeAfterSuccess) {
        if (!StringUtils.hasText(mobile) || !StringUtils.hasText(code)) {
            return Result.error(ErrorMsgCode.PARAMETER_FAIL);
        }
        if (scene == null) {
            return Result.error(ErrorMsgCode.PARAMETER_FAIL);
        }
        String cacheKey = captchaRedisKey(scene, mobile);
        Object cached = redisService.getCacheObject(cacheKey);
        if (cached == null) {
            return Result.error(ErrorMsgCode.D_400004);
        }
        SmsLogEntity smsLog = (SmsLogEntity) cached;
        if (smsLog.getSendTime() != null && smsLog.getValidTime() != null) {
            long elapsedSec = (System.currentTimeMillis() - smsLog.getSendTime().getTime()) / 1000;
            if (elapsedSec > smsLog.getValidTime()) {
                return Result.error(ErrorMsgCode.D_400006);
            }
        }
        String expect = smsLog.getVerifyCode() == null ? "" : smsLog.getVerifyCode().trim();
        String actual = code.trim();
        if (!actual.equals(expect)) {
            return Result.error(ErrorMsgCode.D_400008);
        }
        if (consumeAfterSuccess) {
            redisService.deleteObject(cacheKey);
        }
        return Result.ok();
    }

    @Override
    public Result<?> sendLoginSmsCode(String mobile) {
        return sendCaptcha(mobile, SmsCaptchaScene.LOGIN);
    }

    /**
     * 与历史 Redis 键兼容：LOGIN 场景沿用 {@link RedisKeySaltConstant#REDIS_LOGIN_VALID_CODE_KEY}。
     */
    private String captchaRedisKey(SmsCaptchaScene scene, String mobile) {
        if (scene == SmsCaptchaScene.LOGIN) {
            return RedisKeySaltConstant.REDIS_LOGIN_VALID_CODE_KEY + mobile;
        }
        return "sms_captcha_" + scene.name() + "_" + mobile;
    }

    public boolean sendMobileVerifyCode(String mobile, Integer checkCode) throws ClientException {
        return true;
    }
}
