"""図版を生成する。light: <name>.svg / dark: <name>.dark.svg（viewBoxは同一）。
fig03はexperiment/data/sites.jsonの計測値から描く。
"""
import json
from pathlib import Path
from xml.sax.saxutils import escape

OUT = Path(__file__).parent
THEMES = {
    "": dict(text="#1f2937", sub="#4b5563", line="#9ca3af", card="#f3f4f6", acc="#1d4ed8", warn="#b45309", bad="#b91c1c", ok="#15803d", barbg="#e5e7eb", fill1="#dbeafe", fill2="#bfdbfe", fill3="#fde68a"),
    ".dark": dict(text="#f3f4f6", sub="#d1d5db", line="#6b7280", card="#1f2937", acc="#93c5fd", warn="#fbbf24", bad="#fca5a5", ok="#86efac", barbg="#374151", fill1="#1e3a5f", fill2="#1e40af", fill3="#78350f"),
}
FONT = "sans-serif"


def t(x, y, s, size=15, fill="text", weight="normal", anchor="start"):
    return f'<text x="{x}" y="{y}" font-family="{FONT}" font-size="{size}" font-weight="{weight}" fill="{{{fill}}}" text-anchor="{anchor}">{escape(s)}</text>'


def svg(w, h, title, body):
    return (f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {w} {h}" role="img" aria-label="{escape(title)}">'
            f'<title>{escape(title)}</title>' + "".join(body) + "</svg>\n")


def fig_timeline():
    w, h = 800, 400
    ev = [
        ("9/22", "国連総会の演説", "「米国の文書は全部、\n願わくば世界も」", "sub"),
        ("9/29", "EO 14434に署名", "同日、自主協定（Accord）も", "acc"),
        ("9/30", "カリフォルニア州", "知事令N-10-26「AIのまま」", "bad"),
        ("10/2", "連邦官報に掲載", "91 FR 63129", "sub"),
        ("10/4", "SI Forceを発表", "SNS投稿ベース。期限120日", "sub"),
        ("11/28", "立法案の期限", "SIの連邦定義案（60日）", "warn"),
    ]
    b = [t(24, 34, "呼称変更の前後で、何がいつ起きたか", 20, weight="bold")]
    b.append(t(24, 58, "2026年。9/29がEOの署名日。赤は反対方向の動き、黄は次の分かれ目", 14, "sub"))
    y0 = 150
    b.append(f'<line x1="40" y1="{y0}" x2="760" y2="{y0}" stroke="{{line}}" stroke-width="3"/>')
    for i, (d, head, note, col) in enumerate(ev):
        x = 100 + i * 120
        b.append(f'<circle cx="{x}" cy="{y0}" r="9" fill="{{{col}}}"/>')
        b.append(t(x, y0 - 22, d, 17, col, "bold", "middle"))
        up = i % 2 == 0
        ty = y0 + 40 if up else y0 + 150
        b.append(f'<line x1="{x}" y1="{y0+9}" x2="{x}" y2="{ty-18}" stroke="{{line}}"/>')
        b.append(t(x, ty, head, 14, "text", "bold", "middle"))
        for j, line in enumerate(note.split("\n")):
            b.append(t(x, ty + 20 + j * 18, line, 12, "sub", "normal", "middle"))
    b.append(t(24, 386, "出典：連邦官報・ホワイトハウス・カリフォルニア州の原文、報道（国連演説とSI Forceは報道経由）", 12, "sub"))
    return svg(w, h, "2026年9月22日の国連演説、9月29日のEO 14434署名、9月30日のカリフォルニア州知事令、10月2日の官報掲載、10月4日のSI Force発表、11月28日の立法案の期限を並べた年表", b)


