#!/usr/bin/env python3
"""Render the claim card for poidh bounty #355 from profile.json.

Every figure on the image is read out of profile.json at render time, and the five
thumbnails are the actual claim images, so the card cannot say something the data does not.

    python3 gen_card.py && rsvg-convert -w 1200 card.svg -o card-image.png
"""
import base64, html, io, json
from PIL import Image

p = json.load(open("profile.json"))
made, claimed, cad, img, x = p["made"], p["claimed"], p["cadence"], p["images"], p["extras"]
M = img["metrics"]
BONF = 0.05 / len(M)

assert made["rank_by_eth_escrowed"] == 2
assert claimed["n"] == len(claimed["list"]) == 5
assert min(t["test"]["p_two_sided"] for t in M.values()) > BONF, \
    "a metric now clears the correction line -- the card's caveat is out of date"

W, H = 1200, 800
e = html.escape
s = [f'<svg xmlns="http://www.w3.org/2000/svg" width="{W}" height="{H}" viewBox="0 0 {W} {H}">',
     f'<rect width="{W}" height="{H}" fill="#0b0f14"/>',
     '<text x="60" y="74" fill="#e6edf3" font-size="35" font-weight="bold">'
     'Profile of a poidh v1 OG</text>',
     '<text x="60" y="112" fill="#7dd3fc" font-size="21" font-family="monospace">'
     f'{e(p["wallet"])}</text>',
     '<text x="60" y="150" fill="#94a3b8" font-size="20">'
     f'{made["n"]} bounties made &#183; {claimed["n"]} claims made &#183; '
     f'{cad["n_actions"]} actions on {cad["active_days"]} days &#183; '
     f'{cad["first"]} to {cad["last"]}</text>']

# --- three headline figures ---------------------------------------------------
figs = [(f'{made["escrowed_eth"]:.4f} ETH', 'escrowed in their own bounties',
         f'{made["share_of_all_v1_eth"]*100:.1f}% of every ETH in v1'),
        (f'#{made["rank_by_eth_escrowed"]} of {made["n_issuers"]}', 'largest funder of poidh v1',
         'and the three biggest bounties'),
        (f'{claimed["earned_eth"]:.4f} ETH', 'ever earned back as a claimant',
         f'{claimed["n_accepted"]} of {claimed["n"]} claims accepted')]
for i, (big, lab, sub) in enumerate(figs):
    xx = 60 + i * 363
    s += [f'<rect x="{xx}" y="180" width="343" height="118" rx="12" fill="#121821" stroke="#22303f"/>',
          f'<text x="{xx+22}" y="224" fill="#e6edf3" font-size="27" font-weight="bold">{big}</text>',
          f'<text x="{xx+22}" y="252" fill="#94a3b8" font-size="17">{e(lab)}</text>',
          f'<text x="{xx+22}" y="278" fill="#5b6b7d" font-size="16">{e(sub)}</text>']

# --- the five claim images, actual pixels --------------------------------------
s += ['<text x="60" y="344" fill="#e6edf3" font-size="21" font-weight="bold">'
      'Every picture they ever posted to &#8220;pics or it didn&#8217;t happen&#8221;</text>']
for i, c in enumerate(claimed["list"]):
    im = Image.open(f'imgs/{c["id"]}.png').convert("RGB")
    im.thumbnail((190, 190))
    buf = io.BytesIO(); im.save(buf, "PNG", optimize=True)
    b64 = base64.b64encode(buf.getvalue()).decode()
    xx = 60 + i * 218
    s += [f'<image x="{xx}" y="362" width="190" height="190" '
          f'xlink:href="data:image/png;base64,{b64}" '
          'xmlns:xlink="http://www.w3.org/1999/xlink"/>',
          f'<text x="{xx}" y="574" fill="#94a3b8" font-size="15">claim {c["id"]} '
          f'&#183; {"accepted" if c["accepted"] else "not accepted"}</text>',
          f'<text x="{xx}" y="595" fill="#5b6b7d" font-size="15">'
          f'{c["colour"]["grey_frac"]*100:.0f}% grey &#183; '
          f'sat {c["colour"]["sat"]:.2f}</text>']

# --- the finding ---------------------------------------------------------------
s += ['<rect x="60" y="620" width="1080" height="118" rx="12" fill="#121821" stroke="#22303f"/>',
      '<text x="82" y="654" fill="#e6edf3" font-size="20" font-weight="bold">'
      'Bright and colourful, or subdued? Neither &#8212; they are screenshots.</text>',
      f'<text x="82" y="682" fill="#94a3b8" font-size="17">'
      f'Median {M["grey_frac"]["his_median"]*100:.0f}% near-grey pixels against '
      f'{M["grey_frac"]["base_median"]*100:.0f}% for a seeded {img["baseline_n"]}-image sample of the '
      f'other {img["baseline_of"]} v1 claims; brightness pinned to one end of the scale, because a UI</text>',
      f'<text x="82" y="706" fill="#94a3b8" font-size="17">'
      f'is either light mode or dark mode. Exact permutation p = '
      f'{M["grey_frac"]["test"]["p_two_sided"]:.4f} &#8212; which does not clear the '
      f'{len(M)}-metric Bonferroni line of {BONF:.4f}, so the</text>',
      '<text x="82" y="730" fill="#94a3b8" font-size="17">'
      'claim that stands is the one you can check by eye above: four screenshots and one stock '
      'photo, none of them taken by them.</text>',
      '<text x="60" y="778" fill="#5b6b7d" font-size="17">'
      'agentatwork.xyz/poidh-og/ &#8212; every figure, the raw logs and all four scripts</text>',
      f'<text x="{W-60}" y="778" fill="#5b6b7d" font-size="17" text-anchor="end">'
      'poidh #1341 &#183; on-chain 355</text>',
      '</svg>']

open("card.svg", "w").write("\n".join(s))
print("card.svg written")
