package com.erp.security;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
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;
import java.util.Map;

@Component
public class JwtTokenProvider {

    private final SecretKey secretKey;
    private final long expiration;

    public JwtTokenProvider(
            @Value("${jwt.secret}") String secret,
            @Value("${jwt.expiration}") long expiration) {
        this.secretKey = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
        this.expiration = expiration;
    }

    /**
     * JWT 토큰 생성 — Node.js JwtUtils.generateToken() 과 동일한 페이로드 구조
     * personBean keys: userId, userName, deptName, companyCode, companyName, userType, userTypeName
     */
    public String generateToken(Map<String, Object> personBean) {
        Date now = new Date();
        Object fpc = personBean.get("force_password_change");
        boolean forcePasswordChange = fpc instanceof Boolean ? (Boolean) fpc
                : fpc != null && Boolean.parseBoolean(fpc.toString());
        return Jwts.builder()
                .claim("user_id",       personBean.get("user_id"))
                .claim("user_name",     personBean.get("user_name"))
                .claim("dept_name",     personBean.get("dept_name"))
                .claim("company_code",  personBean.get("company_code"))
                .claim("company_name",  personBean.get("company_name"))
                .claim("user_type",     personBean.get("user_type"))
                .claim("user_type_name", personBean.get("user_type_name"))
                .claim("force_password_change", forcePasswordChange)
                .issuedAt(now)
                .expiration(new Date(now.getTime() + expiration))
                .audience().add("PMS-Users").and()
                .issuer("PMS-System")
                .signWith(secretKey)
                .compact();
    }

    /** JWT 의 force_password_change claim. 없는 토큰(legacy)은 false 로 간주. */
    public boolean isForcePasswordChange(String token) {
        try {
            Boolean v = getClaims(token).get("force_password_change", Boolean.class);
            return Boolean.TRUE.equals(v);
        } catch (Exception e) {
            return false;
        }
    }

    public boolean validateToken(String token) {
        try {
            Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token);
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            return false;
        }
    }

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

    public String getUserId(String token) {
        return getClaims(token).get("user_id", String.class);
    }

    public String getCompanyCode(String token) {
        return getClaims(token).get("company_code", String.class);
    }

    public String getUserType(String token) {
        return getClaims(token).get("user_type", String.class);
    }
}
