#!/usr/bin/env python3
"""Generate Chrome Web Store graphic assets for "Rewrite with AI".

Outputs (PNG, in ./graphics):
  promo-small-440x280.png      small promo tile
  promo-marquee-1400x560.png   marquee promo tile
  screenshot-1..5 (1280x800)   listing screenshots

Run:  python3 generate_assets.py
"""
import os
from PIL import Image, ImageDraw, ImageFont, ImageFilter

OUT = os.path.join(os.path.dirname(__file__), "graphics")
os.makedirs(OUT, exist_ok=True)

# ---- brand palette -------------------------------------------------------
BLUE      = (37, 99, 235)     # #2563eb
BLUE_DK   = (29, 78, 216)     # #1d4ed8
BLUE_LT   = (239, 246, 255)   # #eff6ff
INK       = (30, 41, 59)      # #1e293b slate-800
SLATE     = (100, 116, 139)   # #64748b slate-500
SLATE_LT  = (148, 163, 184)   # #94a3b8
LINE      = (203, 213, 225)   # #cbd5e1
PANEL     = (248, 250, 252)   # #f8fafc slate-50
WHITE     = (255, 255, 255)
AMBER     = (180, 83, 9)      # #b45309

FONT_DIR = "/usr/share/fonts/truetype/dejavu"
def font(size, bold=False, mono=False):
    if mono:
        name = "DejaVuSansMono-Bold.ttf" if bold else "DejaVuSansMono.ttf"
    else:
        name = "DejaVuSans-Bold.ttf" if bold else "DejaVuSans.ttf"
    return ImageFont.truetype(os.path.join(FONT_DIR, name), size)

def text_w(d, s, f):
    return d.textbbox((0, 0), s, font=f)[2]

def center(d, cx, y, s, f, fill):
    d.text((cx - text_w(d, s, f) / 2, y), s, font=f, fill=fill)

def rrect(d, box, r, fill=None, outline=None, width=1):
    d.rounded_rectangle(box, radius=r, fill=fill, outline=outline, width=width)

def soft_shadow(img, box, r, blur=18, offset=(0, 10), alpha=70):
    """Composite a soft drop shadow for a rounded rect onto `img` (RGB)."""
    x0, y0, x1, y1 = box
    pad = blur * 3
    layer = Image.new("RGBA", img.size, (0, 0, 0, 0))
    ld = ImageDraw.Draw(layer)
    ld.rounded_rectangle([x0 + offset[0], y0 + offset[1],
                          x1 + offset[0], y1 + offset[1]],
                         radius=r, fill=(15, 23, 42, alpha))
    layer = layer.filter(ImageFilter.GaussianBlur(blur))
    img.paste(Image.alpha_composite(img.convert("RGBA"), layer).convert("RGB"),
              (0, 0))

def logo(d, x, y, size, radius_ratio=0.22):
    """White R on a blue rounded square, top-left at (x,y)."""
    rrect(d, [x, y, x + size, y + size], int(size * radius_ratio), fill=BLUE)
    f = font(int(size * 0.66), bold=True)
    s = "R"
    bb = d.textbbox((0, 0), s, font=f)
    tw, th = bb[2] - bb[0], bb[3] - bb[1]
    d.text((x + (size - tw) / 2 - bb[0], y + (size - th) / 2 - bb[1]),
           s, font=f, fill=WHITE)

def wrap(d, s, f, max_w):
    words, lines, cur = s.split(), [], ""
    for w in words:
        t = (cur + " " + w).strip()
        if text_w(d, t, f) <= max_w:
            cur = t
        else:
            if cur:
                lines.append(cur)
            cur = w
    if cur:
        lines.append(cur)
    return lines

