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

import java.io.FileInputStream;
import java.nio.file.Files;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

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.TemplateImportInfo;
import com.iqser.red.service.persistence.management.v1.processor.service.ComponentLogService;
import com.iqser.red.service.persistence.management.v1.processor.service.FileManagementStorageService;
import com.iqser.red.service.persistence.management.v1.processor.utils.StorageIdUtils;
import com.knecon.fforesight.tenantcommons.TenantContext;

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 FileImportService {

    FileImportPersistenceService fileImportPersistenceService;
    FileManagementStorageService storageService;
    ComponentLogService componentLogService;


    @Observed(name = "FileImportService", contextualName = "import-files-in-parallel")
    public void importFilesInParallel(List<FileExchangeImportModel.FileImport> files, String userId, TemplateImportInfo templateImportInfo, String dossierId) {

        List<CompletableFuture<Void>> fileImportFutures = new LinkedList<>();

        String tenantId = TenantContext.getTenantId();

        for (FileExchangeImportModel.FileImport file : files) {
            fileImportFutures.add(CompletableFuture.supplyAsync(() -> {
                TenantContext.setTenantId(tenantId);
                importFile(userId, templateImportInfo, file, dossierId);
                return null;
            }));
        }
        fileImportFutures.forEach(CompletableFuture::join);
    }


    @Observed(name = "FileImportService", contextualName = "import-file")
    public void importFile(String userId, TemplateImportInfo templateImportInfo, FileExchangeImportModel.FileImport file, String dossierId) {

        // separate service for transactions
        String fileId = fileImportPersistenceService.saveFileToDb(userId, file, dossierId, templateImportInfo);

        file.getFilesToUpload()
                .forEach(fileToUpload -> {
                    try (FileInputStream in = new FileInputStream(fileToUpload.file().toFile())) {
                        storageService.storeObject(StorageIdUtils.getStorageId(dossierId, fileId, fileToUpload.fileType()), in);
                        Files.deleteIfExists(fileToUpload.file());
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                });
        if (file.getEntityLog() != null) {
            storageService.saveEntityLog(dossierId, fileId, file.getEntityLog());
        }
        if (file.getComponentLog() != null) {
            storageService.saveComponentLog(dossierId, fileId, file.getComponentLog());
        }
        if (file.getOverrides() != null) {
            file.getOverrides()
                    .forEach(componentOverride -> componentLogService.overrideComponent(dossierId, fileId, componentOverride));
        }
    }

}
