package com.sundot.airport.common.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.teaopenapi.models.Config;
import com.sundot.airport.common.config.AliyunSmsConfig;
import com.sundot.airport.common.constant.CacheConstants;
import com.sundot.airport.common.core.redis.RedisCache;
import com.sundot.airport.common.exception.ServiceException;
import com.sundot.airport.common.service.SmsService;
import com.sundot.airport.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 短信服务实现类
 *
 * @author wangxx
 */
@Slf4j
@Service
public class AliyunSmsServiceImpl implements SmsService {

    @Autowired
    private AliyunSmsConfig smsConfig;

    @Autowired
    private RedisCache redisCache;

    private Client client;

    /**
     * 短信验证码有效期（秒）
     */
    private static final int CODE_EXPIRE_TIME = 300;

    /**
     * 短信发送间隔（秒）
     */
    private static final int SEND_INTERVAL = 60;

    @PostConstruct
    public void init() {
        if (smsConfig.getEnabled()) {
            try {
                Config config = new Config()
                        .setAccessKeyId(smsConfig.getAccessKeyId())
                        .setAccessKeySecret(smsConfig.getAccessKeySecret());
                // 设置 endpoint，不同地域可能不同，请根据实际情况修改
                config.endpoint = "dysmsapi.aliyuncs.com";
                client = new Client(config);
                log.info("短信客户端初始化成功");
            } catch (Exception e) {
                log.error("短信客户端初始化失败：{}", e.getMessage(), e);
            }
        } else {
            log.warn("短信登录功能未开启，跳过短信客户端初始化");
        }
    }

    @Override
    public boolean sendSmsCode(String phoneNumber) {
        if (!smsConfig.getEnabled()) {
            throw new ServiceException("短信登录功能暂未开启");
        }

        if (StringUtils.isEmpty(phoneNumber)) {
            throw new ServiceException("手机号码不能为空");
        }

        // 校验手机号格式
        if (!isValidPhone(phoneNumber)) {
            throw new ServiceException("手机号码格式不正确");
        }

        // 检查是否发送频繁
        String sendKey = CacheConstants.SMS_SEND_INTERVAL_KEY + phoneNumber;
        if (redisCache.hasKey(sendKey)) {
            throw new ServiceException("短信发送太过频繁，请" + getExpireTime(sendKey) + "秒后再试");
        }

        // 生成 6 位数字验证码
        String code = RandomUtil.randomNumbers(6);

        // 构建模板参数
        Map<String, String> templateParam = new HashMap<>();
        templateParam.put("code", code);

        // 发送到阿里云短信
        boolean result = sendSms(phoneNumber, JSONUtil.toJsonStr(templateParam));

        if (result) {
            // 存储验证码到 Redis，用于后续验证
            String verifyKey = CacheConstants.SMS_CODE_KEY + phoneNumber;
            redisCache.setCacheObject(verifyKey, code, CODE_EXPIRE_TIME, TimeUnit.SECONDS);

            // 设置发送间隔锁
            redisCache.setCacheObject(sendKey, "1", SEND_INTERVAL, TimeUnit.SECONDS);

            log.info("短信验证码发送成功 - 手机号：{}, 验证码：{}", phoneNumber, code);
        } else {
            log.error("短信验证码发送失败 - 手机号：{}", phoneNumber);
        }

        return result;
    }

    @Override
    public boolean verifySmsCode(String phoneNumber, String code) {
        if (!smsConfig.getEnabled()) {
            throw new ServiceException("短信登录功能暂未开启");
        }

        if (StringUtils.isEmpty(phoneNumber) || StringUtils.isEmpty(code)) {
            throw new ServiceException("手机号或验证码不能为空");
        }

        String verifyKey = CacheConstants.SMS_CODE_KEY + phoneNumber;
        String storedCode = redisCache.getCacheObject(verifyKey);

        if (storedCode == null) {
            throw new ServiceException("验证码已过期，请重新获取");
        }

        if (!code.equals(storedCode)) {
            throw new ServiceException("验证码错误");
        }

        // 验证成功后删除验证码，防止重复使用
        redisCache.deleteObject(verifyKey);
        return true;
    }

    @Override
    public boolean sendSms(String phoneNumber, String templateParam) {
        if (!smsConfig.getEnabled()) {
            throw new ServiceException("短信登录功能暂未开启");
        }

        try {
            SendSmsRequest request = new SendSmsRequest()
                    .setPhoneNumbers(phoneNumber)
                    .setSignName(smsConfig.getSignName())
                    .setTemplateCode(smsConfig.getTemplateCode())
                    .setTemplateParam(templateParam);

            SendSmsResponse response = client.sendSms(request);

            // 判断发送结果
            if ("OK".equals(response.getBody().getCode())) {
                log.info("短信发送成功 - 手机号：{}, 请求 ID: {}", phoneNumber, response.getBody().getRequestId());
                return true;
            } else {
                log.error("短信发送失败 - 手机号：{}, 错误码：{}, 错误信息：{}",
                        phoneNumber, response.getBody().getCode(), response.getBody().getMessage());
                throw new ServiceException("短信发送失败：" + response.getBody().getMessage());
            }
        } catch (Exception e) {
            log.error("发送短信异常 - 手机号：{}, 错误：{}", phoneNumber, e.getMessage(), e);
            throw new ServiceException("短信发送异常：" + e.getMessage());
        }
    }

    /**
     * 验证手机号格式
     */
    private boolean isValidPhone(String phoneNumber) {
        if (phoneNumber == null || phoneNumber.length() != 11) {
            return false;
        }
        String regex = "^1(3[0-9]|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\\d{8}$";
        return phoneNumber.matches(regex);
    }

    /**
     * 获取 Redis key 的剩余过期时间
     */
    private Long getExpireTime(String key) {
        return redisCache.getExpire(key);
    }
}
