package at.procon.dip.domain.document.service;

import at.procon.dip.domain.document.dto.GenericDocumentAttributeResponse;
import at.procon.dip.domain.document.dto.GenericDocumentDetailResponse;
import at.procon.dip.domain.document.dto.GenericDocumentRepresentationResponse;
import at.procon.dip.domain.document.dto.GenericDocumentSourceResponse;
import at.procon.dip.domain.document.entity.Document;
import at.procon.dip.domain.document.repository.DocumentAttributeRepository;
import at.procon.dip.domain.document.repository.DocumentRepository;
import at.procon.dip.domain.document.repository.DocumentSourceRepository;
import at.procon.dip.domain.document.repository.DocumentTextRepresentationRepository;
import java.util.Optional;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class GenericDocumentReadService {

    private final DocumentRepository documentRepository;
    private final DocumentAttributeRepository documentAttributeRepository;
    private final DocumentSourceRepository documentSourceRepository;
    private final DocumentTextRepresentationRepository documentTextRepresentationRepository;

    public Optional<GenericDocumentDetailResponse> findById(UUID documentId) {
        return documentRepository.findById(documentId).map(this::toResponse);
    }

    private GenericDocumentDetailResponse toResponse(Document document) {
        return new GenericDocumentDetailResponse(
                document.getId(),
                document.getOwnerTenant() == null ? null : document.getOwnerTenant().getTenantKey(),
                document.getVisibility(),
                document.getDocumentType(),
                document.getDocumentFamily(),
                document.getStatus(),
                document.getTitle(),
                document.getSummary(),
                document.getLanguageCode(),
                document.getMimeType(),
                document.getBusinessKey(),
                document.getDedupHash(),
                document.getCreatedAt(),
                document.getUpdatedAt(),
                documentAttributeRepository.findByDocument_IdOrderByAttributeName_AttributeContextAscAttributeName_AttributeNameAsc(document.getId())
                        .stream()
                        .map(attribute -> new GenericDocumentAttributeResponse(
                                attribute.getId(),
                                attribute.getAttributeName().getAttributeName(),
                                attribute.getAttributeName().getNormalizedName(),
                                attribute.getAttributeName().getAttributeContext(),
                                attribute.getAttributeName().getAttributeValueType(),
                                attribute.getStringValue(),
                                attribute.getIntegerValue(),
                                attribute.getNumberValue(),
                                attribute.getDateValue(),
                                attribute.getDatetimeValue(),
                                attribute.getBooleanValue(),
                                attribute.getCreatedAt()
                        ))
                        .toList(),
                documentSourceRepository.findByDocument_Id(document.getId()).stream()
                        .map(source -> new GenericDocumentSourceResponse(
                                source.getId(),
                                source.getSourceType(),
                                source.getExternalSourceId(),
                                source.getSourceUri(),
                                source.getSourceFilename(),
                                source.getParentSourceId(),
                                source.getImportBatchId(),
                                source.getReceivedAt(),
                                source.getCreatedAt()
                        ))
                        .toList(),
                documentTextRepresentationRepository.findByDocument_Id(document.getId()).stream()
                        .map(representation -> new GenericDocumentRepresentationResponse(
                                representation.getId(),
                                representation.getRepresentationType(),
                                representation.getBuilderKey(),
                                representation.getLanguageCode(),
                                representation.getTokenCount(),
                                representation.getCharCount(),
                                representation.getChunkIndex(),
                                representation.getChunkStartOffset(),
                                representation.getChunkEndOffset(),
                                representation.isPrimaryRepresentation(),
                                representation.getContent() == null ? null : representation.getContent().getId(),
                                preview(representation.getTextBody()),
                                representation.getCreatedAt()
                        ))
                        .toList()
        );
    }

    private String preview(String textBody) {
        if (textBody == null) {
            return null;
        }
        return textBody.length() <= 400 ? textBody : textBody.substring(0, 400);
    }
}
