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

import java.io.InputStream;

import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Service;

import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
import com.iqser.red.service.persistence.management.v1.processor.utils.StorageIdUtils;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.RedactionLog;
import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.imported.ImportedRedactions;
import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.section.SectionGrid;
import com.iqser.red.storage.commons.exception.StorageObjectDoesNotExist;
import com.iqser.red.storage.commons.service.StorageService;
import com.knecon.fforesight.tenantcommons.TenantContext;

import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@RequiredArgsConstructor
public class FileManagementStorageService {

    private final StorageService storageService;


    @SneakyThrows
    public byte[] getStoredObjectBytes(String dossierId, String fileId, FileType fileType) {

        return IOUtils.toByteArray(storageService.getObject(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, fileType)).getInputStream());
    }


    @SneakyThrows
    public byte[] getStoredObjectBytes(String storageId) {

        return IOUtils.toByteArray(storageService.getObject(TenantContext.getTenantId(), storageId).getInputStream());
    }


    public void storeObject(String dossierId, String fileId, FileType fileType, InputStream stream) {

        storageService.storeObject(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, fileType), stream);
    }


    public <T> void storeJSONObject(String dossierId, String fileId, FileType fileType, T jsonObject) {

        storageService.storeJSONObject(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, fileType), jsonObject);
    }


    public void storeObject(String storageId, InputStream data) {

        storageService.storeObject(TenantContext.getTenantId(), storageId, data);
    }


    public RedactionLog getRedactionLog(String dossierId, String fileId) {

        try {
            return storageService.readJSONObject(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, FileType.REDACTION_LOG), RedactionLog.class);
        } catch (StorageObjectDoesNotExist e) {
            log.debug("RedactionLog does not exist");
            throw new NotFoundException("RedactionLog does not exist");
        }
    }


    public SectionGrid getSectionGrid(String dossierId, String fileId) {

        try {
            return storageService.readJSONObject(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, FileType.SECTION_GRID), SectionGrid.class);
        } catch (StorageObjectDoesNotExist e) {
            log.debug("SectionGrid not available.");
            throw new NotFoundException("SectionGrid does not exist");
        } catch (Exception e) {
            throw new RuntimeException("Could not convert SectionGrid", e);
        }
    }


    public ImportedRedactions getImportedRedactions(String dossierId, String fileId) {

        try {
            return storageService.readJSONObject(TenantContext.getTenantId(),
                    StorageIdUtils.getStorageId(dossierId, fileId, FileType.IMPORTED_REDACTIONS),
                    ImportedRedactions.class);
        } catch (StorageObjectDoesNotExist e) {
            throw new NotFoundException("ImportedRedactions does not exist");
        } catch (Exception e) {
            throw new RuntimeException("Could not convert ImportedRedactions", e);
        }
    }


    public boolean objectExists(String dossierId, String fileId, FileType origin) {

        return storageService.objectExists(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, origin));
    }


    public void deleteObject(String dossierId, String fileId, FileType fileType) {

        storageService.deleteObject(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, fileType));
    }


    public void deleteObject(String storageId) {

        storageService.deleteObject(TenantContext.getTenantId(), storageId);
    }

}
