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

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

import org.springframework.stereotype.Service;

import com.iqser.red.service.persistence.management.v1.processor.dataexchange.models.FileExchangeImportModel;
import com.iqser.red.service.persistence.management.v1.processor.dataexchange.models.ImportTemplateResult;
import com.iqser.red.service.persistence.management.v1.processor.dataexchange.models.TemplateImportInfo;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.ReportTemplateEntity;
import com.iqser.red.service.persistence.management.v1.processor.exception.BadRequestException;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.ReportTemplatePersistenceService;
import com.iqser.red.service.persistence.service.v1.api.shared.model.ImportResponse;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.Dossier;

import io.micrometer.observation.ObservationRegistry;
import io.micrometer.observation.annotation.Observed;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;

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

    DossierTemplateImportService dossierTemplateImportService;
    DossierImportService dossierImportService;
    FileExchangeArchivalService fileExchangeArchivalService;
    ReportTemplatePersistenceService reportTemplateService;
    ObservationRegistry registry;


    @Observed(name = "FileExchangeImportService", contextualName = "import-files")
    public ImportResponse importFileExchangeArchive(String userId, byte[] archive) {

        long start = System.currentTimeMillis();
        log.info("Starting file import for user {}", userId);
        FileExchangeImportModel fileExchangeImportModel = fileExchangeArchivalService.readFileExchangeArchive(archive, userId);
        log.info("Parsed file import archive with {} dossiers and {} files",
                 fileExchangeImportModel.getDossiers().size(),
                 fileExchangeImportModel.getFiles().values()
                         .stream()
                         .mapToLong(Collection::size).sum());
        String dossierTemplateId = importFileExchangeModel(fileExchangeImportModel, userId);
        log.info("Finished file import with template id {} for user {} in {} ms", dossierTemplateId, userId, System.currentTimeMillis() - start);

        enrichObservation(userId, archive, fileExchangeImportModel);

        return new ImportResponse(dossierTemplateId);
    }


    private String importFileExchangeModel(FileExchangeImportModel fileExchangeImportModel, String userId) {

        ImportTemplateResult importTemplateResult = fileExchangeImportModel.getImportTemplateResult();

        if (importTemplateResult == null) {
            throw new BadRequestException("DossierTemplate not present in import archive.");
        }

        TemplateImportInfo templateImportInfo = dossierTemplateImportService.importDossierTemplate(importTemplateResult);

        List<String> allReportTemplateIds = reportTemplateService.findByDossierTemplateId(templateImportInfo.getDossierTemplateId())
                .stream()
                .map(ReportTemplateEntity::getTemplateId)
                .toList();

        for (Dossier dossierToImport : fileExchangeImportModel.getDossiers()) {
            dossierImportService.importDossier(fileExchangeImportModel, userId, dossierToImport, templateImportInfo, allReportTemplateIds);
        }
        return templateImportInfo.getDossierTemplateId();
    }


    private void enrichObservation(String userId, byte[] archive, FileExchangeImportModel importModel) {

        if (registry.getCurrentObservation() != null) {
            registry.getCurrentObservation()
                    .highCardinalityKeyValue("archive-size", String.valueOf(archive.length))
                    .highCardinalityKeyValue("user", userId)
                    .highCardinalityKeyValue("number of files",
                                             String.valueOf(importModel.getFiles().values()
                                                                    .stream()
                                                                    .mapToInt(List::size).sum()))
                    .highCardinalityKeyValue("number of dossiers", String.valueOf(importModel.getDossiers().size()));
        }
    }


}
