"""Tests for Thieme Medical Publishers dance function."""

import pytest
from unittest.mock import patch, Mock

from .common import BaseDanceTest
from metapub import PubMedFetcher
from metapub.findit.dances import the_doi_slide as the_thieme_tap
from metapub.exceptions import AccessDenied, NoPDFLink
from tests.fixtures import load_pmid_xml, THIEME_EVIDENCE_PMIDS


class TestThiemeTap(BaseDanceTest):
    """Test cases for Thieme Medical Publishers journal access."""

    def setUp(self):
        """Set up test fixtures."""
        super().setUp()
        self.fetch = PubMedFetcher()

    def test_thieme_tap_url_construction_recent(self):
        """Test 1: URL construction for recent article.
        
        PMID: 38048813 (PPmP)
        Expected: Should construct valid Thieme PDF URL with HTTP protocol
        """
        pma = self.fetch.article_by_pmid('38048813')
        
        assert pma.journal == 'Psychother Psychosom Med Psychol'
        assert pma.doi == '10.1055/a-2189-0166'
        print(f"Test 1 - Article info: {pma.journal}, DOI: {pma.doi}")

        # Test without verification (should always work for URL construction)
        url = the_thieme_tap(pma, verify=False)
        assert url is not None
        assert 'thieme-connect.de' in url
        assert '/products/ejournals/pdf/' in url
        assert pma.doi in url
        assert url.endswith('.pdf')
        
        expected_url = f"http://www.thieme-connect.de/products/ejournals/pdf/{pma.doi}.pdf"
        assert url == expected_url
        print(f"Test 1 - PDF URL: {url}")

    def test_thieme_tap_url_construction_s_prefix_pattern_a(self):
        """Test 2: URL construction for s-prefix DOI pattern.
        
        PMID: 25364329 (Evid Based Spine Care J)
        Expected: Should construct valid URL for Thieme article with s-prefix DOI
        """
        pma = self.fetch.article_by_pmid('25364329')
        
        assert pma.journal == 'Evid Based Spine Care J'
        assert pma.doi == '10.1055/s-0034-1387804'
        print(f"Test 2 - Article info: {pma.journal}, DOI: {pma.doi}")

        # Test URL construction for s-prefix DOI pattern
        url = the_thieme_tap(pma, verify=False)
        assert url is not None
        assert 'thieme-connect.de' in url
        assert pma.doi in url
        assert url.endswith('.pdf')
        
        expected_url = f"http://www.thieme-connect.de/products/ejournals/pdf/{pma.doi}.pdf"
        assert url == expected_url
        print(f"Test 2 - S-prefix DOI URL: {url}")

    def test_thieme_tap_url_construction_s_prefix_pattern_b(self):
        """Test 3: URL construction for s-prefix DOI pattern variant.
        
        PMID: 219391 (Neuropadiatrie)
        Expected: Should construct valid URL for s-prefix DOI pattern
        """
        pma = self.fetch.article_by_pmid('219391')
        
        assert pma.journal == 'Neuropadiatrie'
        assert pma.doi == '10.1055/s-0028-1085314'
        print(f"Test 3 - Article info: {pma.journal}, DOI: {pma.doi}")

        url = the_thieme_tap(pma, verify=False)
        assert url is not None
        assert 'thieme-connect.de' in url
        assert pma.doi in url
        assert url.endswith('.pdf')
        print(f"Test 3 - S-prefix DOI variant URL: {url}")

    @patch('metapub.findit.dances.generic.verify_pdf_url')
    def test_thieme_tap_successful_access_with_verification(self, mock_verify):
        """Test 4: Successful access with verification.
        
        PMID: 38048813 (PPmP)
        Expected: Should return PDF URL when verification passes
        """
        # Mock successful PDF verification
        mock_verify.return_value = True

        pma = self.fetch.article_by_pmid('38048813')
        
        # Test with verification - should return PDF URL
        url = the_thieme_tap(pma, verify=True)
        assert 'thieme-connect.de' in url
        assert '/products/ejournals/pdf/' in url
        assert '.pdf' in url
        
        # Verify that verify_pdf_url was called
        mock_verify.assert_called_once()
        print(f"Test 4 - Verified PDF URL: {url}")

    @patch('metapub.findit.dances.generic.verify_pdf_url')
    def test_thieme_tap_paywall_detection(self, mock_verify):
        """Test 5: Paywall detection via verification.
        
        Expected: Should detect paywall when PDF verification fails
        """
        # Mock verification raising AccessDenied (paywall detected)
        mock_verify.side_effect = AccessDenied('DENIED: Thieme url requires subscription')

        pma = self.fetch.article_by_pmid('36644330')  # Real Thieme article
        
        # Test with verification - should propagate AccessDenied
        with pytest.raises(AccessDenied) as exc_info:
            the_thieme_tap(pma, verify=True)
        
        assert 'DENIED' in str(exc_info.value)
        mock_verify.assert_called_once()
        print(f"Test 5 - Correctly detected paywall: {exc_info.value}")



    def test_thieme_tap_doi_patterns(self):
        """Test 8: Different DOI patterns work correctly with real PMIDs.
        
        Expected: Should handle both s-prefix and a-prefix DOIs
        """
        # Test s-prefix DOI patterns - real PMID from verified list
        pma_s = self.fetch.article_by_pmid('36644330')  # ACI open with s-prefix DOI
        assert pma_s.doi == '10.1055/s-0040-1721489'
        
        url_s = the_thieme_tap(pma_s, verify=False)
        assert 'thieme-connect.de' in url_s
        assert 's-0040-1721489' in url_s
        print(f"Test 8a - s-prefix DOI URL: {url_s}")
        
        # Test with another s-prefix DOI  
        pma_s2 = self.fetch.article_by_pmid('32894878')  # Methods Inf Med with s-prefix DOI
        assert pma_s2.doi == '10.1055/s-0040-1715580'
        
        url_s2 = the_thieme_tap(pma_s2, verify=False)
        assert 'thieme-connect.de' in url_s2
        assert 's-0040-1715580' in url_s2
        print(f"Test 8b - Another s-prefix DOI URL: {url_s2}")


