"""
Source adapter for Drake Scans (drakecomic.org).

Manga pages link their chapters as
    https://drakecomic.org/<manga-slug>-chapter-<num>/
Chapter pages embed their reader config:
    ts_reader.run({"post_id":..., "sources":[{"images":[url, ...]}]})
That list is the chapter's canonical page set and reading order.

Note: some chapter posts on the site have extra images from other manga
attached to them (the site's own reader shows them). We deliberately do
NOT filter those out — we recreate exactly what the site's reader lists.
"""

import json
import re
import sys

from . import core


class DrakeScansSource:
    name = "drake"
    site = "https://drakecomic.org"

    def __init__(self, manga_slug: str | None = None):
        # Default to the manga this repo was originally built for.
        self.manga_slug = manga_slug or "disastrous-necromancer"

    def output_dir(self, manga_url: str) -> "core.Path":
        return core.Path(self.manga_slug)

    def chapter_dirname(self, ch_id: str) -> str:
        return f"chapter_{int(ch_id):03d}"

    def get_chapters(self, manga_url: str) -> list[tuple[str, str, str]]:
        """-> [(ch_id, ch_url, label)] in reading order."""
        html = core.fetch_html(manga_url)
        if html is None:
            sys.exit("Could not fetch manga page.")
        # Note: findall() would return tuples here (two capture groups), so
        # use finditer() to pull the url and chapter number from one match.
        link_re = re.compile(
            r'href="(' + re.escape(self.site) + r'/[^"]*'
            + re.escape(self.manga_slug) + r'-chapter-(\d+)/)"')
        chapters = []
        for m in link_re.finditer(html):
            url, num = m.group(1), int(m.group(2))
            chapters.append((str(num), url, f"Chapter {num}"))
        chapters.sort(key=lambda c: int(c[0]))
        return chapters

    def get_pages(self, chapter_url: str) -> list[str]:
        html = core.fetch_html(chapter_url)
        if html is None:
            return []
        cfg = extract_ts_reader_json(html)
        if not cfg:
            core.log("  ts_reader config not found — layout may have changed.")
            return []
        urls = next((s.get("images") or []
                     for s in (cfg.get("sources") or []) if s.get("images")), [])
        if not urls:
            core.log("  no images in reader config.")
        return urls


def extract_ts_reader_json(html: str) -> dict | None:
    """Extract the ts_reader.run({...}) JSON object (string-aware brace scan)."""
    idx = html.find("ts_reader.run(")
    if idx == -1:
        return None
    start = html.find("(", idx) + 1
    depth, in_str, esc = 0, False, False
    for i in range(start, len(html)):
        c = html[i]
        if in_str:
            if esc:
                esc = False
            elif c == "\\":
                esc = True
            elif c == '"':
                in_str = False
        elif c == '"':
            in_str = True
        elif c == "{":
            depth += 1
        elif c == "}":
            depth -= 1
            if depth == 0:
                try:
                    return json.loads(html[start:i + 1])
                except json.JSONDecodeError:
                    return None
    return None