def fig_nested():
    w, h = 800, 460
    b = [t(24, 34, "EOの「SI」は、いまの「AI」と同じ範囲を指す", 20, weight="bold")]
    b.append(t(24, 58, "超知能（研究者の言う意味）は、その一番奥の、まだ確認されていない部分", 14, "sub"))
    b.append(f'<ellipse cx="270" cy="265" rx="250" ry="185" fill="{{fill1}}" stroke="{{acc}}" stroke-width="2"/>')
    b.append(t(270, 122, "EO 14434の「SI」", 18, "text", "bold", "middle"))
    b.append(t(270, 144, "＝ 米国法の「artificial intelligence」", 14, "sub", "normal", "middle"))
    b.append(t(270, 168, "外側の例：スパムフィルタ、おすすめ表示、画像の分類器", 12, "sub", "normal", "middle"))
    b.append(f'<ellipse cx="270" cy="305" rx="170" ry="100" fill="{{fill2}}" stroke="{{acc}}" stroke-width="1.5"/>')
    b.append(t(270, 262, "いまのフロンティアモデル", 16, "text", "bold", "middle"))
    b.append(t(270, 284, "（ChatGPT、Claude、エージェント）", 13, "sub", "normal", "middle"))
    b.append(f'<ellipse cx="270" cy="350" rx="95" ry="38" fill="{{fill3}}" stroke="{{warn}}" stroke-width="2" stroke-dasharray="6 4"/>')
    b.append(t(270, 346, "研究者の言う超知能", 14, "text", "bold", "middle"))
    b.append(t(270, 364, "確認した主要ラボの主張はなし", 11, "sub", "normal", "middle"))
    notes = [
        ("条件はこれだけ", ["人間が決めた目的に対して、", "予測・推奨・判断を出す", "機械ベースのシステム", "（15 U.S.C. §9401(3)）"], "acc"),
        ("人間を超える条件", ["条文のどこにも書かれていない"], "bad"),
        ("変わるかもしれない点", ["60日以内（11/28）に、大統領", "補佐官がSec.1の能力を反映", "する定義の立法案を出す。", "決めるのは議会"], "warn"),
    ]
    y = 100
    for head, lines, col in notes:
        b.append(t(548, y, head, 15, col, "bold"))
        for j, ln in enumerate(lines):
            b.append(t(548, y + 22 + j * 18, ln, 13, "text"))
        y += 22 + len(lines) * 18 + 30
    return svg(w, h, "入れ子の図。一番外がEO 14434のSI（米国法のAIと同じ）、その中にいまのフロンティアモデル、一番奥に研究者の言う超知能。人間を超える条件は条文に無い", b)


def fig_sites():
    data = json.loads((OUT / "experiment/data/sites.json").read_text())
    rows = []
    for name, r in data["sites"].items():
        if r.get("status") != "ok" or name.startswith("EO 14434"):
            continue
        si, ai = r["si_long"] + r["si_abbr"], r["ai_long"] + r["ai_abbr"]
        if si + ai == 0:
            continue
        rows.append((name, si, ai))
    rows.sort(key=lambda x: (-x[1] / (x[1] + x[2]), x[0]))
    w = 800
    h = 110 + len(rows) * 30 + 40
    b = [t(24, 34, "署名から1週間後、省庁のAIページはSIに替わったか", 20, weight="bold")]
    b.append(t(24, 58, "ページ本文の「SI」と「AI」の出現数の比（長形と略称の合計。2026-10-06に計測）", 14, "sub"))
    x0, bw = 220, 360
    for i, (name, si, ai) in enumerate(rows):
        y = 84 + i * 30
        share = si / (si + ai)
        b.append(t(24, y + 17, name, 14, "text", "bold"))
        b.append(f'<rect x="{x0}" y="{y}" width="{bw}" height="22" rx="5" fill="{{barbg}}"/>')
        if si:
            b.append(f'<rect x="{x0}" y="{y}" width="{max(6, round(bw * share))}" height="22" rx="5" fill="{{acc}}"/>')
        b.append(t(x0 + bw + 14, y + 17, f"SI {si} ／ AI {ai}", 14, "text", "bold"))
    yb = 84 + len(rows) * 30 + 8
    b.append(t(24, yb + 14, "青がSI。NISTとCAISIは、過去の文書名や既存のプログラム名のAIを残している。国務省・OPMはAIの語自体が出なかったため除外", 12, "sub"))
    b.append(t(24, yb + 32, "メニューや過去の文書名も数に入る。0かどうかと大きな偏りは読めるが、細かい差に意味はない", 12, "sub"))
    return svg(w, h, "省庁ページ本文のSIとAIの出現比。DHSとCISAはほぼSI、NISTは約6割がSI、ai.govやOSTP、GSA、NSF、NASA、FTC、DOEなどはSIが0", b)


def main():
    for suffix, theme in THEMES.items():
        for name, fn in [("fig01-timeline", fig_timeline), ("fig02-nested", fig_nested), ("fig03-sites", fig_sites)]:
            s = fn()
            for k, v in theme.items():
                s = s.replace("{" + k + "}", v)
            (OUT / f"{name}{suffix}.svg").write_text(s)


if __name__ == "__main__":
    main()
