"""HTTP API client for widetorah.com REST endpoints.

Usage::

    from widetorah import WideTorah

    with WideTorah() as client:
        books = client.list_books()
        verse = client.get_verse("genesis", 1, 1)
        results = client.search("covenant")
"""

from __future__ import annotations

from typing import Any

import httpx


class WideTorah:
    """Python SDK for WideTorah — Torah, Talmud, Rashi commentary, and Jewish encyclopdia.

    Provides typed access to all widetorah.com API endpoints including
    Tanakh books, verses, parashot, Talmud tractates, daf pages, Mishnah,
    Rashi commentary, Jewish holidays, biblical figures, topics, and glossary.

    Args:
        base_url: API base URL. Defaults to ``https://widetorah.com``.
        timeout: Request timeout in seconds. Defaults to ``10.0``.
    """

    def __init__(
        self,
        base_url: str = "https://widetorah.com",
        timeout: float = 10.0,
    ) -> None:
        self._client = httpx.Client(
            base_url=f"{base_url.rstrip('/')}/api/v1/torah/",
            timeout=timeout,
        )

    def _get(self, path: str, **params: Any) -> dict[str, Any]:
        resp = self._client.get(
            path,
            params={k: v for k, v in params.items() if v is not None},
        )
        resp.raise_for_status()
        result: dict[str, Any] = resp.json()
        return result

    # ─── Books ────────────────────────────────────────────────────────

    def list_books(self, section: str | None = None, **params: Any) -> dict[str, Any]:
        """List all 24 books of the Tanakh.

        Args:
            section: Filter by section — ``torah``, ``neviim``, or ``ketuvim``.
        """
        return self._get("books/", section=section, **params)

    def get_book(self, slug: str) -> dict[str, Any]:
        """Get book details by slug (e.g. ``'genesis'``, ``'psalms'``).

        Returns name, hebrew_name, section, chapter_count, verse_count.
        """
        return self._get(f"books/{slug}/")

    # ─── Translations ─────────────────────────────────────────────────

    def list_translations(self, **params: Any) -> dict[str, Any]:
        """List available Torah translations (JPS-1917, Koren, Masoretic Hebrew)."""
        return self._get("translations/", **params)

    # ─── Chapters ─────────────────────────────────────────────────────

    def list_chapters(self, book: str | None = None, **params: Any) -> dict[str, Any]:
        """List chapters, optionally filtered by book slug.

        Args:
            book: Book slug to filter by (e.g. ``'genesis'``).
        """
        return self._get("chapters/", book__slug=book, **params)

    # ─── Verses ───────────────────────────────────────────────────────

    def get_verse(
        self,
        book: str,
        chapter: int,
        verse: int,
        translation: str = "jps-1917",
    ) -> dict[str, Any]:
        """Get a specific Torah verse by book, chapter, and verse number.

        Args:
            book: Book slug (e.g. ``'genesis'``, ``'exodus'``).
            chapter: Chapter number.
            verse: Verse number.
            translation: Translation code. Defaults to ``'jps-1917'``.

        Returns:
            Verse dict with text, text_hebrew, reference, book_slug, chapter_number.
        """
        return self._get(
            "verses/",
            chapter__book__slug=book,
            translation__code=translation,
            chapter__number=chapter,
            number=verse,
        )

    def search(self, query: str, limit: int = 25) -> dict[str, Any]:
        """Search Torah verses by keyword.

        Args:
            query: Search query string (e.g. ``'covenant'``, ``'blessing'``).
            limit: Maximum number of results. Defaults to 25.
        """
        return self._get("verses/", search=query, page_size=limit)

    # ─── Parashot ─────────────────────────────────────────────────────

    def list_parashot(self, book: str | None = None, **params: Any) -> dict[str, Any]:
        """List the 54 weekly Torah portions (parashot).

        Args:
            book: Filter by book slug (e.g. ``'genesis'``).
        """
        return self._get("parashot/", book__slug=book, **params)

    def get_parashah(self, slug: str) -> dict[str, Any]:
        """Get parashah details by slug (e.g. ``'bereshit'``, ``'noach'``).

        Returns name, hebrew_name, book_slug, start/end chapter/verse, reference.
        """
        return self._get(f"parashot/{slug}/")

    # ─── Talmud Tractates ─────────────────────────────────────────────

    def list_tractates(self, seder: str | None = None, **params: Any) -> dict[str, Any]:
        """List Talmud tractates (63 volumes across 6 sedarim).

        Args:
            seder: Filter by seder name (e.g. ``'zeraim'``, ``'moed'``).
        """
        return self._get("tractates/", seder=seder, **params)

    # ─── Talmud Daf ───────────────────────────────────────────────────

    def get_talmud_daf(
        self,
        tractate: str,
        daf: int,
        side: str = "a",
    ) -> dict[str, Any]:
        """Get a Talmud folio page (daf) by tractate, number, and side.

        Args:
            tractate: Tractate slug (e.g. ``'berakhot'``, ``'shabbat'``).
            daf: Daf (folio) number.
            side: Page side — ``'a'`` (recto) or ``'b'`` (verso). Defaults to ``'a'``.

        Returns:
            Daf dict with text_hebrew, text_english, text_aramaic.
        """
        return self._get(
            "dapim/",
            tractate__slug=tractate,
            number=daf,
            side=side,
        )

    # ─── Mishnah ──────────────────────────────────────────────────────

    def list_mishnah(self, tractate: str | None = None, **params: Any) -> dict[str, Any]:
        """List Mishnah chapters, optionally filtered by tractate.

        Args:
            tractate: Tractate slug to filter by.
        """
        return self._get("mishnah/", tractate__slug=tractate, **params)

    # ─── Rashi Commentary ─────────────────────────────────────────────

    def list_rashi(
        self,
        book: str | None = None,
        chapter: int | None = None,
        **params: Any,
    ) -> dict[str, Any]:
        """List Rashi commentaries on Torah verses.

        Args:
            book: Filter by book slug (e.g. ``'genesis'``).
            chapter: Filter by chapter number.
        """
        return self._get("rashi/", book__slug=book, chapter=chapter, **params)

    # ─── Jewish Holidays ──────────────────────────────────────────────

    def list_holidays(self, category: str | None = None, **params: Any) -> dict[str, Any]:
        """List Jewish holidays (biblical, rabbinic, modern).

        Args:
            category: Filter by category (e.g. ``'biblical'``, ``'rabbinic'``).
        """
        return self._get("holidays/", category=category, **params)

    # ─── Biblical Figures ─────────────────────────────────────────────

    def list_figures(self, era: str | None = None, **params: Any) -> dict[str, Any]:
        """List biblical figures (patriarchs, prophets, kings, etc.).

        Args:
            era: Filter by era (e.g. ``'patriarchs'``, ``'judges'``).
        """
        return self._get("figures/", era=era, **params)

    def get_figure(self, slug: str) -> dict[str, Any]:
        """Get a biblical figure's details by slug.

        Returns name, hebrew_name, description, era, is_prophet.
        """
        return self._get(f"figures/{slug}/")

    # ─── Topics ───────────────────────────────────────────────────────

    def list_topics(self, **params: Any) -> dict[str, Any]:
        """List thematic topics (covenant, creation, law, etc.)."""
        return self._get("topics/", **params)

    # ─── Glossary ─────────────────────────────────────────────────────

    def list_glossary(self, **params: Any) -> dict[str, Any]:
        """List Hebrew/Aramaic glossary terms with definitions."""
        return self._get("glossary/", **params)

    # ─── Lifecycle ────────────────────────────────────────────────────

    def close(self) -> None:
        """Close the underlying HTTP client."""
        self._client.close()

    def __enter__(self) -> WideTorah:
        return self

    def __exit__(self, *_: object) -> None:
        self.close()
