import os
import json
import time
import random
from pathlib import Path
from google import genai
from google.genai import types

GEMINI_API_KEY = os.environ["GEMINI_API_KEY"]
client = genai.Client(api_key=GEMINI_API_KEY)

# ─────────────────────────────────────────────────────────────────────────────
# ORDRE CRITIQUE :
#   Image 0 = grille overview (ancre tous les variants de créatures)
#   Images 1-7 = chaque créature individuelle (référence détaillée)
#   Image 8 = Parent (personnage secondaire)
# ─────────────────────────────────────────────────────────────────────────────
REFS = {
    # --- APERCU GLOBAL (Image 0) — poids le plus fort pour la cohérence ---
    "emotion_grid":   "emotion_grid.png",        # Image 0 -> All 7 creature forms overview

    # --- CRÉATURES INDIVIDUELLES (Images 1 à 7) ---
    "happy":          "happy_creature.png",      # Image 1 -> JOY FORM (yellow bouncy)
    "fun":            "fun_creature.png",         # Image 2 -> AMUSEMENT FORM (orange stretchy)
    "calm":           "calm.png",                 # Image 3 -> CALM FORM (light blue oval)
    "sad":            "sad_creature.png",         # Image 4 -> SADNESS FORM (navy gelatin)
    "fear":           "fear_creature.png",        # Image 5 -> FEAR FORM (purple trembling)
    "anger":          "anger_creature.png",       # Image 6 -> ANGER FORM (red spiky)
    "confidence":     "confidence_creature.png",  # Image 7 -> CONFIDENCE FORM (gold star)

    # --- PARENT (Image 8) ---
    "mom":            "mom.png",                  # Image 8 -> Le Parent
}

CHARACTER_MAPPING = (
    "STRICT IDENTITY MAPPING — follow exactly: "
    "Image 0 = OVERVIEW of all 7 emotion creature forms — use for visual consistency reference. "
    "Image 1 = JOY CREATURE (Character 1, yellow bouncy form). "
    "Image 2 = AMUSEMENT CREATURE (Character 2, orange stretchy form). "
    "Image 3 = CALM CREATURE (Character 3, light blue oval form). "
    "Image 4 = SADNESS CREATURE (Character 4, navy gelatin form). "
    "Image 5 = FEAR CREATURE (Character 5, purple trembling form). "
    "Image 6 = ANGER CREATURE (Character 6, red spiky form). "
    "Image 7 = CONFIDENCE CREATURE (Character 7, gold star form). "
    "Image 8 = LE PARENT WOMAN (Character 8). "
)

LOCK_PHRASES = (
    "Maintain strict visual likeness of every emotion creature as shown in their individual reference image. "
    "Each creature form has a UNIQUE shape, color, and texture — do not mix or confuse them. "
    "Ensure character structure, colors, and textures remain 100% identical to the reference sheets. "
    "Do not alter creature proportions or design details. "
)

IMAGE_DESCRIPTIONS = (
    "Image 0 = SHAPE-SHIFTER OVERVIEW: one magical creature with 7 emotional forms: "
    "1-yellow round bouncy (Joy), 2-orange tall stretchy (Amusement), 3-light blue oval velvet (Calm), "
    "4-navy blue drooping gelatin (Sadness), 5-purple trembling oval (Fear), "
    "6-red spiky teardrop (Anger), 7-gold star radiant (Confidence). "
    "Image 1 = JOY CREATURE: bright yellow round ball body, small yellow flame antennae on top, "
    "big round brown eyes, wide happy smile, tiny stubby arms and legs, golden sparkling particles. "
    "Image 2 = AMUSEMENT CREATURE: bright orange tall elongated flexible rubbery body, "
    "small orange antennae on head, big round eyes, huge open grin showing teeth, long rubbery arms and legs. "
    "Image 3 = CALM CREATURE: light sky-blue soft oval matte velvet body, tiny closed peaceful eyes, "
    "gentle smile, small stubby arms, floats gently, faint soft blue glow halo. "
    "Image 4 = SADNESS CREATURE: deep navy blue glossy gelatin ghost-like body, long flowing drape lower body, "
    "sad droopy puppy eyes, reflective wet glossy surface, mist trail beneath. "
    "Image 5 = FEAR CREATURE: small purple translucent round oval body, large wide white eyes with "
    "purple irises, two curly antennae on top, tiny clenched fists, shaking vibrational energy lines around it. "
    "Image 6 = ANGER CREATURE: bright red spiky teardrop-shaped body with pointed bumps all over, "
    "orange fiery core glow inside, heavy furrowed brow, angry squinting eyes, steam rising from top. "
    "Image 7 = CONFIDENCE CREATURE: brilliant metallic gold 5-pointed star shape, arms on hips proudly, "
    "warm brown eyes, wide proud smile, radiant golden star-burst light aura all around. "
    "Image 8 = LE PARENT WOMAN: short wavy brown hair in loose updo, warm round brown eyes, "
    "sage green knitted sweater, gold chain necklace with small green pendant, kind and loving expression. "
)

