package uk.ac.ebi.subs.api.controllers;

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.Resource;
import org.springframework.security.access.method.P;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import uk.ac.ebi.subs.data.fileupload.FileStatus;
import uk.ac.ebi.subs.repository.model.ProcessingStatus;
import uk.ac.ebi.subs.repository.repos.fileupload.FileRepository;
import uk.ac.ebi.subs.repository.repos.status.ProcessingStatusRepository;
import uk.ac.ebi.subs.validator.data.ValidationResult;
import uk.ac.ebi.subs.validator.data.structures.GlobalValidationStatus;
import uk.ac.ebi.subs.validator.repository.ValidationResultRepository;
import uk.ac.ebi.subs.validator.repository.ValidatorResultRepositoryCustom;

import java.util.List;
import java.util.Map;

import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;

@RestController
@RequiredArgsConstructor
public class SubmissionBlockersSummaryController {

    @NonNull
    private FileRepository fileRepository;
    @NonNull
    private ValidatorResultRepositoryCustom validatorResultRepositoryCustom;
    @NonNull
    private ValidationResultRepository validationResultRepository;
    @NonNull
    private ProcessingStatusRepository processingStatusRepository;

    @GetMapping(value = "/submissions/{submissionId}/submissionBlockersSummary")
    public Resource<SubmissionBlockersSummary> getSubmissionContentsIssuesSummary(@PathVariable @P("submissionId") String submissionId) {
        SubmissionBlockersSummary submissionBlockersSummary = new SubmissionBlockersSummary();

        getFileIssues(submissionId, submissionBlockersSummary);
        getMetadataIssues(submissionId, submissionBlockersSummary);
        checkSubmissionEmptiness(submissionId, submissionBlockersSummary);
        checkPendingValidationResults(submissionId, submissionBlockersSummary);

        Resource<SubmissionBlockersSummary> submissionIssuesSummaryResource = new Resource<>(submissionBlockersSummary);

        Link selfLink = linkTo(methodOn(
                this.getClass()).getSubmissionContentsIssuesSummary(submissionId)
        ).withSelfRel();

        submissionIssuesSummaryResource.add(selfLink);

        return submissionIssuesSummaryResource;
    }



    private void getFileIssues(String submissionId, SubmissionBlockersSummary submissionBlockersSummary) {
        submissionBlockersSummary.notReadyFileCount = fileRepository.countBySubmissionIdAndStatusNot(submissionId, FileStatus.READY_FOR_ARCHIVE);
    }

    private void getMetadataIssues(String submissionId, SubmissionBlockersSummary submissionBlockersSummary) {
        submissionBlockersSummary.setValidationIssuesPerDataTypeId(
                validatorResultRepositoryCustom.validationIssuesPerDataTypeId(submissionId));
    }

    private void checkSubmissionEmptiness(String submissionId, SubmissionBlockersSummary submissionBlockersSummary) {
        List<ValidationResult> validationResults = validationResultRepository.findAllBySubmissionId(submissionId);
        List<ProcessingStatus> processingStatuses = processingStatusRepository.findBySubmissionId(submissionId);

        if (validationResults.size() == 0 || processingStatuses.size() == 0) {
            submissionBlockersSummary.setEmptySubmission(true);
        }
    }

    private void checkPendingValidationResults(String submissionId, SubmissionBlockersSummary submissionBlockersSummary) {
        submissionBlockersSummary.anyPendingValidationResult =
                validationResultRepository.countBySubmissionIdAndValidationStatusIs(submissionId, GlobalValidationStatus.Pending) > 0;
    }

    @Data
    class SubmissionBlockersSummary {
        long notReadyFileCount;
        @JsonInclude(content= JsonInclude.Include.NON_EMPTY)
        Map<String, Integer> validationIssuesPerDataTypeId;
        boolean emptySubmission;
        boolean anyPendingValidationResult;
    }
}

@@ -169,16 +169,87 @@
 ructor;%0A
+import org.springframework.data.rest.webmvc.ResourceNotFoundException;%0A
 import o
@@ -281,16 +281,16 @@
 s.Link;%0A
-
 import o
@@ -604,32 +604,81 @@
 oad.FileStatus;%0A
+import uk.ac.ebi.subs.repository.model.DataType;%0A
 import uk.ac.ebi
@@ -710,32 +710,91 @@
 ocessingStatus;%0A
+import uk.ac.ebi.subs.repository.repos.DataTypeRepository;%0A
 import uk.ac.ebi
@@ -1192,16 +1192,42 @@
 ustom;%0A%0A
+import java.util.HashMap;%0A
 import j
@@ -1817,16 +1817,80 @@
 ository;
+%0A    @NonNull%0A    private DataTypeRepository dataTypeRepository;
 %0A%0A    @G
@@ -3253,117 +3253,996 @@
     
-submissionBlockersSummary.setValidationIssuesPerDataTypeId(%0A                validatorResultRepositoryCustom.v
+Map%3CString, Integer%3E validationIssuesPerDataTypeId =%0A                validatorResultRepositoryCustom.validationIssuesPerDataTypeId(submissionId);%0A        Map%3CString, Map%3CString, Object%3E%3E validationBlockersByDataTypeId = new HashMap%3C%3E();%0A%0A        validationIssuesPerDataTypeId.forEach((dataTypeId, count) -%3E %7B%0A            DataType dataType = dataTypeRepository.findOne(dataTypeId);%0A%0A            if (dataType == null) %7B%0A                throw new ResourceNotFoundException();%0A            %7D%0A%0A            String dataTypeDisplayName = dataType.getDisplayNamePlural();%0A%0A            Map%3CString, Object%3E blockerDataTypeProperties = new HashMap%3C%3E();%0A            blockerDataTypeProperties.put(%22displayName%22, dataTypeDisplayName);%0A            blockerDataTypeProperties.put(%22count%22, count);%0A%0A            validationBlockersByDataTypeId.put(dataTypeId, blockerDataTypeProperties);%0A%0A            submissionBlockersSummary.totalMetadataBlockers += count;%0A        %7D);%0A%0A        submissionBlockersSummary.setV
 alid
@@ -4270,22 +4270,39 @@
 eId(
-submission
+validationBlockersByDataType
 Id)
-)
 ;%0A  
@@ -5294,39 +5294,51 @@
     Map%3CString, 
-Integer
+Map%3CString, Object%3E
 %3E validationIssu
@@ -5354,16 +5354,52 @@
 TypeId;%0A
+        long totalMetadataBlockers;%0A
         

Rework validation blockers by dataType Id structure and add display name