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

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.TestPropertySource;

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.peristence.v1.server.integration.service.DossierTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;

import feign.FeignException;
import lombok.SneakyThrows;

@TestPropertySource(properties = {
        "spring.servlet.multipart.max-file-size=50MB",
        "spring.servlet.multipart.max-request-size=50MB"
})
public class ZipFileUploadTest extends AbstractPersistenceServerServiceTest {

    @Autowired
    private DossierTesterAndProvider dossierTesterAndProvider;

    @Autowired
    private UploadClient uploadClient;

    @Autowired
    private FileClient fileClient;

    @SneakyThrows
    @Test
    void testZipUploadWithEntryCountCheck() {

        var dossier = dossierTesterAndProvider.provideTestDossier();

        var smallZipResource = new ClassPathResource("files/zip/ArchiveWithManyFiles.zip");
        var smallZip = new MockMultipartFile(
                "ArchiveWithManyFiles.zip",
                "ArchiveWithManyFiles.zip",
                "application/zip",
                IOUtils.toByteArray(smallZipResource.getInputStream())
        );

        var uploadResult = uploadClient.upload(smallZip, dossier.getId(), false, false);

        assertNotNull(uploadResult, "Upload result for small zip should not be null.");
        assertEquals(9993, uploadResult.getFileIds().size());

        var largeZipResource = new ClassPathResource("files/zip/ArchiveWithTooManyFiles.zip");
        var largeZip = new MockMultipartFile(
                "ArchiveWithTooManyFiles.zip",
                "ArchiveWithTooManyFiles.zip",
                "application/zip",
                IOUtils.toByteArray(largeZipResource.getInputStream())
        );

        FeignException ex = assertThrows(
                FeignException.class,
                () -> uploadClient.upload(largeZip, dossier.getId(), false, false),
                "Uploading a zip with more than 10000 entries should throw a FeignException."
        );

        assertEquals(400, ex.status(), "Expected HTTP 400 (Bad Request) for a ZIP bomb scenario");
        assertTrue(ex.getMessage().contains("ZIP-Bomb detected"),
                   "Exception message should contain 'ZIP-Bomb detected' or similar.");

        var filesInDossier = fileClient.getDossierStatus(dossier.getId());
        assertEquals(9993, filesInDossier.size());
    }
}

