#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
md2html_mathjax.py
------------------
Convert a Markdown file (with LaTeX math) into a standalone HTML file.

- Inserts MathJax (CDN) and CSS into <head>
- Uses Python-Markdown + pymdownx.arithmatex so math survives Markdown rendering
- Default inline CSS (dark-mode aware), overridable with --css-file or --no-css

Requirements:
  pip install markdown pymdown-extensions

Usage:
  python md2html_mathjax.py input.md -o output.html

  # Options:
  python md2html_mathjax.py input.md -o output.html \
      --title "My Notes" \
      --lang ja \
      --mathjax-url https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js \
      --css-file style.css

License: MIT
Author: ChatGPT
"""
import argparse
import re
from pathlib import Path
from typing import Optional

import markdown


DEFAULT_CSS = r"""
/* Minimal typesetting */
:root{--fg:#111;--bg:#fff;--muted:#666;--code-bg:#f6f8fa;--border:#e5e7eb;--link:#2563eb;}
@media (prefers-color-scheme: dark){
  :root{--fg:#e5e7eb;--bg:#0b121b;--muted:#9ca3af;--code-bg:#111827;--border:#1f2937;--link:#60a5fa;}
}
html {font-size: 16px;}
body {margin: 2rem auto; max-width: 880px; padding: 0 1rem; color: var(--fg); background: var(--bg); line-height: 1.75;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Noto Sans JP', 'Hiragino Sans', 'Yu Gothic',
                   'Helvetica Neue', Arial, 'Apple Color Emoji','Segoe UI Emoji';}
h1,h2,h3,h4{line-height:1.3}
pre, code {font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', 'Courier New', monospace;}
pre {background: var(--code-bg); padding: 1rem; overflow:auto; border-radius: 8px; border:1px solid var(--border);}
code {background: var(--code-bg); padding: .15rem .35rem; border-radius: 6px;}
a {color: var(--link); text-decoration: none;}
a:hover {text-decoration: underline;}
table {border-collapse: collapse; width: 100%; margin: 1rem 0}
th, td {border: 1px solid var(--border); padding: .5rem .75rem; text-align: left;}
blockquote {border-left: 4px solid var(--border); margin: 1rem 0; padding: .25rem 1rem; color: var(--muted);}
hr {border: 0; border-top:1px solid var(--border); margin: 2rem 0;}
/* Ensure math spans render inline nicely */
.arithmatex { font-size: 1em; }
"""


HTML_TEMPLATE = """<!DOCTYPE html>
<html lang="{lang}">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="generator" content="md2html_mathjax.py" />
  <title>{title}</title>
  {css_block}
  <script>
    // MathJax config: process only elements with class 'arithmatex' (emitted by pymdownx.arithmatex)
    window.MathJax = {{
      tex: {{
        inlineMath: [['$', '$'], ['\\\\(', '\\\\)']],
        displayMath: [['$$', '$$'], ['\\\\[', '\\\\]']],
        processEscapes: true,
        tags: 'ams'
      }},
      options: {{
        processHtmlClass: 'arithmatex',
        ignoreHtmlClass: '.*'
      }}
    }};
  </script>
  <script id="MathJax-script" defer src="{mathjax_url}"></script>
</head>
<body>
{body}
</body>
</html>
"""


def derive_title(md_text: str, fallback: str) -> str:
    # 1) YAML metadata title: `title: ...` (very loose)
    m = re.search(r'(?mi)^title:\s*(.+)$', md_text)
    if m:
        return m.group(1).strip()
    # 2) First ATX heading (# H1)
    m = re.search(r'(?m)^#\s+(.+?)\s*$', md_text)
    if m:
        return m.group(1).strip()
    return fallback


def build_html(md_text: str, title: str, lang: str, mathjax_url: str, css_text: Optional[str]) -> str:
    # Render Markdown with math passthrough using pymdownx.arithmatex
    exts = [
        "extra",            # tables, etc.
        "toc",              # optional TOC ids
        "sane_lists",
        "attr_list",
        "pymdownx.arithmatex",
        "codehilite",       # highlight wrapper (no pygments by default)
    ]
    ext_cfg = {
        "pymdownx.arithmatex": {"generic": True},
        "codehilite": {"guess_lang": False, "use_pygments": False},
        "toc": {"permalink": True},
    }
    body = markdown.markdown(md_text, extensions=exts, extension_configs=ext_cfg, output_format="xhtml")
    css_block = f"<style>\n{css_text}\n</style>" if css_text else ""
    return HTML_TEMPLATE.format(lang=lang, title=title, css_block=css_block, mathjax_url=mathjax_url, body=body)


def main():
    ap = argparse.ArgumentParser(description="Markdown (with LaTeX) -> HTML with MathJax & inline CSS.")
    ap.add_argument("input_md", help="Input Markdown file path")
    ap.add_argument("-o", "--output", required=True, help="Output HTML file path")
    ap.add_argument("--title", default=None, help="HTML <title>. Default: from Markdown H1 or file name")
    ap.add_argument("--lang", default="ja", help="HTML lang attribute (default: ja)")
    ap.add_argument("--mathjax-url", default="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js",
                    help="MathJax v3 bundle URL (default: tex-chtml.js)")
    ap.add_argument("--css-file", default=None, help="Use CSS from file instead of the built-in default")
    ap.add_argument("--no-css", action="store_true", help="Do not embed any CSS")
    args = ap.parse_args()

    inp = Path(args.input_md).expanduser().resolve()
    out = Path(args.output).expanduser().resolve()
    if not inp.exists():
        raise SystemExit(f"[ERR] Markdown not found: {inp}")

    md_text = inp.read_text(encoding="utf-8")
    title = args.title or derive_title(md_text, inp.stem)

    css_text = None
    if not args.no_css:
        if args.css_file:
            css_text = Path(args.css_file).read_text(encoding="utf-8")
        else:
            css_text = DEFAULT_CSS

    html = build_html(md_text, title=title, lang=args.lang, mathjax_url=args.mathjax_url, css_text=css_text)
    out.parent.mkdir(parents=True, exist_ok=True)
    out.write_text(html, encoding="utf-8")
    print(f"[OK] Wrote: {out}")


if __name__ == "__main__":
    main()
