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

import static com.iqser.red.service.persistence.service.v1.api.shared.model.warning.WarningsComparatorUtils.WARNING_MODEL_COMPARATOR;

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

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.LegalBasisEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.LegalBasisMappingPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DossierRepository;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogEntry;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntryState;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntryType;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Position;
import com.iqser.red.service.persistence.service.v1.api.shared.model.warning.ApproveResponse;
import com.iqser.red.service.persistence.service.v1.api.shared.model.warning.WarningModel;
import com.iqser.red.service.persistence.service.v1.api.shared.model.warning.WarningType;

import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;

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

    EntityLogService entityLogService;
    LegalBasisMappingPersistenceService legalBasisMappingPersistenceService;
    DossierRepository dossierRepository;


    public ApproveResponse verifyApprovalOfFile(String dossierId, String fileId) {

        ApproveResponse approveResponse = new ApproveResponse();
        approveResponse.setFileId(fileId);
        EntityLog entityLog = entityLogService.getEntityLog(dossierId, fileId, true);
        List<EntityLogEntry> entityLogEntries = entityLog.getEntityLogEntry();
        List<LegalBasisEntity> legalBasisMappings = legalBasisMappingPersistenceService.getLegalBasisMapping(dossierRepository.findDossierTemplateId(dossierId));

        for (EntityLogEntry entry : entityLogEntries) {
            if (entry.getState().equals(EntryState.APPLIED) && !entry.getEntryType().equals(EntryType.IMAGE) && !entry.getEntryType().equals(EntryType.IMAGE_HINT)) {
                if (StringUtils.isEmpty(entry.getLegalBasis())) {
                    addWarning(entry, WarningType.LEGAL_BASIS_MISSING, approveResponse);
                } else {
                    var legalBasisEntity = legalBasisMappings.stream()
                            .filter(mapping -> mapping.getTechnicalName().equals(entry.getLegalBasis()))
                            .findFirst();
                    if (legalBasisEntity.isEmpty() || StringUtils.isEmpty(legalBasisEntity.get().getTechnicalName())) {
                        addWarning(entry, WarningType.UNMAPPED_JUSTIFICATION, approveResponse);
                    }
                }
            }
            if (entry.getState().equals(EntryState.PENDING)) {
                addWarning(entry, WarningType.PENDING_CHANGE, approveResponse);
            }
        }

        approveResponse.setHasWarnings(approveResponse.getFileWarnings() != null && !approveResponse.getFileWarnings().isEmpty());
        return approveResponse;
    }


    private void addWarning(EntityLogEntry entry, WarningType warningType, ApproveResponse approveResponse) {

        ArrayList<WarningModel> fileWarnings = approveResponse.getFileWarnings();
        WarningModel newFileWarning = WarningModel.builder()
                .id(entry.getId())
                .pages(entry.getPositions()
                               .stream()
                               .map(Position::getPageNumber)
                               .collect(Collectors.toSet()))
                .value(shortenValue(entry.getValue()))
                .warningType(warningType)
                .type(entry.getType())
                .build();
        fileWarnings.add(newFileWarning);
        fileWarnings.sort(WARNING_MODEL_COMPARATOR);
        approveResponse.setFileWarnings(fileWarnings);
        log.info("fileWarnigns: {}", approveResponse.getFileWarnings());
    }


    private String shortenValue(String value) {

        if (value.length() > 100) {
            return value.substring(0, 97) + "...";
        }
        return value;
    }

}
