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

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

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.FileManagementStorageService;
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.imported.ImportedLegalBases;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedLegalBasis;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedRedaction;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedRedactionsPerPage;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class V31TechnicalNameImportedFilesMigration extends Migration {

    private static final String NAME = "Migration for replacing legal basis reasons with technical names in imported redactions and legal bases files";
    private static final long VERSION = 31;

    private final DossierRepository dossierRepository;
    private final FileRepository fileRepository;
    private final FileManagementStorageService fileManagementStorageService;
    private final LegalBasisMappingService legalBasisMappingService;


    public V31TechnicalNameImportedFilesMigration(DossierRepository dossierRepository,
                                                  FileRepository fileRepository,
                                                  FileManagementStorageService fileManagementStorageService,
                                                  LegalBasisMappingService legalBasisMappingService) {

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


    @Override
    protected void migrate() {

        log.info("Migration: Updating imported redactions and legal bases files by replacing legal basis reasons with technical names");

        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();

                if (fileManagementStorageService.objectExists(dossierId, fileId, FileType.IMPORTED_REDACTIONS)) {
                    ImportedRedactionsPerPage importedRedactions = fileManagementStorageService.getImportedRedactions(dossierId, fileId);

                    boolean updated = false;

                    for (ImportedRedaction redaction : importedRedactions.getImportedRedactions().values().stream().flatMap(Collection::stream).toList()) {
                        String currentLegalBasis = redaction.getLegalBasis();

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

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

                    }

                    if (updated) {
                        fileManagementStorageService.storeJSONObject(dossierId, fileId, FileType.IMPORTED_REDACTIONS, importedRedactions);
                        log.info("Updated imported redactions for dossierId: {}, fileId: {}", dossierId, fileId);
                    }
                }

                if (fileManagementStorageService.objectExists(dossierId, fileId, FileType.IMPORTED_LEGAL_BASES)) {
                    ImportedLegalBases importedLegalBases = fileManagementStorageService.getImportedLegalBases(dossierId, fileId);

                    boolean updated = false;

                    List<ImportedLegalBasis> legalBases = importedLegalBases.getImportedLegalBases();

                    for (ImportedLegalBasis importedLegalBasis : legalBases) {
                        String currentReason = importedLegalBasis.getReason();
                        String currentTechnicalName = importedLegalBasis.getTechnicalName();

                        if (currentTechnicalName == null || currentTechnicalName.isEmpty()) {
                            if (currentReason != null && !currentReason.isEmpty()) {
                                TechnicalNameResult result = legalBasisMappingService.processLegalBasis(currentReason, reasonToTechnicalNameMap);

                                if (result != null) {
                                    importedLegalBasis.setTechnicalName(result.technicalName());
                                    updated = true;
                                }
                            }
                        }
                    }

                    if (updated) {
                        fileManagementStorageService.storeJSONObject(dossierId, fileId, FileType.IMPORTED_LEGAL_BASES, importedLegalBases);
                        log.info("Updated imported legal bases for dossierId: {}, fileId: {}", dossierId, fileId);
                    }
                }
            }
        }

        log.info("Migration completed.");
    }

}
