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)

REFS = {
    "fifi":    "fifi.png",
    "lila":    "Lila.png",
    "barnabe": "barnabe.png",
    "island":  "plage_colorée.png",
    "lagoon":  "lagoon.png",
}
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:
            response = client.models.generate_content(
                model="gemini-3-pro-image-preview",
                contents=parts,
                config=types.GenerateContentConfig(
                    response_modalities=["IMAGE", "TEXT"]
                )
            )
            return response
        except Exception as e:
            wait = (2 ** attempt) + random.uniform(0, 2)
            print(f"  Erreur tentative {attempt+1}/{max_retries} : {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_equilibre"):
    Path(output_dir).mkdir(exist_ok=True)
    page_num = page_data["page"]
    prompt = page_data["prompt"].replace("{prenom}", PRENOM)
    output_path = f"{output_dir}/page_{page_num:02d}.png"

    format_instruction = (
        "IMPORTANT: single full SQUARE illustration, 1:1 ratio, "
        "exactly 2362x2362 pixels, 300 DPI, no borders, fills entire frame."
    )

    full_prompt = style_master + " " + format_instruction + " Scene: " + prompt

    print(f"Page {page_num:02d}...")

    text = (
        "Use ALL reference images to maintain EXACT visual consistency across every scene. "
        "Ref 1 - FIFI THE FLAMINGO: bright pink fluffy feathers, white wing tips, curved orange-brown beak, big green eyes with lashes, small yellow floral headband, elegant long pink legs. Same design every scene. "
        "Ref 2 - LILA: blonde hair in two pigtails with green ties, big bright green eyes, green raincoat with yellow buttons, grey leggings, yellow rubber boots. Same design every scene. "
        "Ref 3 - BARNABE: brown fluffy bear, bright yellow knitted turtleneck sweater, round chubby body, cream muzzle. Same design every scene. "
        "Ref 4 - L'ILE DE LA VITALITE: vibrant magical tropical island, colorful glowing gemstone fruits on trees, crystal clear turquoise water, white sand, lush palm trees. Use for island scenes. "
        "Ref 5 - LE LAGON DES BULLES: warm magical pool, giant iridescent soap bubbles, rainbow mist, mossy rocks. Use for lagoon scenes. "
        f"CHILD CHARACTER {PRENOM}: short slightly wavy brown hair, big round brown eyes, rosy cheeks, blue denim overalls, yellow t-shirt, white sneakers. Same face and outfit every scene. "
        "FORMAT: SQUARE 1:1, 2362x2362px. NOT a double spread. "
        "Now generate: " + full_prompt
    )

    parts = [types.Part(text=text)]
    for key in ["fifi", "lila", "barnabe", "island", "lagoon"]:
        if refs.get(key):
            parts.append(types.Part(
                inline_data=types.Blob(data=refs[key], mime_type="image/png")
            ))

    try:
        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
    except Exception as e:
        print(f"ERREUR page {page_num} : {e}")
        return None

    print(f"ERREUR page {page_num} : pas d'image generee")
    return None


def generate_book(prompts_file="prompts_equilibre.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 — format 1:1 (2362x2362) — 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"])
    failed = [r["page"] for r in results if not r["success"]]
    print(f"\nTermine : {success}/{len(pages)} pages generees")
    if failed:
        print(f"Pages echouees : {failed}")
        print(f"Relancer : python3 generate_book_equilibre.py {prompts_file} {failed[0]} {failed[-1]}")

    with open("book_equilibre_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_equilibre.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)