def browser_chrome(d, box, url):
    """Draw a faux browser window frame; return inner content box."""
    x0, y0, x1, y1 = box
    rrect(d, box, 16, fill=WHITE, outline=LINE, width=2)
    # top bar
    bar_h = 52
    d.rounded_rectangle([x0, y0, x1, y0 + bar_h + 16], radius=16, fill=PANEL)
    d.rectangle([x0, y0 + bar_h, x1, y0 + bar_h + 16], fill=PANEL)
    for i, c in enumerate([(237, 106, 94), (245, 191, 79), (97, 197, 84)]):
        cx = x0 + 26 + i * 26
        cy = y0 + bar_h / 2
        d.ellipse([cx - 7, cy - 7, cx + 7, cy + 7], fill=c)
    # url pill
    rrect(d, [x0 + 110, y0 + 12, x1 - 24, y0 + bar_h - 12], 14,
          fill=WHITE, outline=LINE, width=1)
    d.text((x0 + 128, y0 + 17), url, font=font(18), fill=SLATE)
    d.line([x0, y0 + bar_h + 16, x1, y0 + bar_h + 16], fill=LINE, width=1)
    return (x0, y0 + bar_h + 16, x1, y1)

# =========================================================================
# PROMO: small tile 440x280
# =========================================================================
def promo_small():
    W, H = 440, 280
    img = Image.new("RGB", (W, H), WHITE)
    d = ImageDraw.Draw(img)
    d.rectangle([0, 0, W, H], fill=BLUE)
    # subtle darker panel band at bottom
    d.rectangle([0, H - 84, W, H], fill=BLUE_DK)
    logo(d, W / 2 - 44, 40, 88)
    center(d, W / 2, 144, "Rewrite with AI", font(34, bold=True), WHITE)
    center(d, W / 2, 188, "Highlight. Right-click. Rewrite.",
           font(18), (219, 234, 254))
    center(d, W / 2, H - 60, "Powered by ChatGPT", font(17, bold=True), WHITE)
    img.save(os.path.join(OUT, "promo-small-440x280.png"))

# =========================================================================
# PROMO: marquee 1400x560
# =========================================================================
def promo_marquee():
    W, H = 1400, 560
    img = Image.new("RGB", (W, H), BLUE)
    d = ImageDraw.Draw(img)
    # diagonal lighter wedge on the right
    d.polygon([(W * 0.52, 0), (W, 0), (W, H), (W * 0.34, H)], fill=BLUE_DK)

    # left: message
    lx = 90
    logo(d, lx, 96, 96)
    d.text((lx + 120, 110), "Rewrite with AI", font=font(40, bold=True), fill=WHITE)
    d.text((lx, 230), "Better writing,", font=font(72, bold=True), fill=WHITE)
    d.text((lx, 312), "without leaving", font=font(72, bold=True), fill=WHITE)
    d.text((lx, 394), "the page.", font=font(72, bold=True), fill=(191, 219, 254))
    d.text((lx + 4, 488),
           "Highlight any text  •  right-click  •  pick a style",
           font=font(24), fill=(219, 234, 254))

    # right: mock context menu card
    cx0, cy0 = 880, 120
    cw, ch = 420, 330
    # selection chip
    rrect(d, [cx0, cy0 - 4, cx0 + cw, cy0 + 44], 8, fill=(191, 219, 254))
    d.text((cx0 + 16, cy0 + 8), "“our launch went pretty good…”",
           font=font(20), fill=INK)
    # menu
    my = cy0 + 70
    rrect(d, [cx0, my, cx0 + cw, my + ch], 16, fill=WHITE, outline=LINE, width=2)
    d.text((cx0 + 22, my + 16), "Rewrite with AI", font=font(20, bold=True), fill=BLUE)
    d.line([cx0 + 16, my + 52, cx0 + cw - 16, my + 52], fill=LINE, width=1)
    items = ["Summarize this", "Rewrite this better", "Rewrite professionally",
             "Rewrite casual", "Shorten this text", "Extend this text"]
    iy = my + 66
    for i, it in enumerate(items):
        if i == 1:
            rrect(d, [cx0 + 10, iy - 6, cx0 + cw - 10, iy + 30], 8, fill=BLUE_LT)
        d.text((cx0 + 24, iy), it, font=font(20),
               fill=INK if i == 1 else SLATE)
        iy += 42
    img.save(os.path.join(OUT, "promo-marquee-1400x560.png"))

# =========================================================================
# SCREENSHOTS 1280x800
# =========================================================================
SW, SH = 1280, 800

