#!/usr/bin/env python3
"""Get detailed information about a specific paper by ID."""

import argparse
import json
import urllib.request
import urllib.parse
import xml.etree.ElementTree as ET
import re

def get_semantic_scholar(paper_id: str) -> dict:
    """Get paper from Semantic Scholar by ID (paperId, DOI, arXiv ID, etc.)."""
    base_url = f"https://api.semanticscholar.org/graph/v1/paper/{paper_id}"
    params = {
        "fields": "title,authors,year,abstract,citationCount,referenceCount,url,openAccessPdf,externalIds,venue,publicationDate,fieldsOfStudy,citations,references"
    }
    url = f"{base_url}?{urllib.parse.urlencode(params)}"
    
    req = urllib.request.Request(url, headers={"User-Agent": "ResearchPaperSearch/1.0"})
    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            paper = json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        return {"error": f"Paper not found: {e.code}"}
    except Exception as e:
        return {"error": f"Semantic Scholar API error: {e}"}
    
    authors = [a.get("name", "") for a in paper.get("authors", [])]
    
    # Get top citations
    citations = []
    for c in paper.get("citations", [])[:5]:
        if c:
            citations.append({
                "title": c.get("title"),
                "year": c.get("year"),
                "authors": [a.get("name") for a in c.get("authors", [])[:2]]
            })
    
    # Get key references
    references = []
    for r in paper.get("references", [])[:5]:
        if r:
            references.append({
                "title": r.get("title"),
                "year": r.get("year"),
                "authors": [a.get("name") for a in r.get("authors", [])[:2]]
            })
    
    return {
        "source": "semantic_scholar",
        "id": paper.get("paperId"),
        "title": paper.get("title"),
        "authors": authors,
        "year": paper.get("year"),
        "venue": paper.get("venue"),
        "abstract": paper.get("abstract"),
        "citationCount": paper.get("citationCount"),
        "referenceCount": paper.get("referenceCount"),
        "url": paper.get("url"),
        "openAccessPdf": paper.get("openAccessPdf", {}).get("url") if paper.get("openAccessPdf") else None,
        "doi": paper.get("externalIds", {}).get("DOI"),
        "arxivId": paper.get("externalIds", {}).get("ArXiv"),
        "fieldsOfStudy": paper.get("fieldsOfStudy", []),
        "topCitations": citations,
        "keyReferences": references
    }

def get_arxiv(arxiv_id: str) -> dict:
    """Get paper from arXiv by ID."""
    # Clean ID (remove version if present for initial lookup)
    clean_id = re.sub(r'v\d+$', '', arxiv_id)
    
    url = f"http://export.arxiv.org/api/query?id_list={clean_id}"
    req = urllib.request.Request(url, headers={"User-Agent": "ResearchPaperSearch/1.0"})
    
    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            xml_data = resp.read().decode()
    except Exception as e:
        return {"error": f"arXiv API error: {e}"}
    
    ns = {"atom": "http://www.w3.org/2005/Atom", "arxiv": "http://arxiv.org/schemas/atom"}
    root = ET.fromstring(xml_data)
    
    entry = root.find("atom:entry", ns)
    if entry is None:
        return {"error": "Paper not found on arXiv"}
    
    arxiv_id = entry.find("atom:id", ns).text.split("/abs/")[-1]
    authors = [a.find("atom:name", ns).text for a in entry.findall("atom:author", ns)]
    
    # Get categories
    categories = [c.get("term") for c in entry.findall("atom:category", ns)]
    
    # Get DOI if available
    doi = None
    doi_elem = entry.find("arxiv:doi", ns)
    if doi_elem is not None:
        doi = doi_elem.text
    
    published = entry.find("atom:published", ns).text if entry.find("atom:published", ns) is not None else None
    updated = entry.find("atom:updated", ns).text if entry.find("atom:updated", ns) is not None else None
    
    return {
        "source": "arxiv",
        "id": arxiv_id,
        "title": entry.find("atom:title", ns).text.strip().replace("\n", " "),
        "authors": authors,
        "year": int(published[:4]) if published else None,
        "published": published,
        "updated": updated,
        "abstract": entry.find("atom:summary", ns).text.strip(),
        "categories": categories,
        "primaryCategory": categories[0] if categories else None,
        "url": f"https://arxiv.org/abs/{arxiv_id}",
        "pdfUrl": f"https://arxiv.org/pdf/{arxiv_id}.pdf",
        "doi": doi,
        "isOpenAccess": True
    }

