package com.erp.util;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

/**
 * Node.js PasswordEncryption (utils/passwordEncryption.ts) 와 호환되는 Java 구현.
 *
 * 알고리즘: AES-256-CBC
 * 키 유도:  scrypt(secret, "salt", N=16384, r=8, p=1, dkLen=32)
 * 저장 형식: iv_hex:ciphertext_hex
 *
 * external_db_connections.password 컬럼 복호화에 사용.
 */
public class PasswordEncryption {

    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";

    private final byte[] key;

    public PasswordEncryption(String secretKey) {
        this.key = CredentialEncryption.SCrypt.generate(
                secretKey.getBytes(StandardCharsets.UTF_8),
                "salt".getBytes(StandardCharsets.UTF_8),
                16384, 8, 1, 32);
    }

    /** 평문 → iv_hex:ciphertext_hex */
    public String encrypt(String plaintext) {
        try {
            byte[] iv = new byte[16];
            new java.security.SecureRandom().nextBytes(iv);

            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE,
                    new SecretKeySpec(key, "AES"),
                    new IvParameterSpec(iv));
            byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));

            return toHex(iv) + ":" + toHex(ciphertext);
        } catch (Exception e) {
            throw new RuntimeException("암호화 실패: " + e.getMessage(), e);
        }
    }

    private static String toHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) sb.append(String.format("%02x", b));
        return sb.toString();
    }

    /** iv_hex:ciphertext_hex → 평문 */
    public String decrypt(String encryptedPassword) {
        try {
            String[] parts = encryptedPassword.split(":");
            if (parts.length != 2) throw new IllegalArgumentException("잘못된 암호화 형식 (expected iv:ciphertext)");

            byte[] iv         = fromHex(parts[0]);
            byte[] ciphertext = fromHex(parts[1]);

            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE,
                    new SecretKeySpec(key, "AES"),
                    new IvParameterSpec(iv));
            return new String(cipher.doFinal(ciphertext), StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("복호화 실패: " + e.getMessage(), e);
        }
    }

    private static byte[] fromHex(String hex) {
        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i + 1), 16));
        }
        return data;
    }
}