def shot_base(title, subtitle):
    img = Image.new("RGB", (SW, SH), BLUE)
    d = ImageDraw.Draw(img)
    d.rectangle([0, 0, SW, SH], fill=PANEL)
    # header band
    d.rectangle([0, 0, SW, 150], fill=BLUE)
    logo(d, 56, 40, 64)
    d.text((140, 46), title, font=font(40, bold=True), fill=WHITE)
    d.text((140, 100), subtitle, font=font(22), fill=(219, 234, 254))
    return img, d

def shot1():
    """Right-click menu over a text box."""
    img, d = shot_base("Rewrite anything in place", "Select text → right-click → pick a style")
    inner = browser_chrome(d, [80, 200, SW - 80, SH - 60], "mail.google.com  ·  Compose")
    x0, y0, x1, y1 = inner
    pad = 40
    # compose box
    rrect(d, [x0 + pad, y0 + pad, x1 - pad, y1 - pad], 12, fill=WHITE,
          outline=LINE, width=2)
    tx, ty = x0 + pad + 28, y0 + pad + 28
    f = font(24)
    d.text((tx, ty), "Hi team,", font=f, fill=INK)
    # highlighted sentence
    sel = "our launch went pretty good and we got a lot of signups"
    lines = wrap(d, sel, f, x1 - pad - 28 - tx)
    sy = ty + 48
    for ln in lines:
        w = text_w(d, ln, f)
        d.rectangle([tx - 4, sy - 2, tx + w + 4, sy + 30], fill=(191, 219, 254))
        d.text((tx, sy), ln, font=f, fill=INK)
        sy += 40
    d.text((tx, sy + 8), "Let me know what you think.", font=f, fill=INK)

    # context menu near selection
    mx, my = tx + 220, sy - 30
    mw = 320
    items = ["Summarize this", "Rewrite this better", "Rewrite professionally",
             "Rewrite casual", "Shorten this text", "Extend this text"]
    mh = 60 + len(items) * 44
    soft_shadow(img, [mx, my, mx + mw, my + mh], 14, blur=16, offset=(0, 10), alpha=80)
    d = ImageDraw.Draw(img)
    rrect(d, [mx, my, mx + mw, my + mh], 14, fill=WHITE, outline=LINE, width=2)
    d.text((mx + 20, my + 16), "Rewrite with AI", font=font(20, bold=True), fill=BLUE)
    d.line([mx + 14, my + 50, mx + mw - 14, my + 50], fill=LINE, width=1)
    iy = my + 62
    for i, it in enumerate(items):
        if i == 1:
            rrect(d, [mx + 8, iy - 5, mx + mw - 8, iy + 31], 8, fill=BLUE_LT)
        d.text((mx + 22, iy), it, font=font(20), fill=INK if i == 1 else SLATE)
        iy += 44
    img.save(os.path.join(OUT, "screenshot-1-rightclick.png"))

def shot2():
    """In-place replacement before/after."""
    img, d = shot_base("Replaces your selection", "The rewrite drops right back into the box")
    colw = (SW - 80 - 80 - 40) / 2
    # before card
    for idx, (label, lblcol, txt, txtcol) in enumerate([
        ("BEFORE", SLATE, "our launch went pretty good and we got a lot of signups",
         INK),
        ("AFTER", BLUE, "Our launch was a strong success, driving a significant "
         "number of new signups.", INK)]):
        cx = 80 + idx * (colw + 40)
        cy = 230
        ch = 420
        rrect(d, [cx, cy, cx + colw, cy + ch], 16, fill=WHITE,
              outline=BLUE if idx else LINE, width=3 if idx else 2)
        d.text((cx + 24, cy + 22), label, font=font(18, bold=True), fill=lblcol)
        if idx:
            chip = "Rewrite this professionally"
            cw = text_w(d, chip, font(16)) + 28
            rrect(d, [cx + colw - cw - 24, cy + 18, cx + colw - 24, cy + 46], 14,
                  fill=BLUE_LT)
            d.text((cx + colw - cw - 24 + 14, cy + 22), chip, font=font(16),
                   fill=BLUE)
        f = font(26)
        lines = wrap(d, txt, f, colw - 48)
        yy = cy + 80
        for ln in lines:
            d.text((cx + 24, yy), ln, font=f, fill=txtcol)
            yy += 40
    # arrow
    ax = 80 + colw + 20
    d.text((ax - 14, 420), "→", font=font(56, bold=True), fill=BLUE)
    img.save(os.path.join(OUT, "screenshot-2-inplace.png"))

