package kz.konturai.parser.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

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

@Service
public class EncryptionService {

    private static final Logger logger = LoggerFactory.getLogger(EncryptionService.class);
    private static final String ALGORITHM = "AES";
    private static final int KEY_SIZE = 256;

    private final SecretKey secretKey;

    public EncryptionService(@Value("${encryption.secret-key:}") String secretKeyBase64) {
        SecretKey key;
        if (secretKeyBase64 != null && !secretKeyBase64.isEmpty()) {
            try {
                byte[] keyBytes = Base64.getDecoder().decode(secretKeyBase64);
                // If decoded key is exactly 32 bytes (256 bits), use it directly
                // Otherwise, derive a 32-byte key using SHA-256
                if (keyBytes.length == 32) {
                    key = new SecretKeySpec(keyBytes, ALGORITHM);
                } else {
                    // Derive a proper 32-byte key using SHA-256
                    MessageDigest sha = MessageDigest.getInstance("SHA-256");
                    byte[] derivedKey = sha.digest(keyBytes);
                    key = new SecretKeySpec(derivedKey, ALGORITHM);
                    logger.info("Derived AES-256 key from provided secret (original length: {} bytes)",
                            keyBytes.length);
                }
            } catch (Exception e) {
                logger.warn("Failed to decode encryption key from config, generating new one", e);
                key = generateKey();
            }
        } else {
            logger.warn(
                    "Encryption secret key not configured, generating temporary key. This should be configured in production!");
            key = generateKey();
        }
        this.secretKey = key;
    }

    private SecretKey generateKey() {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
            keyGenerator.init(KEY_SIZE, new SecureRandom());
            return keyGenerator.generateKey();
        } catch (Exception e) {
            logger.error("Failed to generate encryption key", e);
            throw new RuntimeException("Failed to initialize encryption service", e);
        }
    }

    public String encrypt(String plainText) {
        if (plainText == null || plainText.isEmpty()) {
            return plainText;
        }

        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception e) {
            logger.error("Failed to encrypt data", e);
            throw new RuntimeException("Encryption failed", e);
        }
    }

    public String decrypt(String encryptedText) {
        if (encryptedText == null || encryptedText.isEmpty()) {
            return encryptedText;
        }

        try {
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            logger.error("Failed to decrypt data", e);
            throw new RuntimeException("Decryption failed", e);
        }
    }
}
