"""
GLAMWalk -- Volume 4: Libraries & Archives
11_standard_ebooks_fetch_and_split.py

Fetching exactly one specific, predictable Standard Ebooks URL (never crawling arbitrary links, due to a real anti-scraper honeypot) and splitting on its real semantic chapter markup.

Source: Volume Four, Sections 4.1-4.2
Targets Python 3.11.4 -- see Volume One, Chapter 1.5/1.6.

NOTE: This script makes real network requests to a live public API.
It's safe to run as-is, but requires an internet connection.
"""

import requests
from bs4 import BeautifulSoup

def split_standard_ebooks_chapters(html):
    """
    Standard Ebooks marks chapter boundaries explicitly — no
    heuristic guessing required, unlike Chapter 1's plain-Gutenberg
    approach. Title comes from a <p epub:type="title"> tag FIRST,
    checked before any ordinal heading — a real bug this project hit:
    checking an ordinal heading like <h2>I</h2> first grabbed "I"
    as the title instead of the real chapter title sitting right
    next to it.
    """
    soup = BeautifulSoup(html, "html.parser")
    chapters = []

    for section in soup.select('section[epub|type~="chapter"]'):
        title_el = section.select_one('p[epub|type="title"]')
        if title_el:
            title = title_el.get_text(strip=True)
        else:
            heading = section.find(["h1", "h2", "h3"])
            title = heading.get_text(strip=True) if heading else "Untitled Chapter"

        chapters.append({"title": title, "body": section.get_text("\n", strip=True)})

    return chapters


def fetch_standard_ebook(author_slug, title_slug):
    """
    Deliberately narrow: fetches exactly ONE specific, predictable URL.
    Never parses or follows arbitrary <a> tags found on the page —
    Standard Ebooks' anti-scraper honeypot exists specifically to
    catch importers that do.
    """
    url = f"https://standardebooks.org/ebooks/{author_slug}/{title_slug}/text/single-page"
    response = requests.get(url, timeout=20)
    if response.status_code == 404:
        return None
    response.raise_for_status()
    return response.text