def shot3():
    """Inline autocomplete with /// triggers."""
    img, d = shot_base("Inline autocomplete", "Type /// for a hint, //// to continue — Tab to insert")
    inner = browser_chrome(d, [80, 200, SW - 80, SH - 60], "docs.google.com")
    x0, y0, x1, y1 = inner
    pad = 44
    rrect(d, [x0 + pad, y0 + pad, x1 - pad, y1 - pad], 12, fill=WHITE,
          outline=LINE, width=2)
    tx, ty = x0 + pad + 28, y0 + pad + 30
    f = font(24)
    fm = font(23, mono=True)
    d.text((tx, ty), "Thanks for the detailed report. In conclusion,",
           font=f, fill=INK)
    # the trigger text
    trig = "///wrap up optimistically///"
    d.text((tx, ty + 44), trig, font=fm, fill=BLUE)
    cur_x = tx + text_w(d, trig, fm) + 6
    d.rectangle([cur_x, ty + 44, cur_x + 3, ty + 44 + 30], fill=INK)  # caret

    # suggestion popup
    px, py = tx + 40, ty + 100
    sug = "we're confident next quarter will be even stronger."
    f2 = font(22)
    lines = wrap(d, sug, f2, 480)
    ph = 60 + len(lines) * 32 + 54
    pw = 540
    soft_shadow(img, [px, py, px + pw, py + ph], 14, blur=16, offset=(0, 8), alpha=70)
    d = ImageDraw.Draw(img)
    rrect(d, [px, py, px + pw, py + ph], 14, fill=WHITE, outline=BLUE, width=2)
    d.text((px + 20, py + 16), "Suggestion", font=font(16, bold=True), fill=SLATE)
    yy = py + 46
    for ln in lines:
        d.text((px + 20, yy), ln, font=f2, fill=INK)
        yy += 32
    # Tab / Esc hints
    rrect(d, [px + 20, yy + 12, px + 90, yy + 44], 8, fill=BLUE)
    d.text((px + 38, yy + 17), "Tab", font=font(18, bold=True), fill=WHITE)
    d.text((px + 104, yy + 17), "insert", font=font(18), fill=SLATE)
    rrect(d, [px + 200, yy + 12, px + 270, yy + 44], 8, fill=PANEL,
          outline=LINE, width=1)
    d.text((px + 216, yy + 17), "Esc", font=font(18, bold=True), fill=SLATE)
    d.text((px + 284, yy + 17), "dismiss", font=font(18), fill=SLATE)

    # legend of triggers — vertical stack on the right, clear of the popup
    lx2 = 770
    ly2 = ty - 4
    d.text((lx2, ly2), "TRIGGERS", font=font(16, bold=True), fill=SLATE_LT)
    ly2 += 36
    legend = [("///hint///", "suggest the next sentence from a hint"),
              ("////", "continue, using the surrounding text"),
              ("////instruction////", "run a custom instruction")]
    for code, desc in legend:
        cw = text_w(d, code, font(18, mono=True)) + 24
        rrect(d, [lx2, ly2, lx2 + cw, ly2 + 34], 6, fill=BLUE_LT)
        d.text((lx2 + 12, ly2 + 5), code, font=font(18, mono=True), fill=BLUE)
        d.text((lx2, ly2 + 44), desc, font=font(18), fill=SLATE)
        ly2 += 92
    img.save(os.path.join(OUT, "screenshot-3-autocomplete.png"))

