package com.zioinfo.hrm.common;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * 인사 PII / 자격증명 암호화 유틸 — AES-256-GCM.
 *
 * <p>GUARDiA 보안 불변 규칙: 사원 개인정보(주민번호·연락처·계좌번호 등) PII는 평문 저장 금지.
 * {@code *_enc} 컬럼에 본 유틸로 암호화 저장하고, API 응답에는 마스킹/제외한다.
 *
 * <p>저장 포맷: Base64( IV(12B) || ciphertext || GCM tag(16B) ).
 */
@Component
public class CryptoUtil {

    private static final int IV_LEN = 12;
    private static final int TAG_BITS = 128;
    private final SecretKeySpec key;
    private final SecureRandom random = new SecureRandom();

    public CryptoUtil(@Value("${guardia.crypto.secret:guardia-hrm-aes-256-gcm-master-key-2026-zioinfo}") String secret) {
        try {
            byte[] digest = MessageDigest.getInstance("SHA-256").digest(secret.getBytes(StandardCharsets.UTF_8));
            this.key = new SecretKeySpec(digest, "AES");
        } catch (Exception e) {
            throw new IllegalStateException("암호화 키 초기화 실패", e);
        }
    }

    public String encrypt(String plain) {
        if (plain == null || plain.isEmpty()) return plain;
        try {
            byte[] iv = new byte[IV_LEN];
            random.nextBytes(iv);
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(TAG_BITS, iv));
            byte[] ct = cipher.doFinal(plain.getBytes(StandardCharsets.UTF_8));
            byte[] out = new byte[iv.length + ct.length];
            System.arraycopy(iv, 0, out, 0, iv.length);
            System.arraycopy(ct, 0, out, iv.length, ct.length);
            return Base64.getEncoder().encodeToString(out);
        } catch (Exception e) {
            throw new RuntimeException("ERR-HRM-CRYPTO-01: 암호화 실패");
        }
    }

    public String decrypt(String enc) {
        if (enc == null || enc.isEmpty()) return enc;
        try {
            byte[] all = Base64.getDecoder().decode(enc);
            byte[] iv = new byte[IV_LEN];
            System.arraycopy(all, 0, iv, 0, IV_LEN);
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(TAG_BITS, iv));
            byte[] pt = cipher.doFinal(all, IV_LEN, all.length - IV_LEN);
            return new String(pt, StandardCharsets.UTF_8);
        } catch (Exception e) {
            return "";
        }
    }

    public static String mask(String value) {
        if (value == null || value.isEmpty()) return value;
        int at = value.indexOf('@');
        if (at > 0) {
            String local = value.substring(0, at);
            String shown = local.length() <= 2 ? local.substring(0, 1) : local.substring(0, 2);
            return shown + "***" + value.substring(at);
        }
        if (value.length() <= 4) return "****";
        return value.substring(0, value.length() - 4).replaceAll(".", "*") + value.substring(value.length() - 4);
    }
}
