package at.procon.dip.ingestion.service;

import at.procon.dip.domain.access.DocumentAccessContext;
import at.procon.dip.domain.document.CanonicalDocumentMetadata;
import at.procon.dip.domain.document.RelationType;
import at.procon.dip.domain.document.SourceType;
import at.procon.dip.domain.document.entity.Document;
import at.procon.dip.domain.document.service.DocumentRelationService;
import at.procon.dip.domain.document.service.command.CreateDocumentRelationCommand;
import at.procon.dip.ingestion.config.DipIngestionProperties;
import at.procon.dip.ingestion.dto.ImportedDocumentResult;
import at.procon.dip.ingestion.service.TedPackageExpansionService.TedPackageEntry;
import at.procon.dip.ingestion.spi.OriginalContentStoragePolicy;
import at.procon.dip.ingestion.spi.SourceDescriptor;
import at.procon.dip.ingestion.config.DipIngestionProperties;
import at.procon.dip.ingestion.service.IngestionInternalAttributes;
import at.procon.dip.runtime.condition.ConditionalOnRuntimeMode;
import at.procon.dip.runtime.config.RuntimeMode;
import java.time.OffsetDateTime;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
@ConditionalOnRuntimeMode(RuntimeMode.NEW)
@RequiredArgsConstructor
public class TedPackageChildImportProcessor {

    private final GenericDocumentImportService importService;
    private final DocumentRelationService relationService;
    private final DipIngestionProperties properties;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public ChildImportResult processChild(UUID packageDocumentId,
                                          String packageSourceIdentifier,
                                          OffsetDateTime packageReceivedAt,
                                          DocumentAccessContext accessContext,
                                          TedPackageEntry entry,
                                          int sortOrder) {
        String childUri = "tedpkg://" + packageSourceIdentifier + "/" + entry.archivePath();
        String childIdentifier = packageSourceIdentifier + ":" + entry.archivePath();
        String xmlContent = entry.textUtf8() != null && !entry.textUtf8().isBlank()
                ? entry.textUtf8()
                : new String(entry.data(), java.nio.charset.StandardCharsets.UTF_8);

        Map<String, String> childAttributes = new LinkedHashMap<>();
        childAttributes.put("documentTypeHint", "TED_NOTICE");
        childAttributes.put("packageId", packageSourceIdentifier);
        childAttributes.put("archivePath", entry.archivePath());
        childAttributes.put("title", entry.fileName());
        childAttributes.put("importBatchId", properties.getTedPackageImportBatchId());
        if (properties.isTedPackageDeferLexicalIndexing()) {
            childAttributes.put(IngestionInternalAttributes.DEFER_LEXICAL_INDEX, Boolean.TRUE.toString());
        }

        ImportedDocumentResult childResult = importService.importDocument(new SourceDescriptor(
                accessContext == null ? DocumentAccessContext.publicDocument() : accessContext,
                SourceType.PACKAGE_CHILD,
                childIdentifier,
                childUri,
                entry.fileName(),
                "application/xml",
                entry.data(),
                xmlContent,
                packageReceivedAt == null ? OffsetDateTime.now() : packageReceivedAt,
                OriginalContentStoragePolicy.STORE,
                childAttributes
        ));

        Document childDocument = childResult.document();
        relationService.ensureRelation(new CreateDocumentRelationCommand(
                packageDocumentId,
                childDocument.getId(),
                RelationType.EXTRACTED_FROM,
                sortOrder,
                entry.archivePath()
        ));

        CanonicalDocumentMetadata childMetadata = childDocument.toCanonicalMetadata();

        if (childResult.deduplicated()) {
            return ChildImportResult.success(childDocument.getId(), childMetadata,
                    "TED XML child already existed and was linked to package: " + entry.archivePath());
        }
        return ChildImportResult.success(childDocument.getId(), childMetadata,
                childResult.warnings() == null || childResult.warnings().isEmpty() ? null : String.join(" | ", childResult.warnings()));
    }

    public record ChildImportResult(UUID childDocumentId, CanonicalDocumentMetadata childDocumentMetadata, String warning) {
        public static ChildImportResult success(UUID childDocumentId, CanonicalDocumentMetadata childDocumentMetadata, String warning) {
            return new ChildImportResult(childDocumentId, childDocumentMetadata, warning);
        }

        public static ChildImportResult warning(String warning) {
            return new ChildImportResult(null, null, warning);
        }
    }
}