def shot4():
    """Two modes."""
    img, d = shot_base("Two ways to reach ChatGPT", "Use your own API key, or drive a ChatGPT tab — no key needed")
    colw = (SW - 80 - 80 - 44) / 2
    cards = [
        (BLUE, WHITE, "API key mode", [
            "Paste your OpenAI API key",
            "Calls the official OpenAI API",
            "Fast & stable — best for autocomplete",
            "Billed to your OpenAI account",
        ], "RECOMMENDED"),
        (WHITE, INK, "ChatGPT tab mode", [
            "No API key required",
            "Drives a real chatgpt.com tab",
            "Uses your own logged-in session",
            "Free — depends on the live site",
        ], "NO KEY NEEDED"),
    ]
    for idx, (bg, fg, title, bullets, badge) in enumerate(cards):
        cx = 80 + idx * (colw + 44)
        cy = 240
        ch = 440
        rrect(d, [cx, cy, cx + colw, cy + ch], 18, fill=bg,
              outline=LINE if idx else None, width=2)
        d.text((cx + 32, cy + 34), title, font=font(32, bold=True), fill=fg)
        # badge
        bcol_bg = WHITE if idx == 0 else BLUE_LT
        bcol_fg = BLUE
        bw = text_w(d, badge, font(15, bold=True)) + 28
        rrect(d, [cx + 32, cy + 84, cx + 32 + bw, cy + 84 + 30], 14, fill=bcol_bg)
        d.text((cx + 32 + 14, cy + 89), badge, font=font(15, bold=True), fill=bcol_fg)
        yy = cy + 150
        sub = (219, 234, 254) if idx == 0 else SLATE
        for b in bullets:
            d.ellipse([cx + 34, yy + 8, cx + 44, yy + 18],
                      fill=WHITE if idx == 0 else BLUE)
            for j, ln in enumerate(wrap(d, b, font(23), colw - 90)):
                d.text((cx + 62, yy), ln, font=font(23), fill=fg)
                yy += 32
            yy += 18
    img.save(os.path.join(OUT, "screenshot-4-modes.png"))

def shot5():
    """Whole-page summary in a modal."""
    img, d = shot_base("No selection? Summarize the page", "Right-click with nothing selected to act on the whole page")
    inner = browser_chrome(d, [80, 200, SW - 80, SH - 60], "en.wikipedia.org/wiki/Photosynthesis")
    x0, y0, x1, y1 = inner
    # faint page text behind
    f = font(20)
    yy = y0 + 36
    para = ("Photosynthesis is the process used by plants, algae and some "
            "bacteria to convert light energy into chemical energy. " * 6)
    for ln in wrap(d, para, f, x1 - x0 - 80)[:9]:
        d.text((x0 + 40, yy), ln, font=f, fill=SLATE_LT)
        yy += 30
    # dim overlay clipped to the rounded content area
    ov = Image.new("RGBA", (SW, SH), (0, 0, 0, 0))
    od = ImageDraw.Draw(ov)
    od.rounded_rectangle([x0, y0, x1, y1], radius=14, fill=(15, 23, 42, 150))
    img.paste(Image.alpha_composite(img.convert("RGBA"), ov).convert("RGB"), (0, 0))
    base = img
    # modal
    mw, mh = 720, 360
    mx, my = (SW - mw) / 2, 270
    soft_shadow(base, [mx, my, mx + mw, my + mh], 18, blur=22, offset=(0, 14), alpha=120)
    bd = ImageDraw.Draw(base)
    rrect(bd, [mx, my, mx + mw, my + mh], 18, fill=WHITE, outline=LINE, width=2)
    bd.text((mx + 32, my + 26), "Summary", font=font(26, bold=True), fill=INK)
    rrect(bd, [mx + mw - 130, my + 24, mx + mw - 32, my + 60], 10, fill=BLUE)
    bd.text((mx + mw - 130 + 22, my + 30), "Copy", font=font(20, bold=True), fill=WHITE)
    bd.line([mx + 32, my + 76, mx + mw - 32, my + 76], fill=LINE, width=1)
    summ = ("Photosynthesis lets plants, algae, and some bacteria turn light "
            "into chemical energy, producing the oxygen and food that most "
            "life on Earth depends on.")
    yy = my + 100
    for ln in wrap(bd, summ, font(24), mw - 72):
        bd.text((mx + 32, yy), ln, font=font(24), fill=INK)
        yy += 36
    bd.text((mx + 32, my + mh - 50),
            "Not editable? The result shows here with a Copy button.",
            font=font(19), fill=SLATE)
    base.save(os.path.join(OUT, "screenshot-5-summary.png"))

if __name__ == "__main__":
    promo_small()
    promo_marquee()
    shot1()
    shot2()
    shot3()
    shot4()
    shot5()
    print("Done. Files in:", OUT)
    for fn in sorted(os.listdir(OUT)):
        print("  ", fn)