def get_pubmed(pmid: str) -> dict:
    """Get paper from PubMed by PMID."""
    url = f"https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id={pmid}&retmode=xml"
    req = urllib.request.Request(url, headers={"User-Agent": "ResearchPaperSearch/1.0"})
    
    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            xml_data = resp.read().decode()
    except Exception as e:
        return {"error": f"PubMed API error: {e}"}
    
    root = ET.fromstring(xml_data)
    article = root.find(".//PubmedArticle")
    
    if article is None:
        return {"error": "Paper not found on PubMed"}
    
    # Get title
    title_elem = article.find(".//ArticleTitle")
    title = "".join(title_elem.itertext()) if title_elem is not None else ""
    
    # Get authors with affiliations
    authors = []
    for author in article.findall(".//Author"):
        last = author.find("LastName")
        first = author.find("ForeName")
        if last is not None:
            name = last.text
            if first is not None:
                name = f"{first.text} {last.text}"
            
            affiliation = author.find(".//Affiliation")
            auth_info = {"name": name}
            if affiliation is not None:
                auth_info["affiliation"] = affiliation.text
            authors.append(auth_info)
    
    # Get year
    year = None
    pub_date = article.find(".//PubDate/Year")
    if pub_date is not None:
        year = int(pub_date.text)
    
    # Get abstract
    abstract_parts = article.findall(".//AbstractText")
    abstract = " ".join("".join(p.itertext()) for p in abstract_parts)
    
    # Get journal info
    journal = article.find(".//Journal/Title")
    journal_name = journal.text if journal is not None else None
    
    # Get DOI and PMC ID
    doi = None
    pmc_id = None
    for id_elem in article.findall(".//ArticleId"):
        if id_elem.get("IdType") == "doi":
            doi = id_elem.text
        elif id_elem.get("IdType") == "pmc":
            pmc_id = id_elem.text
    
    # Get MeSH terms
    mesh_terms = [m.find("DescriptorName").text for m in article.findall(".//MeshHeading") 
                  if m.find("DescriptorName") is not None]
    
    # Get keywords
    keywords = [k.text for k in article.findall(".//Keyword") if k.text]
    
    return {
        "source": "pubmed",
        "id": pmid,
        "title": title,
        "authors": authors,
        "year": year,
        "journal": journal_name,
        "abstract": abstract,
        "doi": doi,
        "pmcId": pmc_id,
        "url": f"https://pubmed.ncbi.nlm.nih.gov/{pmid}/",
        "fullTextUrl": f"https://www.ncbi.nlm.nih.gov/pmc/articles/{pmc_id}/" if pmc_id else None,
        "meshTerms": mesh_terms[:10],
        "keywords": keywords,
        "isOpenAccess": pmc_id is not None
    }

def main():
    parser = argparse.ArgumentParser(description="Get detailed paper information")
    parser.add_argument("paper_id", help="Paper ID (format: arxiv:ID, pmid:ID, doi:DOI, or semantic:ID)")
    parser.add_argument("--json", action="store_true", help="Output raw JSON")
    args = parser.parse_args()
    
    paper_id = args.paper_id.strip()
    
    # Parse ID format
    if paper_id.startswith("arxiv:"):
        result = get_arxiv(paper_id[6:])
    elif paper_id.startswith("pmid:"):
        result = get_pubmed(paper_id[5:])
    elif paper_id.startswith("doi:"):
        result = get_semantic_scholar(paper_id)  # Semantic Scholar accepts DOI
    elif paper_id.startswith("semantic:"):
        result = get_semantic_scholar(paper_id[9:])
    elif re.match(r'^\d+\.\d+', paper_id):
        # Looks like arXiv ID
        result = get_arxiv(paper_id)
    elif re.match(r'^\d+$', paper_id):
        # Looks like PMID
        result = get_pubmed(paper_id)
    elif '/' in paper_id or paper_id.startswith('10.'):
        # Looks like DOI
        result = get_semantic_scholar(f"DOI:{paper_id}")
    else:
        result = get_semantic_scholar(paper_id)
    
    if args.json:
        print(json.dumps(result, indent=2))
        return
    
    if "error" in result:
        print(f"❌ {result['error']}")
        return
    
    # Pretty print
    print(f"\n{'='*70}")
    print(f"📄 {result['title']}")
    print(f"{'='*70}")
    
    print(f"\n📚 Source: {result['source'].upper()} | ID: {result['id']}")
    
    if result.get('authors'):
        if isinstance(result['authors'][0], dict):
            author_names = [a['name'] for a in result['authors']]
        else:
            author_names = result['authors']
        print(f"👤 Authors: {', '.join(author_names)}")
    
    if result.get('year'):
        print(f"📅 Year: {result['year']}")
    
    if result.get('venue') or result.get('journal'):
        print(f"📰 Venue: {result.get('venue') or result.get('journal')}")
    
    if result.get('citationCount'):
        print(f"📊 Citations: {result['citationCount']}")
    
    if result.get('categories') or result.get('fieldsOfStudy'):
        fields = result.get('categories') or result.get('fieldsOfStudy')
        print(f"🏷️  Fields: {', '.join(fields[:5])}")
    
    if result.get('isOpenAccess'):
        print(f"🔓 Open Access: Yes")
    
    print(f"\n📝 Abstract:\n{result.get('abstract', 'No abstract available')}")
    
    if result.get('topCitations'):
        print(f"\n📈 Top Citations:")
        for c in result['topCitations']:
            print(f"   • {c.get('title', 'Unknown')} ({c.get('year', '?')})")
    
    if result.get('keyReferences'):
        print(f"\n📚 Key References:")
        for r in result['keyReferences']:
            print(f"   • {r.get('title', 'Unknown')} ({r.get('year', '?')})")
    
    print(f"\n🔗 URL: {result.get('url')}")
    if result.get('pdfUrl'):
        print(f"📥 PDF: {result['pdfUrl']}")
    if result.get('openAccessPdf'):
        print(f"📥 PDF: {result['openAccessPdf']}")
    if result.get('fullTextUrl'):
        print(f"📖 Full Text: {result['fullTextUrl']}")
    if result.get('doi'):
        print(f"🆔 DOI: {result['doi']}")

if __name__ == "__main__":
    main()
