package at.procon.dip.testsupport;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import org.junit.jupiter.api.Named;

public final class MailBundleTestSupport {

    private MailBundleTestSupport() {
    }

    public static final Map<String, List<String>> EXPECTED_ATTACHMENT_NAMES = Map.of(
            "sample-mail-01-basic-reporting.eml", List.of("sample-report.xlsx", "invoice-demo.pdf", "contacts.csv"),
            "sample-mail-02-office-and-text.eml", List.of("purchase-order.docx", "readme.txt", "metadata.json", "payload.xml"),
            "sample-mail-03-inline-image-and-files.eml", List.of("inline-logo.png", "overview.pdf", "contacts.csv"),
            "sample-mail-04-utf8-filenames.eml", List.of("prüfbericht.pdf", "данни.xlsx", "überblick.csv"),
            "sample-mail-05-generic-octet-stream.eml", List.of("generic-report.xlsx", "generic-invoice.pdf", "generic-data.csv")
    );

    public static Path extractBundleToTempDir() throws IOException {
        Path tempDir = Files.createTempDirectory("mail-bundle-");
        try (InputStream in = MailBundleTestSupport.class.getResourceAsStream("/mail/sample-eml-bundle.zip")) {
            if (in == null) {
                throw new IOException("Missing test resource /mail/sample-eml-bundle.zip");
            }
            Path zipPath = tempDir.resolve("sample-eml-bundle.zip");
            Files.copy(in, zipPath, StandardCopyOption.REPLACE_EXISTING);
            unzip(zipPath, tempDir);
        }
        return tempDir.resolve("eml_samples");
    }

    private static void unzip(Path zipPath, Path targetDir) throws IOException {
        try (java.util.zip.ZipInputStream zin = new java.util.zip.ZipInputStream(Files.newInputStream(zipPath))) {
            java.util.zip.ZipEntry entry;
            while ((entry = zin.getNextEntry()) != null) {
                Path out = targetDir.resolve(entry.getName()).normalize();
                if (!out.startsWith(targetDir)) {
                    throw new IOException("Zip slip attempt: " + entry.getName());
                }
                if (entry.isDirectory()) {
                    Files.createDirectories(out);
                } else {
                    Files.createDirectories(out.getParent());
                    Files.copy(zin, out, StandardCopyOption.REPLACE_EXISTING);
                }
                zin.closeEntry();
            }
        }
    }

    public static Stream<String> bundleMailNames() {
        return EXPECTED_ATTACHMENT_NAMES.keySet().stream().sorted();
    }

    public static Stream<Named<String>> namedBundleMailNames() {
        return bundleMailNames().map(name -> Named.of(name, name));
    }
}
