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

import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.LegalBasisEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.RuleSetEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierTemplateEntity;
import com.iqser.red.service.persistence.management.v1.processor.migration.Migration;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.LegalBasisMappingPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.RulesPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DossierTemplateRepository;
import com.iqser.red.service.persistence.service.v1.api.shared.model.RuleFileType;
import com.knecon.fforesight.tenantcommons.TenantContext;

import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

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

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Setter
@Service
public class V30TechnicalNameRuleFileMigration extends Migration {

    private final DossierTemplateRepository dossierTemplateRepository;
    private final RulesPersistenceService rulesPersistenceService;
    private final LegalBasisMappingPersistenceService legalBasisMappingPersistenceService;

    private static final String NAME = "Migration for replacing legal basis reasons with technical names in rule files";
    private static final long VERSION = 30;


    public V30TechnicalNameRuleFileMigration(DossierTemplateRepository dossierTemplateRepository,
                                             RulesPersistenceService rulesPersistenceService,
                                             LegalBasisMappingPersistenceService legalBasisMappingPersistenceService) {

        super(NAME, VERSION);
        this.dossierTemplateRepository = dossierTemplateRepository;
        this.rulesPersistenceService = rulesPersistenceService;
        this.legalBasisMappingPersistenceService = legalBasisMappingPersistenceService;
    }


    @Override
    protected void migrate() {

        log.info("Migration: Updating rule files by replacing legal basis reasons with technical names");
        updateRuleFiles();
    }


    private void updateRuleFiles() {

        List<DossierTemplateEntity> dossierTemplates = dossierTemplateRepository.findAll();
        String tenantId = TenantContext.getTenantId();

        dossierTemplates.parallelStream()
                .forEach(dossierTemplate -> {
                    TenantContext.setTenantId(tenantId);
                    String dossierTemplateId = dossierTemplate.getId();

                    List<LegalBasisEntity> legalBasisMappings = legalBasisMappingPersistenceService.getLegalBasisMapping(dossierTemplateId);

                    if (legalBasisMappings == null || legalBasisMappings.isEmpty()) {
                        log.warn("No legal basis mappings found for dossierTemplateId: {}", dossierTemplateId);
                        return;
                    }

                    Map<String, String> reasonToTechnicalNameMap = legalBasisMappings.stream()
                            .filter(lb -> StringUtils.isNotBlank(lb.getReason()) && StringUtils.isNotBlank(lb.getTechnicalName()) && !lb.getReason().equals(lb.getTechnicalName()))
                            .collect(Collectors.toMap(LegalBasisEntity::getReason, LegalBasisEntity::getTechnicalName, (existing, replacement) -> replacement));

                    if (reasonToTechnicalNameMap.isEmpty()) {
                        log.warn("No valid mappings to replace for dossierTemplateId: {}", dossierTemplateId);
                        return;
                    }

                    Optional<RuleSetEntity> optionalRuleSet = rulesPersistenceService.getRules(dossierTemplateId, RuleFileType.ENTITY);

                    if (optionalRuleSet.isPresent()) {
                        String originalRulesContent = optionalRuleSet.get().getValue();
                        String updatedRulesContent = replaceReasonsWithTechnicalNames(originalRulesContent, reasonToTechnicalNameMap);

                        if (!updatedRulesContent.equals(originalRulesContent)) {
                            rulesPersistenceService.setRules(updatedRulesContent, dossierTemplateId, RuleFileType.ENTITY);
                            log.info("Updated rule file for dossierTemplateId: {}", dossierTemplateId);
                        } else {
                            log.info("No replacements made for dossierTemplateId: {}", dossierTemplateId);
                        }
                    } else {
                        log.warn("No rule set found for dossierTemplateId: {}", dossierTemplateId);
                    }
                });
    }


    private String replaceReasonsWithTechnicalNames(String rulesContent, Map<String, String> reasonToTechnicalNameMap) {

        String rulesContentResult = rulesContent;
        for (Map.Entry<String, String> entry : reasonToTechnicalNameMap.entrySet()) {
            String reason = entry.getKey();
            String technicalName = entry.getValue();
            rulesContentResult = StringUtils.replace(rulesContentResult, quoteString(reason), quoteString(technicalName));
        }
        return rulesContentResult;
    }


    private static String quoteString(String string) {

        return "\"" + string + "\"";
    }

}
