#!/usr/bin/env python3
"""
Generate static HTML reading pages for a downloaded manga (any source).

For every chapter directory (chapter_NNN/, including suffixed ones like
chapter_71_1/ for fix chapters, with .webp/.jpg/.png images) it
writes:
  - <manga_dir>/index.html        -> overview page listing all chapters
  - <manga_dir>/chapter_NNN/index.html -> reader page for that chapter
    (vertical scroll, lazy-loaded images, prev/next navigation)

Safe to re-run at any time (idempotent): it simply regenerates pages from
whatever is on disk. Run it now to get pages for finished chapters, or
again after the download completes to get everything.

Usage:
  python3 generate_html.py [manga_dir]     (default: disastrous-necromancer)
"""

import html
import re
import sys
from pathlib import Path

IMG_EXTS = (".webp", ".jpg", ".jpeg", ".png")

CSS = """
  :root { --bg: #14161a; --fg: #e8e8e8; --muted: #9aa0a6; --accent: #7aa2f7; }
  * { box-sizing: border-box; }
  body { margin: 0; background: var(--bg); color: var(--fg);
         font-family: system-ui, -apple-system, 'Segoe UI', sans-serif; }
  a { color: var(--accent); text-decoration: none; }
  a:hover { text-decoration: underline; }
  header { padding: 16px 20px; border-bottom: 1px solid #2a2d33;
           display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
  header h1 { font-size: 1.25rem; margin: 0; }
  header .sub { color: var(--muted); font-size: 0.9rem; }
  nav { padding: 12px 20px; display: flex; gap: 16px; flex-wrap: wrap;
        border-bottom: 1px solid #2a2d33; background: #1a1d22; }
  nav a { padding: 6px 12px; border-radius: 6px; background: #24272e; }
  nav a:hover { background: #2e323b; text-decoration: none; }
  nav a:empty { display: none; }
  main { max-width: 900px; margin: 0 auto; padding: 0 0 40px; }
  img.page { display: block; width: 100%; height: auto; }
  .chapter-list { list-style: none; padding: 12px 20px; margin: 0;
                  columns: 4; column-gap: 24px; }
  .chapter-list li { break-inside: avoid; }
  .chapter-list a { display: block; padding: 4px 8px; border-radius: 4px; }
  .chapter-list a:hover { background: #24272e; text-decoration: none; }
  .chapter-list li.new a { font-weight: 600; }
  .foot { color: var(--muted); font-size: 0.8rem; text-align: center;
          padding: 16px; border-top: 1px solid #2a2d33; margin-top: 24px; }
  @media (max-width: 700px) { .chapter-list { columns: 2; } }
"""


def chapter_title(dir_name: str) -> str:
    """chapter_12 -> 'Chapter 12', chapter_71_1 -> 'Chapter 71.1'."""
    m = re.match(r"chapter_(\d+(?:_\d+)*)$", dir_name)
    if not m:
        return dir_name
    return "Chapter " + ".".join(m.group(1).split("_"))


def chapter_sort_key(dir_name: str):
    """chapter_71 before chapter_71_1 before chapter_72 (numeric, not lexicographic)."""
    m = re.match(r"chapter_([\d_]+)$", dir_name)
    if m:
        return (0, tuple(int(x) for x in m.group(1).split("_")))
    return (1, dir_name)


def img_key(p: Path):
    """Sort by the LEADING page number only (all-digits would break '002-102')."""
    m = re.match(r"(\d+)", p.name)
    return (0, int(m.group(1))) if m else (1, p.name)


def chapter_page(title: str, images: list[Path], prev: str | None, next_: str | None) -> str:
    imgs = "\n".join(
        f'  <img class="page" src="{html.escape(p.name)}" alt="{html.escape(title)} page {i}" loading="lazy">'
        for i, p in enumerate(images, 1)
    )
    prev_link = f'<a href="../{prev}/">← {html.escape(chapter_title(prev))}</a>' if prev else ""
    next_link = f'<a href="../{next_}/">{html.escape(chapter_title(next_))} →</a>' if next_ else ""
    return f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{html.escape(title)}</title>
<style>{CSS}</style>
</head>
<body>
<header><h1>{html.escape(title)}</h1><span class="sub">{len(images)} pages</span></header>
<nav>
  {prev_link}
  <a href="../">Manga</a>
  {next_link}
</nav>
<main>
{imgs}
</main>
<div class="foot">{prev_link} · <a href="../">All chapters</a> · {next_link}</div>
</body>
</html>
"""


def index_page(manga_title: str, chapters: list[str]) -> str:
    items = []
    for i, c in enumerate(chapters, 1):
        marker = ' class="new"' if i == len(chapters) else ""
        items.append(f'  <li{marker}><a href="{c}/">{html.escape(chapter_title(c))}</a></li>')
    listing = "\n".join(items)
    return f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{html.escape(manga_title)}</title>
<style>{CSS}</style>
</head>
<body>
<header><h1>{html.escape(manga_title)}</h1><span class="sub">{len(chapters)} chapters</span></header>
<main>
<ol class="chapter-list" start="1">
{listing}
</ol>
<div class="foot">Local archive — serve this directory, e.g. <code>python3 -m http.server</code></div>
</main>
</body>
</html>
"""


def main() -> None:
    manga_dir = Path(sys.argv[1]) if len(sys.argv) > 1 else Path("disastrous-necromancer")
    if not manga_dir.is_dir():
        sys.exit(f"Manga directory not found: {manga_dir}")

    manga_title = re.sub(r"[-_]+", " ", manga_dir.name).title()

    chapter_dirs = sorted(
        (d.name for d in manga_dir.iterdir()
         if d.is_dir() and re.match(r"chapter_\d[\d_]*$", d.name)),
        key=chapter_sort_key,
    )

    written = 0
    for i, name in enumerate(chapter_dirs):
        d = manga_dir / name
        images = sorted((p for p in d.iterdir()
                         if p.suffix.lower() in IMG_EXTS and not p.name.endswith(".part")),
                        key=img_key)
        if not images:
            print(f"  {name}: no images yet, skipping page")
            continue
        prev = chapter_dirs[i - 1] if i > 0 else None
        next_ = chapter_dirs[i + 1] if i + 1 < len(chapter_dirs) else None
        title = chapter_title(name)
        (d / "index.html").write_text(chapter_page(title, images, prev, next_))
        written += 1
        print(f"  {name}: {len(images)} pages")

    # Main index always points at the latest chapter if it has pages.
    (manga_dir / "index.html").write_text(index_page(manga_title, chapter_dirs))
    print(f"Wrote {written} chapter pages + index.html in {manga_dir}/")
    print("Serve it with:  python3 -m http.server -d", manga_dir)


if __name__ == "__main__":
    main()
