package cn.novalon.gym.manage.gateway.util;

import cn.novalon.gym.manage.gateway.service.JwtKeyService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;

@Component
public class JwtUtil {

    private static final Logger logger = LoggerFactory.getLogger(JwtUtil.class);

    @Value("${jwt.expiration:86400000}")
    private Long expiration;

    @Autowired
    private JwtKeyService jwtKeyService;

    private SecretKey getSigningKey() {
        return jwtKeyService.getCurrentSigningKey();
    }

    public String generateToken(String username, Long userId) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + expiration);

        try {
            String token = Jwts.builder()
                    .setSubject(username)
                    .claim("userId", userId)
                    .claim("keyVersion", jwtKeyService.getCurrentKeyVersion())
                    .setIssuedAt(now)
                    .setExpiration(expiryDate)
                    .signWith(getSigningKey())
                    .compact();
            
            logger.debug("Generated JWT token for user: {}, userId: {}", username, userId);
            return token;
            
        } catch (Exception e) {
            logger.error("Failed to generate JWT token for user: {}", username, e);
            throw new RuntimeException("Token generation failed", e);
        }
    }

    public Claims parseToken(String token) {
        try {
            return Jwts.parserBuilder()
                    .setSigningKey(getSigningKey())
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
                    
        } catch (Exception e) {
            logger.error("Failed to parse JWT token", e);
            throw new RuntimeException("Invalid token", e);
        }
    }

    public String getUsernameFromToken(String token) {
        Claims claims = parseToken(token);
        return claims.getSubject();
    }

    public Long getUserIdFromToken(String token) {
        Claims claims = parseToken(token);
        return claims.get("userId", Long.class);
    }

    public boolean validateToken(String token) {
        try {
            parseToken(token);
            logger.debug("JWT token validation successful");
            return true;
        } catch (Exception e) {
            logger.warn("JWT token validation failed: {}", e.getMessage());
            return false;
        }
    }

    public boolean isTokenExpired(String token) {
        try {
            Claims claims = parseToken(token);
            boolean expired = claims.getExpiration().before(new Date());
            
            if (expired) {
                logger.warn("JWT token is expired");
            }
            
            return expired;
            
        } catch (Exception e) {
            logger.error("Failed to check token expiration", e);
            return true;
        }
    }
}
