package at.procon.dip.ingestion.service;

import at.procon.dip.ingestion.service.MailMessageExtractionService.MailAttachment;
import at.procon.dip.testsupport.MailBundleTestSupport;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import static org.junit.jupiter.api.Assertions.*;

class MailMessageExtractionServiceBundleTest {

    private static Path bundleRoot;

    private final MailMessageExtractionService service = new MailMessageExtractionService();

    @BeforeAll
    static void extractBundle() throws Exception {
        bundleRoot = MailBundleTestSupport.extractBundleToTempDir();
    }

    @ParameterizedTest(name = "parse {0}")
    @MethodSource("at.procon.dip.testsupport.MailBundleTestSupport#bundleMailNames")
    void parse_should_extract_expected_attachments_from_filesystem_bundle(String fileName) throws Exception {
        Path eml = bundleRoot.resolve("eml").resolve(fileName);
        byte[] rawMime = Files.readAllBytes(eml);

        MailMessageExtractionService.ParsedMailMessage parsed = service.parse(rawMime);

        assertNotNull(parsed.subject(), "subject should be parsed for " + fileName);
        assertNotNull(parsed.receivedAt(), "receivedAt should be parsed for " + fileName);
        assertFalse(parsed.attachments().isEmpty(), "attachments should be extracted for " + fileName);

        List<String> actualNames = parsed.attachments().stream().map(MailAttachment::fileName).toList();
        assertEquals(MailBundleTestSupport.EXPECTED_ATTACHMENT_NAMES.get(fileName), actualNames,
                "attachment filenames should match validation bundle for " + fileName);
    }

    @Test
    void parse_should_preserve_utf8_attachment_filenames() throws Exception {
        Path eml = bundleRoot.resolve("eml").resolve("sample-mail-04-utf8-filenames.eml");
        byte[] rawMime = Files.readAllBytes(eml);

        MailMessageExtractionService.ParsedMailMessage parsed = service.parse(rawMime);

        List<String> actualNames = parsed.attachments().stream().map(MailAttachment::fileName).toList();
        assertEquals(List.of("prüfbericht.pdf", "данни.xlsx", "überblick.csv"), actualNames);
        assertTrue(parsed.textBody().contains("UTF") || !parsed.textBody().isBlank(),
                "UTF-8 sample should produce a readable body");
    }

    @Test
    void parse_should_keep_octet_stream_attachments_in_bundle() throws Exception {
        Path eml = bundleRoot.resolve("eml").resolve("sample-mail-05-generic-octet-stream.eml");
        byte[] rawMime = Files.readAllBytes(eml);

        MailMessageExtractionService.ParsedMailMessage parsed = service.parse(rawMime);

        assertEquals(3, parsed.attachments().size());
        assertTrue(parsed.attachments().stream().allMatch(a -> a.contentType() != null && a.contentType().contains("application/octet-stream")));
    }
}
