"""gem.py -- one Gemini call (text, optional PNGs), so the reef's small judgments don't spend the Claude subscription (Ivy, Oct 23
2026: "We could route thru gemini to offgas the usage"). Same shape as favorites/haiku.py: ask(text, images, max_tokens) -> (text,
usage). Tries each Gemini key on the machine (they are different Google projects with separate daily quotas -- see ~/ask_gemini.py).
Written by Iris."""
import os, json, base64, urllib.request, urllib.error

MODEL = os.environ.get('GEM_MODEL', 'gemini-3.5-flash-lite')

def _keys():
    out = []
    for pth in ('~/.gemini_api_key', '~/.gemini_key'):
        f = os.path.expanduser(pth)
        if os.path.exists(f):
            k = open(f).read().strip()
            if k.startswith('AIza') and k not in out: out.append(k)
    return out

def ask(text, images=(), max_tokens=400, model=None, timeout=30):
    parts = [{'inline_data': {'mime_type': 'image/png', 'data': base64.b64encode(open(p, 'rb').read()).decode()}} for p in images]
    parts.append({'text': text})
    # no thinkingConfig: Gemini 3 models reject the old thinkingBudget (400 INVALID_ARGUMENT), and 3.5-flash-lite answers a
    # yes/no in ~0.7 s without one; 3.8-flash took 13-30 s a call (Oct 23 2026)
    body = {'contents': [{'parts': parts}], 'generationConfig': {'maxOutputTokens': max(max_tokens, 16), 'temperature': 0.2}}
    last = None
    for key in _keys():
        url = f'https://generativelanguage.googleapis.com/v1beta/models/{model or MODEL}:generateContent?key={key}'
        try:
            r = urllib.request.Request(url, data=json.dumps(body).encode(), headers={'content-type': 'application/json'})
            j = json.load(urllib.request.urlopen(r, timeout=timeout))
            t = ''.join(p.get('text', '') for p in j['candidates'][0]['content'].get('parts', []))
            return t, j.get('usageMetadata', {})
        except urllib.error.HTTPError as e:
            last = f'{e.code} {e.read().decode()[:200]}'
            if e.code in (429, 403): continue          # that project's quota: try the next key
            raise RuntimeError(last)
    raise RuntimeError(last or 'no Gemini key')