def test_thieme_journal_recognition():
    """Test basic URL pattern works (simplified registry test)."""
    from metapub import PubMedFetcher
    from metapub.findit.dances import the_doi_slide as the_thieme_tap
    
    # Just test that the function works with real Thieme journals
    fetch = PubMedFetcher()
    
    # Test with a known Thieme article
    try:
        pma = fetch.article_by_pmid('38048813')  # PPmP journal
        if pma.doi and pma.doi.startswith('10.1055/'):
            url = the_thieme_tap(pma, verify=False)
            assert 'thieme-connect.de' in url
            assert '.pdf' in url
            print(f"✓ Thieme URL pattern works: {url}")
        else:
            print("⚠ Test article doesn't have expected Thieme DOI pattern")
    except Exception as e:
        print(f"⚠ Could not test with real article: {e}")


if __name__ == '__main__':
    # Run basic tests if executed directly
    test_instance = TestThiemeTap()
    test_instance.setUp()
    
    print("Running Thieme Medical Publishers tests...")
    print("\n" + "="*60)
    
    tests = [
        ('test_thieme_tap_url_construction_recent', 'Recent article URL construction'),
        ('test_thieme_tap_url_construction_s_prefix_pattern_a', 'S-prefix DOI pattern A'),
        ('test_thieme_tap_url_construction_s_prefix_pattern_b', 'S-prefix DOI pattern B'),
        ('test_thieme_tap_successful_access_with_verification', 'Successful access with verification'),
        ('test_thieme_tap_paywall_detection', 'Paywall detection via verification'),
        ('test_thieme_tap_doi_patterns', 'Different DOI patterns handling')
    ]
    
    for test_method, description in tests:
        try:
            getattr(test_instance, test_method)()
            print(f"✓ {description} works")
        except Exception as e:
            print(f"✗ {description} failed: {e}")
    
    try:
        test_thieme_journal_recognition()
        print("✓ Registry test passed: URL pattern recognition works")
    except Exception as e:
        print(f"✗ Registry test failed: {e}")
    
    print("\n" + "="*60)
    print("Test suite completed!")


