"""
Tests for item meta tags.
"""

import unittest

import elementpath  # For XPath 2.0 selectors.
from lxml import etree
from kerko.views.item.creators import format_creator_name

from tests.integration_testing import SynchronizedTestCase


class CreatorNameTestCase(unittest.TestCase):
    """Unit test for creator name formatting."""

    def test_creator_empty(self):
        self.assertEqual(
            format_creator_name({}),
            '',
        )

    def test_creator_single_field(self):
        self.assertEqual(
            format_creator_name({'name': 'Full name'}),
            'Full name',
        )

    def test_creator_single_field_empty(self):
        self.assertEqual(
            format_creator_name({'name': ''}),
            '',
        )

    def test_creator_two_fields(self):
        self.assertEqual(
            format_creator_name({'firstName': 'FirstName', 'lastName': 'LastName'}),
            'LastName, FirstName',
        )

    def test_creator_two_fields_empty(self):
        self.assertEqual(
            format_creator_name({'firstName': '', 'lastName': ''}),
            '',
        )


class ItemMetaTestCase(SynchronizedTestCase):
    """Integration tests for item meta tags."""

    def test_highwire_press_book(self):
        """Test Highwire Press tags for a 'book' item."""

        with self.app.test_client() as client:
            response = client.get(f'{self.URL_PREFIX}/2351708-TAQ6HCSL', follow_redirects=True)
            self.assertEqual(response.status_code, 200)

            parser = etree.HTMLParser()
            tree = etree.fromstring(response.get_data(as_text=True), parser)
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_title"]/@content'),
                ['A book with multiple authors'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_publication_date"]/@content'),
                ['2019'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_date"]/@content'),
                ['2019'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_year"]/@content'),
                ['2019'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_author"]/@content'),
                [
                    'Mustermann, Erika',
                    'Jacques, Pierre-Jean',
                    'Pérez, Juan',
                    'Doe, John',
                    'Roe, Richard',
                    'Smith, Jane',
                    'Kumar, Ashok',
                ],
                # Google Scholar requires that only the actual authors be included.
                # Thus, 'Jansen, Jan' (Editor) is excluded.
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_language"]/@content'),
                ['en'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_publisher"]/@content'),
                ['Example Publishing'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_isbn"]/@content'),
                ['979-8292-9-6571-8'],
            )
            unexpected_tags = [
                'citation_doi',
                'citation_issn',
                'citation_volume',
                'citation_issue',
                'citation_pdf_url',
                'citation_firstpage',
                'citation_lastpage',
                'citation_conference_title',
                'citation_journal_title',
                'citation_dissertation_institution',
                'citation_technical_report_institution',
                'citation_technical_report_number',
            ]
            self.assertEqual(
                elementpath.select(
                    tree,
                    f'/html/head/meta[matches(@name, "{"|".join(unexpected_tags)}")]/@name'
                ),
                [],
                "Tag is unexpected for this particular item, or for 'book' items in general"
            )

    def test_highwire_press_conference_paper(self):
        """Test Highwire Press tags for a 'conferencePaper' item."""

        with self.app.test_client() as client:
            response = client.get(f'{self.URL_PREFIX}/2351708-99VVIN8V', follow_redirects=True)
            self.assertEqual(response.status_code, 200)

            parser = etree.HTMLParser()
            tree = etree.fromstring(response.get_data(as_text=True), parser)
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_title"]/@content'),
                ['A conference paper'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_publication_date"]/@content'),
                ['2021-11-10'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_date"]/@content'),
                ['2021-11-10'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_year"]/@content'),
                ['2021'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_author"]/@content'),
                ['Hoe, Harry'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_language"]/@content'),
                ['en'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_publisher"]/@content'),
                ['Example Publishing'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_firstpage"]/@content'),
                ['11'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_lastpage"]/@content'),
                ['55'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_conference_title"]/@content'),
                ['First Example Conference, 2021'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_doi"]/@content'),
                ['10.5555/2351708-99VVIN8V'],
            )
            unexpected_tags = [
                'citation_isbn',
                'citation_issn',
                'citation_volume',
                'citation_issue',
                'citation_pdf_url',
                'citation_journal_title',
                'citation_dissertation_institution',
                'citation_technical_report_institution',
                'citation_technical_report_number',
                "Tag is unexpected for this particular item, "
                "or for 'conferencePaper' items in general"
            ]
            self.assertEqual(
                elementpath.select(
                    tree,
                    f'/html/head/meta[matches(@name, "{"|".join(unexpected_tags)}")]/@name'
                ),
                [],
            )

    def test_highwire_press_journal_article(self):
        """Test Highwire Press tags for a 'journalArticle' item."""

        with self.app.test_client() as client:
            response = client.get(f'{self.URL_PREFIX}/2351708-NW89E453', follow_redirects=True)
            self.assertEqual(response.status_code, 200)

            parser = etree.HTMLParser()
            tree = etree.fromstring(response.get_data(as_text=True), parser)
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_title"]/@content'),
                ['Zotero: information management software 2.0'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_publication_date"]/@content'),
                ['2011-06-07'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_date"]/@content'),
                ['2011-06-07'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_year"]/@content'),
                ['2011'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_author"]/@content'),
                ['Fernandez, Peter'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_volume"]/@content'),
                ['28'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_issue"]/@content'),
                ['4'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_language"]/@content'),
                ['en'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_firstpage"]/@content'),
                ['5'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_lastpage"]/@content'),
                ['7'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_journal_title"]/@content'),
                ['Library Hi Tech News'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_doi"]/@content'),
                ['10.1108/07419051111154758'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_issn"]/@content'),
                ['0741-9058'],
            )
            self.assertTrue(
                elementpath.select(
                    tree,
                    f'/html/head/meta[@name="citation_pdf_url"][matches(@content, '
                    f'"https?://[^/]+{self.URL_PREFIX}/[A-Z0-9]+/download/[A-Z0-9]+/Fernandez'
                    f'%20-%202011%20-%20Zotero%20information%20management%20software%202.0.pdf")]'
                ),
                "Incorrect PDF URL"
            )
            unexpected_tags = [
                'citation_isbn',
                'citation_publisher',
                'citation_conference_title',
                'citation_dissertation_institution',
                'citation_technical_report_institution',
                'citation_technical_report_number',
            ]
            self.assertEqual(
                elementpath.select(
                    tree,
                    f'/html/head/meta[matches(@name, "{"|".join(unexpected_tags)}")]/@name'
                ),
                [],
                "Tag is unexpected for this particular item, or for 'journalArticle' items in general"
            )

    def test_highwire_press_report(self):
        """Test Highwire Press tags for a 'report' item."""

        with self.app.test_client() as client:
            response = client.get(f'{self.URL_PREFIX}/2351708-DNFRSHFB', follow_redirects=True)
            self.assertEqual(response.status_code, 200)

            parser = etree.HTMLParser()
            tree = etree.fromstring(response.get_data(as_text=True), parser)
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_title"]/@content'),
                ['A report with a DOI in the Extra field'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_publication_date"]/@content'),
                ['2019'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_date"]/@content'),
                ['2019'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_year"]/@content'),
                ['2019'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_author"]/@content'),
                ['Doe, John'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_language"]/@content'),
                ['en'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_technical_report_institution"]/@content'),
                ['Example Institution'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_technical_report_number"]/@content'),
                ['10'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_doi"]/@content'),
                ['10.5555/2351708-DNFRSHFB'],
            )
            unexpected_tags = [
                'citation_isbn',
                'citation_issn',
                'citation_pdf_url',
                'citation_volume',
                'citation_issue',
                'citation_firstpage',
                'citation_lastpage',
                'citation_publisher',
                'citation_journal_title',
                'citation_conference_title',
                'citation_dissertation_institution',
            ]
            self.assertEqual(
                elementpath.select(
                    tree,
                    f'/html/head/meta[matches(@name, "{"|".join(unexpected_tags)}")]/@name'
                ),
                [],
                "Tag is unexpected for this particular item, or for 'report' items in general"
            )

    def test_highwire_press_thesis(self):
        """Test Highwire Press tags for a 'thesis' item."""

        with self.app.test_client() as client:
            response = client.get(f'{self.URL_PREFIX}/2351708-9TCEM5BE', follow_redirects=True)
            self.assertEqual(response.status_code, 200)

            parser = etree.HTMLParser()
            tree = etree.fromstring(response.get_data(as_text=True), parser)
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_title"]/@content'),
                ['A thesis example'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_publication_date"]/@content'),
                ['2015-05-15'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_date"]/@content'),
                ['2015-05-15'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_year"]/@content'),
                ['2015'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_author"]/@content'),
                ['Hoe, Harry'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_language"]/@content'),
                ['en'],
            )
            self.assertEqual(
                tree.xpath('/html/head/meta[@name="citation_dissertation_institution"]/@content'),
                ['Small University'],
            )
            unexpected_tags = [
                'citation_doi',
                'citation_isbn',
                'citation_issn',
                'citation_pdf_url',
                'citation_volume',
                'citation_issue',
                'citation_firstpage',
                'citation_lastpage',
                'citation_publisher',
                'citation_journal_title',
                'citation_conference_title',
                'citation_technical_report_institution',
                'citation_technical_report_number',
            ]
            self.assertEqual(
                elementpath.select(
                    tree,
                    f'/html/head/meta[matches(@name, "{"|".join(unexpected_tags)}")]/@name'
                ),
                [],
                "Tag is unexpected for this particular item, or for 'thesis' items in general"
            )

    def test_highwire_press_webpage(self):
        """Test Highwire Press tags for a 'webpage' item."""

        with self.app.test_client() as client:
            response = client.get(f'{self.URL_PREFIX}/4507457-YE4WVE35', follow_redirects=True)
            self.assertEqual(response.status_code, 200)

            parser = etree.HTMLParser()
            tree = etree.fromstring(response.get_data(as_text=True), parser)
            self.assertEqual(
                elementpath.select(
                    tree,
                    '/html/head/meta[matches(@name, "citation_.+")]/@name'
                ),
                [],
                "Only book, conferencePaper, journalArticle, report, or thesis "
                "items are allowed to have Highwire Press tags"
            )

    # TODO: Test item with empty title/author/date.
