package com.zioinfo.hrm.auth;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;

@Slf4j
@Component
public class JwtUtil {

    @Value("${guardia.jwt.secret:guardia-hrm-jwt-secret-2026-minimum-256bit-key-zioinfo}")
    private String secret;

    @Value("${guardia.jwt.expiration:86400000}")
    private long expirationMs;

    private SecretKey key() {
        return Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
    }

    public String generate(String username, String role) {
        return Jwts.builder()
            .subject(username)
            .claim("role", role)
            .issuedAt(new Date())
            .expiration(new Date(System.currentTimeMillis() + expirationMs))
            .signWith(key())
            .compact();
    }

    /**
     * UIWS 2FA 이식: 1차 로그인 통과 후 발급하는 단기 verify-token.
     * purpose=2fa 클레임으로 access 토큰과 구분(verify-token 으로는 보호 API 접근 불가).
     */
    public String generateVerifyToken(String username, long validitySeconds) {
        return Jwts.builder()
            .subject(username)
            .claim("purpose", "2fa")
            .issuedAt(new Date())
            .expiration(new Date(System.currentTimeMillis() + validitySeconds * 1000L))
            .signWith(key())
            .compact();
    }

    /** verify-token 검증 후 username 반환. 유효하지 않거나 purpose!=2fa 면 null. */
    public String parseVerifyTokenUsername(String token) {
        try {
            Claims c = parse(token);
            if (!"2fa".equals(c.get("purpose", String.class))) {
                return null;
            }
            return c.getSubject();
        } catch (JwtException | IllegalArgumentException e) {
            log.debug("verify-token 검증 실패: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 보안: 토큰이 2FA verify-token(purpose=2fa)인지 판별.
     * JwtFilter 가 access 토큰만 인증 컨텍스트로 인정하도록 verify-token 을 걸러내는 데 사용
     * (2차 인증 전 verify-token 으로 보호 API 에 접근하는 2FA 우회 차단).
     */
    public boolean isVerifyToken(String token) {
        try {
            return "2fa".equals(parse(token).get("purpose", String.class));
        } catch (JwtException | IllegalArgumentException e) {
            return false;
        }
    }

    public Claims parse(String token) {
        return Jwts.parser().verifyWith(key()).build()
            .parseSignedClaims(token).getPayload();
    }

    public boolean isValid(String token) {
        try { parse(token); return true; }
        catch (JwtException | IllegalArgumentException e) {
            log.debug("JWT 검증 실패: {}", e.getMessage());
            return false;
        }
    }

    public String getUsername(String token) { return parse(token).getSubject(); }
    public String getRole(String token) { return parse(token).get("role", String.class); }
}
