package p.packer.services;

import p.packer.dtos.PackerAssetDetailsDTO;
import p.packer.dtos.PackerAssetActionAvailabilityDTO;
import p.packer.dtos.PackerAssetIdentityDTO;
import p.packer.dtos.PackerAssetSummaryDTO;
import p.packer.dtos.PackerCodecConfigurationFieldDTO;
import p.packer.dtos.PackerDiagnosticDTO;
import p.packer.messages.assets.OutputCodecCatalog;
import p.packer.models.PackerAssetActionAvailability;
import p.packer.models.PackerAssetDetails;
import p.packer.models.PackerAssetIdentity;
import p.packer.models.PackerAssetSummary;
import p.packer.models.PackerCodecConfigurationField;
import p.packer.models.PackerDiagnostic;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public final class PackerReadMessageMapper {
    private PackerReadMessageMapper() {
    }

    public static PackerAssetSummaryDTO toAssetSummaryDTO(PackerAssetSummary summary) {
        return new PackerAssetSummaryDTO(
                summary.assetReference(),
                toAssetIdentityDTO(summary.identity()),
                summary.state(),
                summary.buildParticipation(),
                summary.assetFamily(),
                summary.preloadEnabled(),
                summary.hasDiagnostics());
    }

    public static PackerAssetDetailsDTO toAssetDetailsDTO(PackerAssetDetails details) {
        return new PackerAssetDetailsDTO(
                toAssetSummaryDTO(details.summary()),
                details.outputFormat(),
                details.outputCodec(),
                details.availableOutputCodecs(),
                toCodecConfigurationFieldsByCodecDTO(details.codecConfigurationFieldsByCodec()),
                details.inputsByRole(),
                toDiagnosticDTOs(details.diagnostics()));
    }

    public static List<PackerAssetSummaryDTO> toAssetSummaryDTOs(List<PackerAssetSummary> summaries) {
        return summaries.stream().map(PackerReadMessageMapper::toAssetSummaryDTO).toList();
    }

    public static List<PackerDiagnosticDTO> toDiagnosticDTOs(List<PackerDiagnostic> diagnostics) {
        return diagnostics.stream().map(PackerReadMessageMapper::toDiagnosticDTO).toList();
    }

    public static List<PackerAssetActionAvailabilityDTO> toAssetActionAvailabilityDTOs(
            List<PackerAssetActionAvailability> actions) {
        return actions.stream().map(PackerReadMessageMapper::toAssetActionAvailabilityDTO).toList();
    }

    private static PackerAssetIdentityDTO toAssetIdentityDTO(PackerAssetIdentity identity) {
        return new PackerAssetIdentityDTO(
                identity.assetId(),
                identity.assetUuid(),
                identity.assetName(),
                identity.assetRoot());
    }

    private static Map<OutputCodecCatalog, List<PackerCodecConfigurationFieldDTO>> toCodecConfigurationFieldsByCodecDTO(
            Map<OutputCodecCatalog, List<PackerCodecConfigurationField>> fieldsByCodec) {
        return fieldsByCodec.entrySet().stream().collect(Collectors.toMap(
                Map.Entry::getKey,
                entry -> entry.getValue().stream().map(PackerReadMessageMapper::toCodecConfigurationFieldDTO).toList(),
                (left, right) -> left,
                java.util.LinkedHashMap::new));
    }

    private static PackerCodecConfigurationFieldDTO toCodecConfigurationFieldDTO(PackerCodecConfigurationField field) {
        return new PackerCodecConfigurationFieldDTO(
                field.key(),
                field.label(),
                field.fieldType(),
                field.value(),
                field.required(),
                field.options());
    }

    private static PackerDiagnosticDTO toDiagnosticDTO(PackerDiagnostic diagnostic) {
        return new PackerDiagnosticDTO(
                diagnostic.severity(),
                diagnostic.category(),
                diagnostic.message(),
                diagnostic.evidencePath(),
                diagnostic.blocking());
    }

    private static PackerAssetActionAvailabilityDTO toAssetActionAvailabilityDTO(
            PackerAssetActionAvailability action) {
        return new PackerAssetActionAvailabilityDTO(
                action.action(),
                action.enabled(),
                action.visible(),
                action.reason());
    }
}