PRENOM = "Leo"


def load_references():
    loaded = {}
    for name, path in REFS.items():
        if Path(path).exists():
            loaded[name] = Path(path).read_bytes()
            print(f"Reference chargee : {path}")
        else:
            loaded[name] = None
            print(f"Pas de reference : {path}")
    return loaded


def call_with_retry(parts, max_retries=5):
    for attempt in range(max_retries):
        try:
            return client.models.generate_content(
                model="gemini-3-pro-image-preview",
                contents=parts,
                config=types.GenerateContentConfig(
                    response_modalities=["IMAGE", "TEXT"]
                )
            )
        except Exception as e:
            wait = (2 ** attempt) + random.uniform(0, 2)
            print(f"Tentative {attempt + 1}/{max_retries} echouee : {e}")
            if attempt < max_retries - 1:
                print(f"Attente {wait:.1f}s avant retry...")
                time.sleep(wait)
            else:
                raise


def generate_page(page_data, style_master, refs, output_dir="pages_emotions"):
    Path(output_dir).mkdir(exist_ok=True)
    page_num = page_data["page"]
    page_type = page_data["type"]
    prompt = page_data["prompt"].replace("{prenom}", PRENOM)
    output_path = f"{output_dir}/page_{page_num:02d}.png"

    format_instruction = (
        "IMPORTANT: single full square illustration 2362x2362 pixels, no spread, no border, fills entire frame."
        if page_type == "simple"
        else "IMPORTANT: double page spread 4724x2362 pixels, 2:1 ratio, safe center fold, no spine line, fills entire frame."
    )

    full_prompt = style_master + " " + format_instruction + " Scene: " + prompt
    print(f"Page {page_num:02d}...")

    text = (
        CHARACTER_MAPPING
        + LOCK_PHRASES
        + IMAGE_DESCRIPTIONS
        + f"CHILD CHARACTER {PRENOM}: 5 years old, short slightly wavy brown hair, big round brown eyes, "
          f"rosy cheeks, soft blue pajamas, white socks. Same face and outfit every scene. "
        + "Now generate: " + full_prompt
    )

    # Image 0 (grille overview) en tête = poids maximal pour la cohérence
    # puis chaque créature dans l'ordre (1→7), puis parent (8)
    parts = [types.Part(text=text)]
    for key in ["emotion_grid", "happy", "fun", "calm", "sad", "fear", "anger", "confidence", "mom"]:
        if refs.get(key):
            parts.append(types.Part(
                inline_data=types.Blob(data=refs[key], mime_type="image/png")
            ))

    response = call_with_retry(parts)

    for part in response.candidates[0].content.parts:
        if part.inline_data:
            with open(output_path, "wb") as f:
                f.write(part.inline_data.data)
            print(f"OK : {output_path}")
            return output_path

    print(f"ERREUR page {page_num} : aucune image dans la reponse")
    return None


def generate_book(prompts_file="prompts_emotions.json", start_page=1, end_page=None):
    with open(prompts_file, "r", encoding="utf-8") as f:
        data = json.load(f)

    style_master = data["style_master"]
    pages = data["pages"]

    if end_page:
        pages = [p for p in pages if start_page <= p["page"] <= end_page]
    else:
        pages = [p for p in pages if p["page"] >= start_page]

    refs = load_references()

    print(f"Generation : {len(pages)} pages — prenom : {PRENOM}")
    results = []

    for page_data in pages:
        path = generate_page(page_data, style_master, refs)
        results.append({
            "page": page_data["page"],
            "path": path,
            "success": path is not None
        })
        time.sleep(5)

    success = sum(1 for r in results if r["success"])
    print(f"\nTermine : {success}/{len(pages)} pages generees")

    with open("book_emotions_results.json", "w") as f:
        json.dump(results, f, indent=2)

    return results


if __name__ == "__main__":
    import sys
    prompts_file = sys.argv[1] if len(sys.argv) > 1 else "prompts_emotions.json"
    start = int(sys.argv[2]) if len(sys.argv) > 2 else 1
    end = int(sys.argv[3]) if len(sys.argv) > 3 else None
    generate_book(prompts_file, start, end)
