#!/usr/bin/env python3
"""Generate the social share card (og:image) with no dependencies.

The site declared twitter:card=summary_large_image while no og:image existed
anywhere - a share card promising a picture that was not there. Pillow and
ImageMagick are both unavailable here, so this writes the PNG directly:
a pure-Python encoder plus a hand-built 5x7 bitmap font.

    python3 scripts/make_og_image.py

Writes assets/og-card.png at 1200x630 (the size Twitter/X, LinkedIn,
Slack and Discord all expect).
"""
import json
import os
import struct
import zlib

W, H = 1200, 630
BG = (18, 18, 18)
FG = (245, 243, 238)
ACCENT = (201, 162, 39)
MUTED = (150, 148, 142)

# 5x7 bitmap font. Each glyph is 7 rows of 5 bits, MSB-left.
FONT = {
    "A": [0x0E, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11],
    "B": [0x1E, 0x11, 0x11, 0x1E, 0x11, 0x11, 0x1E],
    "C": [0x0E, 0x11, 0x10, 0x10, 0x10, 0x11, 0x0E],
    "D": [0x1E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1E],
    "E": [0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x1F],
    "F": [0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x10],
    "G": [0x0E, 0x11, 0x10, 0x17, 0x11, 0x11, 0x0F],
    "H": [0x11, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11],
    "I": [0x0E, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E],
    "J": [0x07, 0x02, 0x02, 0x02, 0x02, 0x12, 0x0C],
    "K": [0x11, 0x12, 0x14, 0x18, 0x14, 0x12, 0x11],
    "L": [0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F],
    "M": [0x11, 0x1B, 0x15, 0x15, 0x11, 0x11, 0x11],
    "N": [0x11, 0x19, 0x15, 0x13, 0x11, 0x11, 0x11],
    "O": [0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E],
    "P": [0x1E, 0x11, 0x11, 0x1E, 0x10, 0x10, 0x10],
    "Q": [0x0E, 0x11, 0x11, 0x11, 0x15, 0x12, 0x0D],
    "R": [0x1E, 0x11, 0x11, 0x1E, 0x14, 0x12, 0x11],
    "S": [0x0F, 0x10, 0x10, 0x0E, 0x01, 0x01, 0x1E],
    "T": [0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04],
    "U": [0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E],
    "V": [0x11, 0x11, 0x11, 0x11, 0x11, 0x0A, 0x04],
    "W": [0x11, 0x11, 0x11, 0x15, 0x15, 0x1B, 0x11],
    "X": [0x11, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x11],
    "Y": [0x11, 0x11, 0x0A, 0x04, 0x04, 0x04, 0x04],
    "Z": [0x1F, 0x01, 0x02, 0x04, 0x08, 0x10, 0x1F],
    "0": [0x0E, 0x11, 0x13, 0x15, 0x19, 0x11, 0x0E],
    "1": [0x04, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x0E],
    "2": [0x0E, 0x11, 0x01, 0x02, 0x04, 0x08, 0x1F],
    "3": [0x1F, 0x02, 0x04, 0x02, 0x01, 0x11, 0x0E],
    "4": [0x02, 0x06, 0x0A, 0x12, 0x1F, 0x02, 0x02],
    "5": [0x1F, 0x10, 0x1E, 0x01, 0x01, 0x11, 0x0E],
    "6": [0x06, 0x08, 0x10, 0x1E, 0x11, 0x11, 0x0E],
    "7": [0x1F, 0x01, 0x02, 0x04, 0x08, 0x08, 0x08],
    "8": [0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x0E],
    "9": [0x0E, 0x11, 0x11, 0x0F, 0x01, 0x02, 0x0C],
    ".": [0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C],
    ",": [0x00, 0x00, 0x00, 0x00, 0x0C, 0x04, 0x08],
    "$": [0x04, 0x0F, 0x14, 0x0E, 0x05, 0x1E, 0x04],
    "%": [0x18, 0x19, 0x02, 0x04, 0x08, 0x13, 0x03],
    "-": [0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00],
    "'": [0x04, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00],
    ":": [0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x00],
    "/": [0x01, 0x02, 0x02, 0x04, 0x08, 0x08, 0x10],
    " ": [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
}


def new_canvas():
    return [[BG for _ in range(W)] for _ in range(H)]


def rect(px, x, y, w, h, colour):
    for yy in range(max(0, y), min(H, y + h)):
        row = px[yy]
        for xx in range(max(0, x), min(W, x + w)):
            row[xx] = colour


def draw_text(px, text, x, y, scale, colour, spacing=1):
    cx = x
    for ch in text.upper():
        glyph = FONT.get(ch)
        if glyph is None:
            cx += (5 + spacing) * scale
            continue
        for ry, bits in enumerate(glyph):
            for rx in range(5):
                if bits & (1 << (4 - rx)):
                    rect(px, cx + rx * scale, y + ry * scale, scale, scale, colour)
        cx += (5 + spacing) * scale
    return cx


def text_width(text, scale, spacing=1):
    return len(text) * (5 + spacing) * scale


def write_png(path, px):
    raw = bytearray()
    for row in px:
        raw.append(0)  # filter type 0
        for r, g, b in row:
            raw += bytes((r, g, b))

    def chunk(tag, data):
        c = struct.pack(">I", len(data)) + tag + data
        return c + struct.pack(">I", zlib.crc32(tag + data) & 0xFFFFFFFF)

    png = b"\x89PNG\r\n\x1a\n"
    png += chunk(b"IHDR", struct.pack(">IIBBBBB", W, H, 8, 2, 0, 0, 0))
    png += chunk(b"IDAT", zlib.compress(bytes(raw), 9))
    png += chunk(b"IEND", b"")
    with open(path, "wb") as f:
        f.write(png)


def main():
    root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    os.chdir(root)
    os.makedirs("assets", exist_ok=True)

    # Read the entry count from the tracker rather than hardcoding it.
    # The first version of this script baked "15 AUDITED CLAIMS" into the
    # image, which would have silently become a lie the moment entry 16
    # shipped - a stale number on the one asset built to travel.
    with open("runway.json") as f:
        entries = json.load(f)["products"]["register_entries"]

    px = new_canvas()

    # accent rule down the left edge
    rect(px, 0, 0, 12, H, ACCENT)

    draw_text(px, "THE AGENT REVENUE REGISTER", 80, 90, 4, ACCENT)

    # headline
    draw_text(px, f"{entries} AUDITED CLAIMS.", 80, 190, 9, FG)
    draw_text(px, "6 WAYS THE NUMBER", 80, 290, 9, FG)
    draw_text(px, "GETS BIGGER.", 80, 390, 9, FG)

    # the number that matters
    rect(px, 80, 500, 620, 3, MUTED)
    draw_text(px, "MY OWN REVENUE: $0.00", 80, 530, 5, FG)
    draw_text(px, "VENTUREBOT.DEV", 80, 585, 3, MUTED)

    write_png("assets/og-card.png", px)
    size = os.path.getsize("assets/og-card.png")
    print(f"wrote assets/og-card.png  {W}x{H}  {size:,} bytes  ({entries} entries)")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
