package at.procon.ted.util;

import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Utility class for computing document hashes.
 * Uses SHA-256 for generating unique document identifiers.
 * 
 * @author Martin.Schweitzer@procon.co.at and claude.ai
 */
@Slf4j
public final class HashUtils {

    private static final char[] HEX_ARRAY = "0123456789abcdef".toCharArray();

    private HashUtils() {
        // Utility class, no instantiation
    }

    /**
     * Compute SHA-256 hash of the given content.
     * 
     * @param content The content to hash
     * @return Lowercase hex-encoded hash string (64 characters)
     */
    public static String computeSha256(String content) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hashBytes = digest.digest(content.getBytes(StandardCharsets.UTF_8));
            return bytesToHex(hashBytes);
        } catch (NoSuchAlgorithmException e) {
            // SHA-256 is always available in Java
            throw new RuntimeException("SHA-256 algorithm not available", e);
        }
    }

    /**
     * Compute SHA-256 hash of the given byte array.
     * 
     * @param content The content to hash
     * @return Lowercase hex-encoded hash string (64 characters)
     */
    public static String computeSha256(byte[] content) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hashBytes = digest.digest(content);
            return bytesToHex(hashBytes);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("SHA-256 algorithm not available", e);
        }
    }

    /**
     * Convert byte array to lowercase hexadecimal string.
     */
    private static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int i = 0; i < bytes.length; i++) {
            int v = bytes[i] & 0xFF;
            hexChars[i * 2] = HEX_ARRAY[v >>> 4];
            hexChars[i * 2 + 1] = HEX_ARRAY[v & 0x0F];
        }
        return new String(hexChars);
    }

    /**
     * Validate a hash string format.
     * 
     * @param hash The hash to validate
     * @return true if valid SHA-256 hex string
     */
    public static boolean isValidSha256(String hash) {
        if (hash == null || hash.length() != 64) {
            return false;
        }
        return hash.matches("^[a-f0-9]{64}$");
    }
}
