"""Getting a wiki article and analyze to give a rating based on reader's background."""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_wiki.ipynb.

# %% auto 0
__all__ = ['WikiArticle', 'ArticleAnalysis', 'analyze_article_for_reader', 'is_interactive', 'analyze_multiple_articles']

# %% ../nbs/00_wiki.ipynb 4
import httpx
from bs4 import BeautifulSoup
import html2text
from IPython.display import Markdown
from fastcore.utils import *

# %% ../nbs/00_wiki.ipynb 7
class WikiArticle:
    "Grab a wikipedia article to analyze."
    def __init__(self, url):
        if not url.startswith('https://en.wikipedia.org/wiki/'): 
            raise ValueError("Must be English Wikipedia URL")
        self.url = url
        self._soup = None
        
    @property
    def soup(self):
        if self._soup is None:
            self._soup = BeautifulSoup(httpx.get(self.url).text, 'lxml')
        return self._soup
    
    @property
    def title(self): return self.soup.find('h1', id='firstHeading').text.strip()
    
    @property
    def intro(self):
        "Select an introduction from the `WikiArticle`."
        content = self.soup.select_one("#mw-content-text > div.mw-content-ltr.mw-parser-output")
        paragraphs = []
        for p in content.find_all('p'):
            if p.find_previous('div', class_='mw-heading mw-heading2'): break
            if text := p.text.strip(): paragraphs.append(text)
        return f"# {self.title}\n\n" + '\n\n'.join(paragraphs)

# %% ../nbs/00_wiki.ipynb 17
from claudette import Chat, Client, models
from fastcore.utils import *

# %% ../nbs/00_wiki.ipynb 22
class ArticleAnalysis:
    "Analysis of a Wikipedia article for a reader based on the background."
    def __init__(self,
                interest_rating: int,        # Rating 1-10 of how interesting the article is for this reader based on the background
                interest_reason: str,        # Markdown explanation for interest rating (max 50 words) for this reader based on the background
                difficulty_rating: int,      # Rating 1-10 of how difficult the article is for this reader based on the background
                difficulty_reason: str,      # Markdown explanation for difficulty rating (max 50 words) for this reader based on the background
                prerequisites: list[str],    # List of topics reader should know before reading for this reader based on the background
                prereq_reason: str,          # Markdown explanation for prerequisites (max 50 words) for this reader based on the background
    ):
        assert 1 <= interest_rating <= 10, "Interest rating must be between 1 and 10"
        assert 1 <= difficulty_rating <= 10, "Difficulty rating must be between 1 and 10"
        store_attr()
        
    __repr__ = basic_repr('interest_rating, interest_reason, difficulty_rating, difficulty_reason, prerequisites, prereq_reason')

# %% ../nbs/00_wiki.ipynb 23
def analyze_article_for_reader(article_text: str, background: str) -> ArticleAnalysis:
    "Analyze a Wikipedia article for a specific reader background"
    prompt = f"""Provide an analysis of a Wikipedia article for a reader based on the background.

<problem>
Analyze this article introduction for the given reader background. Provide:
1. Interest rating (1-10) with brief reason
2. Difficulty rating (1-10) with brief reason
3. Prerequisites needed, with reason why they're important
Keep all explanations under 50 words.
</problem>

Here is the article below.
<article>
{article_text}
</article>

Here is the background of the reader. 
Pay attention to detail and think about how this information is related to the article.
<reader_background>
{background}
</reader_background>

Be honest about the rating. It is realistic to have low ratings. 
"""
    
    return client.structured(prompt, ArticleAnalysis)[0]

# %% ../nbs/00_wiki.ipynb 29
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import sys
from typing import List, Dict
import threading

# %% ../nbs/00_wiki.ipynb 30
def is_interactive() -> bool:
    "Check if we're running in an interactive environment (IPython/Jupyter)"
    return hasattr(sys, 'ps1') or bool(sys.flags.interactive) or 'ipykernel' in sys.modules

# %% ../nbs/00_wiki.ipynb 33
def analyze_multiple_articles(articles: List[str], backgrounds: Dict[str, str], max_workers: int = None) -> Dict[str, Dict[str, ArticleAnalysis]]:
    "Analyze multiple articles for different reader backgrounds in parallel"
    Executor = ThreadPoolExecutor if is_interactive() else ProcessPoolExecutor
    results = {}
    with Executor(max_workers=max_workers) as executor:
        futures = {}
        for article_idx, article_text in enumerate(articles):
            results[article_idx] = {}
            for reader_type, background in backgrounds.items():
                future = executor.submit(analyze_article_for_reader, article_text, background)
                futures[(article_idx, reader_type)] = future
        for (article_idx, reader_type), future in futures.items():
            try:
                results[article_idx][reader_type] = future.result()
            except Exception as e:
                results[article_idx][reader_type] = None
    return results
