"""
GLAMWalk -- Volume 5: From Data to Product
04_opt_in_vision_enrichment.py

Opt-in image captioning for rows whose catalog text is too sparse to tag well: fetches an image once, temporarily, and always cleans up the temp file even if captioning fails.

Source: Volume Five, Section 2.2 -- An Opt-In Vision Pass
Targets Python 3.11.4 -- see Volume One, Chapter 1.5/1.6.

NOTE: This is a teaching example. Some names (e.g. a placeholder
value or object) stand in for something you'd supply yourself when
adapting the pattern to a real script.
"""

import re
import requests
import tempfile
import os

STOPWORDS = {"the", "a", "an", "of", "in", "on", "and", "with", "untitled"}


def extract_keywords(text):
    """Same function as in 03_tag_extraction_and_backfill.py --
    included here too so this file runs standalone."""
    words = re.findall(r"[a-z]+", (text or "").lower())
    return sorted(set(w for w in words if len(w) > 2 and w not in STOPWORDS))

def vision_enrich_row(row, describer, max_bytes=8_000_000):
    """
    Opt-in only: fetch an image ONCE, temporarily, caption it with a
    local vision model, merge the result into existing tags, then
    delete the temp file immediately. No persistent local copy is
    ever kept — this project's museum images are reference-only by
    design, and this function respects that even while enriching them.
    """
    response = requests.get(row["image_url"], timeout=20, stream=True)
    content = response.raw.read(max_bytes + 1)
    if len(content) > max_bytes:
        return None   # too large — skip rather than silently truncate

    with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp:
        tmp.write(content)
        tmp_path = tmp.name

    try:
        caption = describer.caption(tmp_path)   # local vision model call
        new_tags = extract_keywords(caption)
        existing_tags = set((row["tags_cache"] or "").split(","))
        merged = sorted(existing_tags | set(new_tags))
        return ",".join(merged)
    finally:
        os.remove(tmp_path)   # ALWAYS clean up, even if captioning raised