class TestThiemeWithVerifiedPMIDs:
    """Test Thieme dance function with verified PMIDs from our system."""
    
    def test_thieme_verified_pmids_url_construction(self):
        """Test URL construction with actual verified PMIDs from Thieme system."""
        from metapub import PubMedFetcher
        
        # Verified PMIDs from thieme_medical_publishers_pmids.txt
        verified_pmids_with_dois = [
            ('36644330', '10.1055/s-0040-1721489'),  # ACI open
            ('37920232', '10.1055/s-0041-1729981'),  # ACI open
            ('32894878', '10.1055/s-0040-1715580'),  # Methods Inf Med
            ('38158213', '10.1055/s-0043-1777732'),  # Methods Inf Med
        ]
        
        fetch = PubMedFetcher()
        
        with patch('metapub.findit.dances.generic.verify_pdf_url') as mock_verify:
            mock_verify.return_value = True
            
            for pmid, expected_doi in verified_pmids_with_dois:
                try:
                    pma = fetch.article_by_pmid(pmid)
                    
                    # Verify the article has the expected DOI
                    assert pma.doi == expected_doi, f"PMID {pmid} DOI mismatch: expected {expected_doi}, got {pma.doi}"
                    
                    # Test URL construction
                    result = the_thieme_tap(pma, verify=True)
                    expected_url = f"http://www.thieme-connect.de/products/ejournals/pdf/{expected_doi}.pdf"
                    
                    assert result == expected_url, f"PMID {pmid} URL mismatch"
                    print(f"✓ PMID {pmid} ({pma.journal}): {result}")
                    
                except Exception as e:
                    print(f"⚠ PMID {pmid} failed: {e}")
                    # Don't fail the test for network issues, just warn
                    pass
    
    def test_thieme_sample_pmids_integration(self):
        """Integration test with sample PMIDs to ensure functionality."""
        from metapub import PubMedFetcher
        
        # Test just 2 PMIDs for lighter integration testing
        sample_pmids = [
            '36644330',  # Recent ACI open
            '32894878',  # Methods Inf Med
        ]
        
        fetch = PubMedFetcher()
        
        for pmid in sample_pmids:
            try:
                pma = fetch.article_by_pmid(pmid)
                
                if pma.doi and pma.doi.startswith('10.1055/'):
                    # Test without verification to avoid network calls
                    url = the_thieme_tap(pma, verify=False)
                    
                    assert 'thieme-connect.de' in url
                    assert '/products/ejournals/pdf/' in url
                    assert pma.doi in url
                    assert url.endswith('.pdf')
                    print(f"✓ Sample integration test PMID {pmid}: {url}")
                else:
                    print(f"⚠ PMID {pmid} doesn't have expected Thieme DOI pattern")
                    
            except Exception as e:
                print(f"⚠ Sample PMID {pmid} failed: {e}")
                # Don't fail for network issues


class TestThiemeXMLFixtures:
    """Test Thieme dance function with real XML fixtures."""

    def test_thieme_authentic_metadata_validation(self):
        """Validate authentic metadata from XML fixtures."""
        for pmid, expected in THIEME_EVIDENCE_PMIDS.items():
            pma = load_pmid_xml(pmid)
            
            assert pma.doi == expected['doi']
            assert pma.journal == expected['journal']
            assert pma.pmid == pmid
            assert pma.doi.startswith('10.1055/'), f"Thieme DOI must start with 10.1055/, got: {pma.doi}"
            
            print(f"✓ PMID {pmid}: {pma.journal} - {pma.doi}")

    def test_thieme_url_construction_without_verification(self):
        """Test URL construction using XML fixtures."""
        for pmid in THIEME_EVIDENCE_PMIDS.keys():
            pma = load_pmid_xml(pmid)
            
            result = the_thieme_tap(pma, verify=False)
            expected_url = f'http://www.thieme-connect.de/products/ejournals/pdf/{pma.doi}.pdf'
            assert result == expected_url
            
            print(f"✓ PMID {pmid} URL: {result}")

    @patch('metapub.findit.dances.generic.verify_pdf_url')
    def test_thieme_paywall_handling(self, mock_verify):
        """Test paywall detection."""
        mock_verify.side_effect = AccessDenied('Thieme subscription required')
        
        pma = load_pmid_xml('38048813')  # Use first test PMID
        
        with pytest.raises(AccessDenied):
            the_thieme_tap(pma, verify=True)

    def test_thieme_journal_coverage(self):
        """Test journal coverage across different Thieme publications."""
        journals_found = set()
        
        for pmid in THIEME_EVIDENCE_PMIDS.keys():
            pma = load_pmid_xml(pmid)
            journals_found.add(pma.journal)
        
        assert len(journals_found) >= 4
        expected_journals = {'Psychother Psychosom Med Psychol', 'Evid Based Spine Care J', 'Neuropadiatrie', 'ACI open', 'Methods Inf Med'}
        assert journals_found == expected_journals

    def test_thieme_doi_pattern_diversity(self):
        """Test DOI pattern diversity across Thieme eras."""
        doi_patterns = {'10.1055/a-': 'Recent articles', '10.1055/s-': 'Standard articles'}
        patterns_found = set()
        
        for pmid in THIEME_EVIDENCE_PMIDS.keys():
            pma = load_pmid_xml(pmid)
            
            for pattern in doi_patterns.keys():
                if pma.doi.startswith(pattern):
                    patterns_found.add(pattern)
                    break
        
        assert len(patterns_found) >= 2, f"Expected at least 2 DOI patterns, got: {patterns_found}"