#!/usr/bin/env python3
"""Generate one brand scene by the brandbook rules (draft of the scene section).

    python3 tools/scene.py <out.webp> "<object, one sentence>" --setting="..." [--mark="..."] [--aspect=16:9]

Built from presentations/skill/art.py (rules approved 26 September 2026), with the
brandbook changes: brand blue #026fe5 and deep navy #0b1d3f, brass the only warm
accent and only as a material, no aura rings, and a list of things that never appear.
The OpenRouter key is read from ~/.config/openrouter/key and never stored here.
"""
import base64
import io
import json
import os
import sys
import urllib.error
import urllib.request

from PIL import Image

MODEL = "openai/gpt-image-2.5-flare"
MARK_REF = os.path.normpath(os.path.join(os.path.dirname(__file__), "../../presentations/theme/logo/transparent_icon.png"))

WORLD = (
    "A premium, restrained but beautiful world, like high-end editorial still life photography, "
    "with a colour harmony built around the brand blue: the main tones are analogous blues "
    "(deep navy #0b1d3f, ink blue, slate blue, the brand blue #026fe5 only in light and small details) "
    "with neutral ivory, graphite and soft grey; warm brushed brass is the only complementary accent, "
    "appears on one or two objects at most and stays small. No green, no red, no purple. "
    "Rich natural materials: felt, leather, paper, glass, metal, dark wood only in small amounts. "
    "Soft directional warm light from a low lamp with gentle shadows, shallow depth of field, "
    "a feeling of quiet luxury and of a serious business at night."
)
CAMERA = (
    "The object rests the way it would in real life, in a believable situation, not a staged pun. "
    "Seen from slightly above with a long lens; the object is turned so that its front faces the left of the frame. "
)
NEVER = (
    "Never: neon, Las Vegas glitter, sparkles, piles of cash, banknotes, gold bars, slot machines, "
    "flashing lights, dice in the air, smoke, glowing rings or halos, visual puns, stock-photo look. "
    "No text, no letters, no digits, no people, no hands."
)
COMPOSITION = {
    "16:9": "The object sits in the right third of the frame; the left half is calm, empty background where text will be placed.",
}


def option(name, default=""):
    return next((a.split("=", 1)[1] for a in sys.argv if a.startswith(name + "=")), default)


def image_ref(path, size=512):
    png = io.BytesIO()
    im = Image.open(path).convert("RGBA")
    im.thumbnail((size, size), Image.LANCZOS)
    im.save(png, "PNG")
    return {"type": "image_url", "image_url": {"url": "data:image/png;base64," + base64.b64encode(png.getvalue()).decode()}}


def main():
    args = [a for a in sys.argv[1:] if not a.startswith("--")]
    if len(args) != 2:
        sys.exit(__doc__)
    out, subject = args
    aspect = option("--aspect", "16:9")
    prompt = ("Cinematic still life photograph, like a frame from an Apple product film. " + WORLD + " " + CAMERA
              + COMPOSITION.get(aspect, "The object is centered.") + " Premium, calm, uncluttered, one object and its setting only. "
              + NEVER + " Object: " + subject)
    setting = option("--setting")
    if setting:
        prompt += (" Setting, which tells the story of the picture and must be clearly visible and recognisable: "
                   + setting + ". The setting follows the palette of the world described above.")
    body = {"model": MODEL, "prompt": prompt, "aspect_ratio": aspect, "background": "opaque", "quality": "medium"}
    mark = option("--mark")
    if mark:
        body["input_references"] = [image_ref(MARK_REF)]
        body["prompt"] += (" The brand mark from the reference image (six rounded arrows around a Y shape) appears exactly once, "
                           + mark + ". It is part of the object's own design, as a product's branding would be: made in the "
                           "object's own material, engraved, debossed, inlaid or cast, tone on tone or in a quiet metal finish, "
                           "modest in size, never a coloured sticker laid on top. Keep its shape exact. It is the only mark; "
                           "there is still no text.")
    key = open(os.path.expanduser("~/.config/openrouter/key")).read().strip()
    req = urllib.request.Request("https://openrouter.ai/api/v1/images", data=json.dumps(body).encode(),
                                 headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"})
    try:
        resp = json.load(urllib.request.urlopen(req, timeout=300))
    except urllib.error.HTTPError as e:
        sys.exit(f"HTTP {e.code}: {e.read().decode()[:400]}")
    item = resp["data"][0]
    data = item.get("b64_json") or item["url"].split(",", 1)[1]
    im = Image.open(io.BytesIO(base64.b64decode(data))).convert("RGB")
    im.thumbnail((1600, 1600), Image.LANCZOS)
    im.save(out, "WEBP", quality=86, method=6)
    print(f"{out}  ${resp.get('usage', {}).get('cost', 0):.3f}")


if __name__ == "__main__":
    main()
