package com.corewing.app.service.impl;

import com.corewing.app.service.VerifyCodeService;
import com.corewing.app.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

/**
 * 验证码服务实现类
 */
@Slf4j
@Service
public class VerifyCodeServiceImpl implements VerifyCodeService {

    private final RedisUtil redisUtil;
    private final SmsBaoUtil smsBaoUtil;
    private final EmailUtil emailUtil;




    public VerifyCodeServiceImpl(RedisUtil redisUtil, SmsBaoUtil smsBaoUtil, EmailUtil emailUtil) {
        this.redisUtil = redisUtil;
        this.smsBaoUtil = smsBaoUtil;
        this.emailUtil = emailUtil;
    }

    @Override
    public boolean sendCode(String account, String type) {

        if (!StringUtils.hasText(account)) {
            throw new RuntimeException(I18nUtil.getMessage("error.account.empty"));
        }

        if (!StringUtils.hasText(type)) {
            throw new RuntimeException(I18nUtil.getMessage("error.verify.type.empty"));
        }

        if (!AccountUtil.isPhone(account) && !AccountUtil.isEmail(account)) {
            throw new RuntimeException(I18nUtil.getMessage("error.account.format.invalid"));
        }

        // 生成验证码
        String code = CommonGenerateUtil.generateCode();

        // 保存到 Redis，key格式：verify_code:{type}:{account}
        String redisKey = String.format("verify_code:%s:%s", type, account);
        redisUtil.set(redisKey, code, CommonGenerateUtil.CODE_EXPIRE_MINUTES * 60);

        log.info("验证码已生成: account={}, type={}, code={}", account, type, code);

        // 发送验证码
        if (AccountUtil.isPhone(account)) {
            // 获取当前ip
            String clientIp = IpUtil.getClientIp(CommonServletUtil.getRequest());
            clientIp = clientIp.replaceAll(":", "");
            // 校验IP发短信次数
            // 使用 setIfAbsent 初始化计数器（只在键不存在时创建，并设置过期时间为1天）
            boolean isNew = redisUtil.setIfAbsent("exceed_" + clientIp, 1, 1, TimeUnit.DAYS);
            // 如果键已存在，递增计数器
            long sendCount = isNew ? 1 : redisUtil.incr("exceed_" + clientIp, 1);

            if (sendCount <= 4) {
                // 发送短信验证码
                boolean success = smsBaoUtil.sendVerifyCode(account, code);
                if (!success) {
                    throw new RuntimeException(I18nUtil.getMessage("error.sms.send.failed"));
                }
            } else {
                throw new RuntimeException(I18nUtil.getMessage("error.sms.send.exceed"));
            }
        } else {
            // 发送邮件验证码
            boolean success = emailUtil.sendVerifyCode(account, code);
            if (!success) {
                throw new RuntimeException(I18nUtil.getMessage("error.email.send.failed"));
            }
        }

        return true;
    }

    @Override
    public boolean verifyCode(String account, String code, String type) {
        if (!StringUtils.hasText(account) || !StringUtils.hasText(code) || !StringUtils.hasText(type)) {
            return false;
        }

        // 从 Redis 获取验证码
        String redisKey = String.format("verify_code:%s:%s", type, account);
        Object savedCode = redisUtil.get(redisKey);

        if (savedCode == null) {
            log.warn("验证码不存在或已过期: account={}, type={}", account, type);
            return false;
        }

        // 验证码比对
        boolean matched = code.equals(savedCode.toString());

        if (matched) {
            // 验证成功后删除验证码
            redisUtil.del(redisKey);
            log.info("验证码验证成功: account={}, type={}", account, type);
        } else {
            log.warn("验证码错误: account={}, type={}, inputCode={}, savedCode={}",
                    account, type, code, savedCode);
        }

        return matched;
    }

}
