package org.jabref.logic.xmp;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import org.jabref.logic.importer.ImportFormatPreferences;
import org.jabref.logic.importer.ParseException;
import org.jabref.logic.importer.fileformat.BibtexParser;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.LinkedFile;
import org.jabref.model.util.DummyFileUpdateMonitor;

import com.google.common.io.Resources;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.xmpbox.XMPMetadata;
import org.apache.xmpbox.schema.DublinCoreSchema;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Answers;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class XmpUtilReaderTest {

    private XmpPreferences xmpPreferences;
    private BibtexParser parser;

    /**
     * Create a temporary PDF-file with a single empty page.
     */
    @BeforeEach
    void setUp() {
        ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS);
        when(importFormatPreferences.getEncoding()).thenReturn(StandardCharsets.UTF_8);
        xmpPreferences = mock(XmpPreferences.class);
        // The code assumes privacy filters to be off
        when(xmpPreferences.isUseXMPPrivacyFilter()).thenReturn(false);

        when(xmpPreferences.getKeywordSeparator()).thenReturn(',');

        parser = new BibtexParser(importFormatPreferences, new DummyFileUpdateMonitor());
    }

    /**
     * Tests reading of dublinCore metadata.
     */
    @Test
    void testReadArticleDublinCoreReadRawXmp() throws IOException, URISyntaxException, ParseException {
        Path path = Path.of(XmpUtilShared.class.getResource("article_dublinCore.pdf").toURI());
        List<XMPMetadata> meta = XmpUtilReader.readRawXmp(path);

        DublinCoreSchema dcSchema = meta.get(0).getDublinCoreSchema();
        DublinCoreExtractor dcExtractor = new DublinCoreExtractor(dcSchema, xmpPreferences, new BibEntry());
        Optional<BibEntry> entry = dcExtractor.extractBibtexEntry();
        String bibString = Resources.toString(XmpUtilShared.class.getResource("article_dublinCore.bib"), StandardCharsets.UTF_8);
        Optional<BibEntry> entryFromBibFile = parser.parseSingleEntry(bibString);

        assertEquals(entryFromBibFile.get(), entry.get());
    }

    /**
     * Tests reading of dublinCore metadata.
     */
    @Test
    void testReadArticleDublinCoreReadXmp() throws IOException, URISyntaxException, ParseException {
        Path pathPdf = Path.of(XmpUtilShared.class.getResource("article_dublinCore.pdf").toURI());
        List<BibEntry> entries = XmpUtilReader.readXmp(pathPdf, xmpPreferences);
        BibEntry entry = entries.get(0);

        String bibString = Resources.toString(XmpUtilShared.class.getResource("article_dublinCore.bib"), StandardCharsets.UTF_8);
        Optional<BibEntry> entryFromBibFile = parser.parseSingleEntry(bibString);
        entryFromBibFile.get().setFiles(Arrays.asList(
                new LinkedFile("", "paper.pdf", "PDF"),
                new LinkedFile("", pathPdf.toAbsolutePath().toString(), "PDF"))
        );

        assertEquals(entryFromBibFile.get(), entry);
    }

    /**
     * Tests an pdf file with an empty metadata section.
     */
    @Test
    void testReadEmtpyMetadata() throws IOException, URISyntaxException {
        List<BibEntry> entries = XmpUtilReader.readXmp(Path.of(XmpUtilShared.class.getResource("empty_metadata.pdf").toURI()), xmpPreferences);
        assertEquals(Collections.emptyList(), entries);
    }

    /**
     * Test non XMP metadata. Metadata are included in the PDInformation
     */
    @Test
    void testReadPDMetadata() throws IOException, URISyntaxException, ParseException {
        Path pathPdf = Path.of(XmpUtilShared.class.getResource("PD_metadata.pdf").toURI());
        List<BibEntry> entries = XmpUtilReader.readXmp(pathPdf, xmpPreferences);

        String bibString = Resources.toString(XmpUtilShared.class.getResource("PD_metadata.bib"), StandardCharsets.UTF_8);
        Optional<BibEntry> entryFromBibFile = parser.parseSingleEntry(bibString);
        entryFromBibFile.get().setFiles(Collections.singletonList(
                new LinkedFile("", pathPdf.toAbsolutePath().toString(), "PDF"))
        );

        assertEquals(entryFromBibFile.get(), entries.get(0));
    }

    /**
     * Tests an pdf file with metadata which has no description section.
     */
    @Test
    void testGetXmpMetadataWithNoDescription() throws IOException, URISyntaxException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method method = XmpUtilReader.class.getDeclaredMethod("getXmpMetadata", PDDocument.class);
        method.setAccessible(true);
        List<XMPMetadata> entries = (List<XMPMetadata>) method.invoke(XmpUtilReader.class, PDDocument.load(XmpUtilShared.class.getResource("no_description_metadata.pdf").openStream()));
        method.setAccessible(false);
        assertEquals(Collections.emptyList(), entries);
    }
}

@@ -56,93 +56,8 @@
 on;%0A
-import java.lang.reflect.InvocationTargetException;%0Aimport java.lang.reflect.Method;%0A
 impo
@@ -607,53 +607,8 @@
 es;%0A
-import org.apache.pdfbox.pdmodel.PDDocument;%0A
 impo
@@ -4718,26 +4718,12 @@
 test
-GetXmpMetadataWith
+Read
 NoDe
@@ -4731,16 +4731,24 @@
 cription
+Metadata
 () throw
@@ -4784,326 +4784,73 @@
 tion
-, NoSuchMethodException, InvocationTargetException, IllegalAccessException %7B%0A        Method method = XmpUtilReader.class.getDeclaredMethod(%22getXmpMetadata%22, PDDocument.class);%0A        method.setAccessible(true);%0A        List%3CXMPMetadata%3E entries = (List%3CXMPMetadata%3E) method.invoke(XmpUtilReader.class, PDDocument.load
+ %7B%0A        List%3CBibEntry%3E entries = XmpUtilReader.readXmp(Path.of
 (Xmp
@@ -4913,58 +4913,32 @@
 f%22).
-openStream()));%0A        method.setAccessible(false
+toURI()), xmpPreferences
 );%0A 

Make test concise