package ru.yandex.webmaster3.storage.turbo.service.commerce;

import java.security.Key;
import java.util.Base64;
import java.util.concurrent.ThreadLocalRandom;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * Created by Oleg Bazdyrev on 11/03/2020.
 */
@Slf4j
@Service("turboCommerceService")
public class TurboCommerceService {

    private static final String ENCRYPT_VERSION1 = "1";
    private static final String ENCRYPT_DELIMITER = ":";
    private static final String ENCRYPT_METHOD = "AES/CBC/PKCS5PADDING";

    private final Key bitrixSecretKey;

    @Autowired
    public TurboCommerceService(@Value("${webmaster3.storage.turbo.commerce.bitrixSecretKey}") String bitrixSecretKeyStr) {
        bitrixSecretKey = new SecretKeySpec(Base64.getDecoder().decode(bitrixSecretKeyStr), "AES");
    }

    public String encryptBitrixToken(String token) {
        Preconditions.checkArgument(!Strings.isNullOrEmpty(token), "token must be not empty");
        try {
            byte[] ivBytes = new byte[16];
            ThreadLocalRandom.current().nextBytes(ivBytes);
            Cipher cipher = Cipher.getInstance(ENCRYPT_METHOD);
            cipher.init(Cipher.ENCRYPT_MODE, bitrixSecretKey, new IvParameterSpec(ivBytes));
            byte[] encrypted = cipher.doFinal(token.getBytes());
            Base64.Encoder base64 = Base64.getEncoder();
            return ENCRYPT_VERSION1 + ENCRYPT_DELIMITER + base64.encodeToString(ivBytes) + ENCRYPT_DELIMITER + base64.encodeToString(encrypted);
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }

    public String decryptBitrixToken(String encrypted) {
        Preconditions.checkArgument(!Strings.isNullOrEmpty(encrypted), "token must be not empty");
        String[] parts = encrypted.split(ENCRYPT_DELIMITER);
        Preconditions.checkArgument(parts.length == 3, "wrong format");
        Preconditions.checkArgument(parts[0].equals(ENCRYPT_VERSION1), "unexpected version " + parts[0]);
        try {
            Base64.Decoder decoder = Base64.getDecoder();
            byte[] ivBytes = decoder.decode(parts[1]);
            byte[] encryptedBytes = decoder.decode(parts[2]);
            Cipher cipher = Cipher.getInstance(ENCRYPT_METHOD);
            cipher.init(Cipher.DECRYPT_MODE, bitrixSecretKey, new IvParameterSpec(ivBytes));
            String result = new String(cipher.doFinal(encryptedBytes));
            return result;
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }
}
