package com.zioinfo.signage.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:ZioInfoSignageJwtSecret2026VeryLongSecretKeyForHS256AlgorithmAtLeast256Bits}")
    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, String tenantCode) {
        return Jwts.builder()
            .subject(username)
            .claim("role", role)
            .claim("tenant", tenantCode)
            .issuedAt(new Date())
            .expiration(new Date(System.currentTimeMillis() + expirationMs))
            .signWith(key())
            .compact();
    }

    /**
     * UIWS 2FA 이식: 1차 로그인 통과 후 발급하는 단기 verify-token.
     * purpose=2fa 클레임으로 access 토큰과 구분(verify-token 으로는 보호 API 접근 불가 — JwtFilter 에서 차단).
     */
    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)인지 판별.
     * verify-token 은 access 와 같은 서명키라 isValid()는 통과하므로, JwtFilter 가 별도로
     * 걸러내지 않으면 2차 코드 검증 없이 보호 API 접근(2FA 완전 우회)이 된다.
     * → JwtFilter 는 purpose=2fa 토큰을 인증 컨텍스트로 세우지 않는다(/api/auth/verify 에서만 사용).
     */
    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); }
    public String getTenant(String token) { return parse(token).get("tenant", String.class); }
}
