package go.kr.project.api.internal.util;

import go.kr.project.api.config.properties.VmisProperties;
import lombok.Getter;
import lombok.Setter;

/**
 * Wrapper utility around legacy {@link NewGpkiUtil} using configuration from YAML.
 *
 * Notes:
 * - Place this class under src/main/java/util as requested.
 * - Uses Lombok for getters/setters.
 */
@Getter
@Setter
public class GpkiCryptoUtil {

    private String gpkiLicPath;
    private Boolean ldap; // null -> legacy default
    private String certFilePath;
    private String envCertFilePathName;
    private String envPrivateKeyFilePathName;
    private String envPrivateKeyPasswd;
    private String sigCertFilePathName;
    private String sigPrivateKeyFilePathName;
    private String sigPrivateKeyPasswd;
    private String myServerId;        // equals to certServerId (INFO system server cert id)
    private String targetServerIdList; // comma joined list (can be single id)

    private transient NewGpkiUtil delegate;

    public static GpkiCryptoUtil from(VmisProperties.GpkiProps props) throws Exception {
        GpkiCryptoUtil util = new GpkiCryptoUtil();
        util.setGpkiLicPath(props.getGpkiLicPath());
        util.setLdap(props.getLdap());
        util.setCertFilePath(props.getCertFilePath());
        util.setEnvCertFilePathName(props.getEnvCertFilePathName());
        util.setEnvPrivateKeyFilePathName(props.getEnvPrivateKeyFilePathName());
        util.setEnvPrivateKeyPasswd(props.getEnvPrivateKeyPasswd());
        util.setSigCertFilePathName(props.getSigCertFilePathName());
        util.setSigPrivateKeyFilePathName(props.getSigPrivateKeyFilePathName());
        util.setSigPrivateKeyPasswd(props.getSigPrivateKeyPasswd());
        util.setMyServerId(props.getCertServerId());
        // Accept single targetServerId but allow list if provided by YAML in future
        util.setTargetServerIdList(props.getTargetServerId());
        util.initialize();
        return util;
    }

    public void initialize() throws Exception {
        NewGpkiUtil g = new NewGpkiUtil();
        if (gpkiLicPath != null) g.setGpkiLicPath(gpkiLicPath);
        if (ldap != null) g.setIsLDAP(ldap);
        if (certFilePath != null) g.setCertFilePath(certFilePath);
        if (envCertFilePathName != null) g.setEnvCertFilePathName(envCertFilePathName);
        if (envPrivateKeyFilePathName != null) g.setEnvPrivateKeyFilePathName(envPrivateKeyFilePathName);
        if (envPrivateKeyPasswd != null) g.setEnvPrivateKeyPasswd(envPrivateKeyPasswd);
        if (sigCertFilePathName != null) g.setSigCertFilePathName(sigCertFilePathName);
        if (sigPrivateKeyFilePathName != null) g.setSigPrivateKeyFilePathName(sigPrivateKeyFilePathName);
        if (sigPrivateKeyPasswd != null) g.setSigPrivateKeyPasswd(sigPrivateKeyPasswd);
        if (myServerId != null) g.setMyServerId(myServerId);
        if (targetServerIdList != null) g.setTargetServerIdList(targetServerIdList);
        g.init();
        this.delegate = g;
    }

    public String encryptToBase64(String plain, String targetServerId, String charset) throws Exception {
        ensureInit();
        byte[] enc = delegate.encrypt(plain.getBytes(charset), targetServerId, true);
        return delegate.encode(enc);
    }

    public String decryptFromBase64(String base64, String charset) throws Exception {
        ensureInit();
        byte[] bin = delegate.decode(base64);
        byte[] dec = delegate.decrypt(bin);
        return new String(dec, charset);
    }

    public String signToBase64(String plain, String charset) throws Exception {
        ensureInit();
        byte[] sig = delegate.sign(plain.getBytes(charset));
        return delegate.encode(sig);
    }

    public String verifyAndExtractBase64(String signedBase64, String charset) throws Exception {
        ensureInit();
        byte[] signed = delegate.decode(signedBase64);
        byte[] data = delegate.validate(signed);
        return new String(data, charset);
    }

    private void ensureInit() {
        if (delegate == null) {
            throw new IllegalStateException("GpkiCryptoUtil is not initialized. Call initialize() or from(props).");
        }
    }
}
