package com.iqser.red.service.peristence.v1.server.integration.service;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;

import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.iqser.red.service.peristence.v1.server.integration.client.FileClient;
import com.iqser.red.service.peristence.v1.server.integration.client.UploadClient;
import com.iqser.red.service.persistence.management.v1.processor.service.FileManagementStorageService;
import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusService;
import com.iqser.red.service.persistence.service.v1.api.shared.model.AnalyzeResult;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileStatus;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.Dossier;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.AddFileRequest;
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.RedactionLogEntry;
import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.section.SectionGrid;

import lombok.SneakyThrows;

@Service
public class FileTesterAndProvider {

    @Autowired
    private FileManagementStorageService fileManagementStorageService;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private UploadClient uploadClient;

    @Autowired
    private FileClient fileClient;

    @Autowired
    private FileStatusService fileStatusService;


    @SneakyThrows
    public FileStatus testAndProvideFile(Dossier dossier) {

        return testAndProvideFile(dossier, "test");
    }


    @SneakyThrows
    public FileStatus testAndProvideFile(Dossier dossier, String fileName) {

        var fileId = testAndProvideFileQuick(dossier, fileName);
        var file = fileClient.getFileStatus(dossier.getId(), fileId);

        assertThat(file.getFileId()).isNotBlank();

        assertThat(fileClient.getDossierStatus(dossier.getId()).size()).isGreaterThanOrEqualTo(1);

        fileManagementStorageService.storeJSONObject(dossier.getId(),
                file.getFileId(),
                FileType.REDACTION_LOG,
                new RedactionLog(1, 1, List.of(RedactionLogEntry.builder().id("annotationId").type("manual").value("value entry").build()), null, 0, 0, 0, 0));
        fileManagementStorageService.storeJSONObject(dossier.getId(), file.getFileId(), FileType.SECTION_GRID, new SectionGrid());
        fileManagementStorageService.storeObject(dossier.getId(), file.getFileId(), FileType.ORIGIN, new ByteArrayInputStream(objectMapper.writeValueAsBytes("bytes of the file")));

        return file;
    }


    @SneakyThrows
    public String testAndProvideFileQuick(Dossier dossier, String fileName) {

        var fileId = Base64.encodeBase64String((dossier.getId() + fileName).getBytes(StandardCharsets.UTF_8));

        AddFileRequest upload = new AddFileRequest(fileName, fileId, dossier.getId(), "1");
        fileManagementStorageService.storeObject(dossier.getId(), fileId, FileType.UNTOUCHED, new ByteArrayInputStream("test".getBytes(StandardCharsets.UTF_8)));
        var mff = new MockMultipartFile(fileName + ".pdf", fileName + ".pdf", "application/pdf", "lorem ipsum".getBytes());
        var uploadResult = uploadClient.upload(mff, dossier.getId(), false);

        return uploadResult.getFileIds().iterator().next();

    }


    public void markFileAsProcessed(String fileId) {

        AnalyzeResult result = new AnalyzeResult();
        result.setFileId(fileId);
        result.setNumberOfPages(100);
        result.setDictionaryVersion(1);
        result.setLegalBasisVersion(1);
        result.setRulesVersion(1);
        result.setDuration(1000);
        result.setDossierDictionaryVersion(1);
        result.setAnalysisNumber(1);
        result.setAnalysisVersion(1);
        fileStatusService.setStatusSuccessful(fileId, result);
        fileStatusService.setStatusProcessed(fileId);
    }

}
