package p.packer.models;

import com.fasterxml.jackson.databind.JsonNode;
import org.apache.commons.lang3.StringUtils;
import p.packer.messages.assets.AssetFamilyCatalog;
import p.packer.messages.assets.OutputCodecCatalog;
import p.packer.messages.assets.OutputFormatCatalog;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public record PackerAssetDeclaration(
        int schemaVersion,
        String assetUuid,
        String name,
        AssetFamilyCatalog assetFamily,
        List<PackerAssetArtifactSelection> artifacts,
        OutputFormatCatalog outputFormat,
        OutputCodecCatalog outputCodec,
        Map<String, String> outputMetadata,
        Map<String, JsonNode> outputPipelineMetadata,
        boolean preloadEnabled) {

    public PackerAssetDeclaration {
        if (schemaVersion <= 0) {
            throw new IllegalArgumentException("schemaVersion must be positive");
        }
        assetUuid = Objects.requireNonNull(assetUuid, "assetUuid").trim();
        name = Objects.requireNonNull(name, "name").trim();
        assetFamily = Objects.requireNonNull(assetFamily, "assetFamily");
        artifacts = List.copyOf(Objects.requireNonNull(artifacts, "artifacts"));
        outputFormat = Objects.requireNonNull(outputFormat, "outputFormat");
        outputCodec = Objects.requireNonNull(outputCodec, "outputCodec");
        outputMetadata = Map.copyOf(Objects.requireNonNull(outputMetadata, "outputMetadata"));
        outputPipelineMetadata = immutablePipelineMetadata(outputPipelineMetadata);
        if (StringUtils.isBlank(assetUuid) || StringUtils.isBlank(name)) {
            throw new IllegalArgumentException("declaration fields must not be blank");
        }
    }

    private static Map<String, JsonNode> immutablePipelineMetadata(Map<String, JsonNode> pipelineMetadata) {
        final Map<String, JsonNode> sanitized = new LinkedHashMap<>();
        Objects.requireNonNull(pipelineMetadata, "outputPipelineMetadata").forEach((key, value) -> {
            if (key == null || key.isBlank() || value == null) {
                return;
            }
            sanitized.put(key.trim(), value.deepCopy());
        });
        return Map.copyOf(sanitized);
    }
}
