package com.iqser.red.service.persistence.management.v1.processor.service;

import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;

import com.google.common.collect.Sets;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileModel;

import io.micrometer.observation.annotation.Observed;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;

@Service
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class DossierIdFileIdRequestValidator {

    DossierManagementService dossierManagementService;
    FileStatusManagementService fileStatusManagementService;


    @Observed(name = "DossierIdFileIdRequestValidator", contextualName = "validate-request")
    public void validateRequestOrThrow404(String dossierTemplateId, Set<String> dossierIds, Set<String> fileIds) {

        if (!dossierIds.isEmpty()) {
            Set<String> availableDossierIds = new HashSet<>(dossierManagementService.findAllDossierIdsInDossierTemplateId(dossierTemplateId, dossierIds));
            Set<String> nonAvailableDossiers = Sets.difference(dossierIds, availableDossierIds);
            if (!nonAvailableDossiers.isEmpty()) {
                throw new NotFoundException(String.format("Dossier Ids %s are not available in dossier template %s", String.join(", ", nonAvailableDossiers), dossierTemplateId));
            }
        }

        if (!fileIds.isEmpty()) {
            Set<FileModel> availableFiles = fileStatusManagementService.findAllByIds(fileIds)
                    .stream()
                    .filter(fileModel -> dossierIds.isEmpty() || dossierIds.contains(fileModel.getDossierId()))
                    .collect(Collectors.toSet());

            Set<String> mentionedDossierIds = availableFiles.stream()
                    .map(FileModel::getDossierId)
                    .collect(Collectors.toSet());

            Set<String> availableDossierIds = new HashSet<>(dossierManagementService.findAllDossierIdsInDossierTemplateId(dossierTemplateId, mentionedDossierIds));

            Set<String> availableFileIds = availableFiles.stream()
                    .filter(file -> availableDossierIds.contains(file.getDossierId()))
                    .map(FileModel::getId)
                    .collect(Collectors.toSet());

            Set<String> nonAvailableFiles = Sets.difference(fileIds, availableFileIds);

            if (!nonAvailableFiles.isEmpty() && dossierIds.isEmpty()) {
                throw new NotFoundException(String.format("File Ids %s are not found in dossier template %s", String.join(", ", nonAvailableFiles), dossierTemplateId));
            }

            if (!nonAvailableFiles.isEmpty()) {
                throw new NotFoundException(String.format("File Ids %s are not found in any of the dossiers %s in dossier template %s",
                                                          String.join(", ", nonAvailableFiles),
                                                          String.join(", ", dossierIds),
                                                          dossierTemplateId));
            }
        }
    }

}
