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

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;

import org.springframework.stereotype.Service;

import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity;
import com.iqser.red.service.persistence.management.v1.processor.migration.LegalBasisMappingService;
import com.iqser.red.service.persistence.management.v1.processor.migration.LegalBasisMappingService.TechnicalNameResult;
import com.iqser.red.service.persistence.management.v1.processor.migration.Migration;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DossierRepository;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileRepository;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Change;
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.EntityLogLegalBasis;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.ManualChange;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.service.EntityLogMongoService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class V29TechnicalNameEntityLogMigration extends Migration {

    private final DossierRepository dossierRepository;
    private final FileRepository fileRepository;
    private final EntityLogMongoService entityLogMongoService;
    private final LegalBasisMappingService legalBasisMappingService;

    private static final String NAME = "Migration for technical name update in entity logs";
    private static final long VERSION = 29;


    public V29TechnicalNameEntityLogMigration(DossierRepository dossierRepository,
                                              FileRepository fileRepository,
                                              EntityLogMongoService entityLogMongoService,
                                              LegalBasisMappingService legalBasisMappingService) {

        super(NAME, VERSION);
        this.dossierRepository = dossierRepository;
        this.fileRepository = fileRepository;
        this.entityLogMongoService = entityLogMongoService;
        this.legalBasisMappingService = legalBasisMappingService;
    }


    @Override
    protected void migrate() {

        AtomicInteger totalEntriesProcessed = new AtomicInteger(0);
        AtomicInteger totalValuesHashed = new AtomicInteger(0);
        AtomicInteger totalValuesUpdatedNormally = new AtomicInteger(0);

        List<DossierEntity> dossiers = dossierRepository.findAll();

        for (DossierEntity dossier : dossiers) {
            String dossierId = dossier.getId();
            String dossierTemplateId = dossier.getDossierTemplateId();


            Map<String, String> reasonToTechnicalNameMap = legalBasisMappingService.getReasonToTechnicalNameMap(dossierTemplateId);

            List<FileEntity> files = fileRepository.findByDossierId(dossierId);

            for (FileEntity file : files) {
                String fileId = file.getId();

                Optional<EntityLog> optionalEntityLog = entityLogMongoService.findEntityLogByDossierIdAndFileId(dossierId, fileId);

                if (optionalEntityLog.isPresent()) {
                    EntityLog entityLog = optionalEntityLog.get();

                    List<EntityLogLegalBasis> legalBasisList = entityLog.getLegalBasis();
                    if (legalBasisList == null) {
                        legalBasisList = new java.util.ArrayList<>();
                        entityLog.setLegalBasis(legalBasisList);
                    }

                    boolean updated = false;

                    for (EntityLogEntry entry : entityLog.getEntityLogEntry()) {
                        totalEntriesProcessed.getAndIncrement();
                        String currentLegalBasis = entry.getLegalBasis();

                        if (currentLegalBasis != null && !currentLegalBasis.isEmpty()) {
                            TechnicalNameResult result = legalBasisMappingService.processLegalBasisAndEntityLogLegalBasisList(currentLegalBasis,
                                                                                                                                                       reasonToTechnicalNameMap,
                                                                                                                                                       legalBasisList);

                            if (result != null && !currentLegalBasis.equals(result.technicalName())) {
                                entry.setLegalBasis(result.technicalName());
                                updated = true;

                                if (result.hashed()) {
                                    totalValuesHashed.getAndIncrement();
                                } else {
                                    totalValuesUpdatedNormally.getAndIncrement();
                                }
                            }
                        }

                        if (entry.getChanges() != null) {
                            for (Change change : entry.getChanges()) {
                                updated |= updatePropertyChanges(change.getPropertyChanges(), reasonToTechnicalNameMap, legalBasisList);
                            }
                        }

                        if (entry.getManualChanges() != null) {
                            for (ManualChange manualChange : entry.getManualChanges()) {
                                updated |= updatePropertyChanges(manualChange.getPropertyChanges(), reasonToTechnicalNameMap, legalBasisList);
                            }
                        }
                    }

                    if (updated) {
                        entityLogMongoService.saveEntityLog(dossierId, fileId, entityLog);
                        log.info("Updated EntityLog for dossierId: {}, fileId: {}", dossierId, fileId);
                    }
                }
            }
        }

        log.info("Migration completed.");
        log.info("Total entries processed: {}", totalEntriesProcessed.get());
        log.info("Total values updated normally: {}", totalValuesUpdatedNormally.get());
        log.info("Total values hashed: {}", totalValuesHashed.get());
    }


    private boolean updatePropertyChanges(Map<String, String> propertyChanges, Map<String, String> reasonToTechnicalNameMap, List<EntityLogLegalBasis> legalBasisList) {

        boolean updated = false;
        if (propertyChanges != null && propertyChanges.containsKey("legalBasis")) {
            String legalBasisValue = propertyChanges.get("legalBasis");

            String updatedLegalBasisValue = legalBasisMappingService.processTextAndEntityLogLegalBasisList(legalBasisValue, reasonToTechnicalNameMap, legalBasisList);

            if (!legalBasisValue.equals(updatedLegalBasisValue)) {
                propertyChanges.put("legalBasis", updatedLegalBasisValue);
                updated = true;
            }
        }
        return updated;
    }

}
