# COPYRIGHT NOTICE
# This file is part of the "Universal Biomedical Skills" project.
# Copyright (c) 2026 MD BABU MIA, PhD <md.babu.mia@mssm.edu>
# All Rights Reserved.
#
# This code is proprietary and confidential.
# Unauthorized copying of this file, via any medium is strictly prohibited.
#
# Provenance: Authenticated by MD BABU MIA

"""Tests for Europe PMC article fetching via DOI."""

import json
from unittest.mock import Mock, patch

import pytest

from biomcp.articles.fetch import _article_details, is_doi, is_pmid
from biomcp.articles.preprints import fetch_europe_pmc_article


class TestDOIDetection:
    """Test DOI and PMID detection functions."""

    def test_valid_dois(self):
        """Test that valid DOIs are correctly identified."""
        valid_dois = [
            "10.1101/2024.01.20.23288905",
            "10.1038/nature12373",
            "10.1016/j.cell.2023.05.001",
            "10.1126/science.abc1234",
        ]
        for doi in valid_dois:
            assert (
                is_doi(doi) is True
            ), f"Expected {doi} to be identified as DOI"
            assert (
                is_pmid(doi) is False
            ), f"Expected {doi} NOT to be identified as PMID"

    def test_valid_pmids(self):
        """Test that valid PMIDs are correctly identified."""
        valid_pmids = [
            "35271234",
            "12345678",
            "1",
            "999999999",
        ]
        for pmid in valid_pmids:
            assert (
                is_pmid(pmid) is True
            ), f"Expected {pmid} to be identified as PMID"
            assert (
                is_doi(pmid) is False
            ), f"Expected {pmid} NOT to be identified as DOI"

    def test_invalid_identifiers(self):
        """Test that invalid identifiers are rejected by both functions."""
        invalid_ids = [
            "PMC11193658",  # PMC ID
            "abc123",  # Random string
            "10.1101",  # Incomplete DOI
            "nature12373",  # DOI without prefix
            "",  # Empty string
        ]
        for identifier in invalid_ids:
            assert (
                is_doi(identifier) is False
            ), f"Expected {identifier} NOT to be identified as DOI"
            assert (
                is_pmid(identifier) is False
            ), f"Expected {identifier} NOT to be identified as PMID"


class TestEuropePMCFetch:
    """Test Europe PMC article fetching."""

    @pytest.mark.asyncio
    async def test_fetch_europe_pmc_article_success(self):
        """Test successful fetch from Europe PMC."""
        # Mock the response
        mock_response = Mock()
        mock_response.hitCount = 1
        mock_response.results = [
            Mock(
                id="PPR790987",
                source="PPR",
                pmid=None,
                pmcid=None,
                doi="10.1101/2024.01.20.23288905",
                title="Test Article Title",
                authorString="Author A, Author B, Author C",
                journalTitle=None,
                pubYear="2024",
                firstPublicationDate="2024-01-23",
                abstractText="This is the abstract text.",
            )
        ]

        with patch(
            "biomcp.articles.preprints.http_client.request_api"
        ) as mock_request:
            mock_request.return_value = (mock_response, None)

            result = await fetch_europe_pmc_article(
                "10.1101/2024.01.20.23288905", output_json=True
            )
            data = json.loads(result)

            assert len(data) == 1
            article = data[0]
            assert article["doi"] == "10.1101/2024.01.20.23288905"
            assert article["title"] == "Test Article Title"
            assert article["journal"] == "Preprint Server (preprint)"
            assert article["date"] == "2024-01-23"
            assert article["authors"] == ["Author A", "Author B", "Author C"]
            assert article["abstract"] == "This is the abstract text."
            assert article["source"] == "Europe PMC"
            assert article["pmid"] is None
            assert "europepmc.org" in article["pmc_url"]

    @pytest.mark.asyncio
    async def test_fetch_europe_pmc_article_not_found(self):
        """Test fetch when article is not found in Europe PMC."""
        mock_response = Mock()
        mock_response.hitCount = 0
        mock_response.results = []

        with patch(
            "biomcp.articles.preprints.http_client.request_api"
        ) as mock_request:
            mock_request.return_value = (mock_response, None)

            result = await fetch_europe_pmc_article(
                "10.1101/invalid.doi", output_json=True
            )
            data = json.loads(result)

            assert len(data) == 1
            assert data[0]["error"] == "Article not found in Europe PMC"

    @pytest.mark.asyncio
    async def test_fetch_europe_pmc_article_error(self):
        """Test fetch when Europe PMC API returns an error."""
        mock_error = Mock()
        mock_error.code = 500
        mock_error.message = "Internal Server Error"

        with patch(
            "biomcp.articles.preprints.http_client.request_api"
        ) as mock_request:
            mock_request.return_value = (None, mock_error)

            result = await fetch_europe_pmc_article(
                "10.1101/2024.01.20.23288905", output_json=True
            )
            data = json.loads(result)

            assert len(data) == 1
            assert data[0]["error"] == "Error 500: Internal Server Error"


class TestArticleDetailsRouting:
    """Test that _article_details correctly routes DOIs to Europe PMC."""

    @pytest.mark.asyncio
    async def test_doi_routes_to_europe_pmc(self):
        """Test that DOIs are routed to fetch_europe_pmc_article."""
        test_doi = "10.1101/2024.01.20.23288905"

        with patch(
            "biomcp.articles.preprints.fetch_europe_pmc_article"
        ) as mock_europe_pmc:
            mock_europe_pmc.return_value = "Europe PMC result"

            result = await _article_details("Test", test_doi)

            mock_europe_pmc.assert_called_once_with(test_doi, output_json=True)
            assert result == "Europe PMC result"

    @pytest.mark.asyncio
    async def test_pmid_routes_to_pubtator(self):
        """Test that PMIDs are routed to fetch_articles."""
        test_pmid = "35271234"

        with patch(
            "biomcp.articles.fetch.fetch_articles"
        ) as mock_fetch_articles:
            mock_fetch_articles.return_value = "PubTator result"

            result = await _article_details("Test", test_pmid)

            mock_fetch_articles.assert_called_once_with(
                [35271234], full=True, output_json=True
            )
            assert result == "PubTator result"

    @pytest.mark.asyncio
    async def test_invalid_identifier_returns_error(self):
        """Test that invalid identifiers return an error."""
        invalid_id = "PMC12345"

        result = await _article_details("Test", invalid_id)

        data = json.loads(result)
        assert len(data) == 1
        assert "Invalid identifier format" in data[0]["error"]
        assert "PMC12345" in data[0]["error"]

__AUTHOR_SIGNATURE__ = "9a7f3c2e-MD-BABU-MIA-2026-MSSM-SECURE"
