package at.procon.dip.embedding.service;

import at.procon.dip.domain.document.entity.DocumentEmbeddingPrefixProfile;
import at.procon.dip.domain.document.repository.DocumentEmbeddingPrefixProfileRepository;
import at.procon.dip.embedding.model.EmbeddingPrefixMode;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HexFormat;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class EmbeddingPrefixProfileService {

    private final DocumentEmbeddingPrefixProfileRepository repository;
    private final ConcurrentMap<String, UUID> idCache = new ConcurrentHashMap<>();

    @Transactional
    public UUID resolveProfileId(EmbeddingPrefixMode prefixMode, String appliedPrefix) {
        EmbeddingPrefixMode normalizedMode = prefixMode == null ? EmbeddingPrefixMode.OFF : prefixMode;
        String normalizedPrefix = appliedPrefix == null ? "" : appliedPrefix;
        String code = buildCode(normalizedMode, normalizedPrefix);

        UUID cached = idCache.get(code);
        if (cached != null) {
            return cached;
        }

        UUID resolved = repository.findByCode(code)
                .map(DocumentEmbeddingPrefixProfile::getId)
                .orElseGet(() -> repository.save(
                        DocumentEmbeddingPrefixProfile.builder()
                                .code(code)
                                .prefixMode(normalizedMode)
                                .prefixText(normalizedPrefix)
                                .build()
                ).getId());
        idCache.putIfAbsent(code, resolved);
        return resolved;
    }

    static String buildCode(EmbeddingPrefixMode prefixMode, String prefixText) {
        return prefixMode.name() + ":" + sha256Hex(prefixText == null ? "" : prefixText);
    }

    private static String sha256Hex(String value) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] bytes = digest.digest(value.getBytes(StandardCharsets.UTF_8));
            return HexFormat.of().formatHex(bytes);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("SHA-256 digest not available", e);
        }
    }
}
