package com.evobms.project.iot.service;

import com.evobms.common.constant.Constants;
import com.evobms.common.utils.StringUtils;
import com.evobms.framework.redis.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.security.SecureRandom;
import java.util.concurrent.TimeUnit;

/**
 * 设备自定义令牌服务（非JWT）
 * - 生成固定长度(65)的随机令牌
 * - 将 token -> sn 映射存入缓存并设置TTL
 * - 从请求中解析并校验令牌，返回设备SN
 */
@Component
public class DeviceTokenService {
    private static final String KEY_PREFIX = "iot_device_token:";
    private static final char[] CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray();
    private final SecureRandom random = new SecureRandom();

    @Value("${token.header:Authorization}")
    private String header;

    @Value("${token.expireTime:30}")
    private int expireMinutes;

    @Autowired
    private RedisCache redisCache;

    /**
     * 生成并缓存设备令牌
     */
    public String issueTokenForSn(String sn) {
        String token = randomToken(64);
        String key = KEY_PREFIX + token;
        redisCache.setCacheObject(key, sn, expireMinutes, TimeUnit.MINUTES);
        return token;
    }

    /**
     * 从请求解析并校验令牌，返回设备SN
     */
    public String resolveSn(HttpServletRequest request) {
        String token = getToken(request);
        if (StringUtils.isEmpty(token)) return null;
        String key = KEY_PREFIX + token;
        return redisCache.getCacheObject(key);
    }

    /**
     * 获取请求头中的令牌并去除前缀
     */
    public String getToken(HttpServletRequest request) {
        // 先按配置的头名读取；若缺失则回退常见头名
        String token = request.getHeader(header);
        if (StringUtils.isEmpty(token)) {
            token = request.getHeader("Authorization");
        }
        if (StringUtils.isEmpty(token)) {
            token = request.getHeader("iot_device_token");
        }
        if (StringUtils.isEmpty(token)) {
            token = request.getHeader("X-Device-Token");
        }
        if (StringUtils.isEmpty(token)) {
            return null;
        }
        // 规范化：去除前后空格，并不区分大小写地移除 "Bearer " 前缀
        String normalized = token.trim();
        String prefix = Constants.TOKEN_PREFIX; // "Bearer "
        int pLen = prefix.length();
        if (normalized.length() >= pLen && normalized.regionMatches(true, 0, prefix, 0, pLen)) {
            normalized = normalized.substring(pLen);
        }

        int ws = indexOfWhitespace(normalized);
        if (ws > 0) {
            normalized = normalized.substring(0, ws);
        }
        return StringUtils.isEmpty(normalized) ? null : normalized.trim();
    }

    private static int indexOfWhitespace(String s) {
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (Character.isWhitespace(c)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 撤销令牌
     */
    public void revoke(String token) {
        if (StringUtils.isEmpty(token)) return;
        String key = KEY_PREFIX + token;
        redisCache.deleteObject(key);
    }

    private String randomToken(int len) {
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            sb.append(CHARS[random.nextInt(CHARS.length)]);
        }
        return sb.toString();
    }
}
