import json, urllib.request, time, sys

API_KEY = "vio_sk_vA8llIYm51J3oyXtfevrM92yUBJ8-3IS1sIn6xydF8o"
BASE = "https://api.viostudio.id/v1"

urls = {}

def generate(slide_name, prompt):
    payload = {"prompt": prompt, "model": "gpt-image-2.0", "aspect_ratio": "3:4", "count": 1}
    print(f"\n🎨 {slide_name}...")
    sys.stdout.flush()
    for attempt in range(3):
        try:
            req = urllib.request.Request(f'{BASE}/images/generate',
                data=json.dumps(payload).encode(),
                headers={'Content-Type':'application/json','Authorization':f'Bearer {API_KEY}','User-Agent':'Mozilla/5.0'},
                method='POST')
            with urllib.request.urlopen(req, timeout=60) as resp:
                gen_id = json.loads(resp.read()).get('generation_ids',[0])[0]
                print(f"✅ Queued ID: {gen_id}")
                sys.stdout.flush()
                for i in range(30):
                    time.sleep(8)
                    try:
                        sr = urllib.request.Request(f'{BASE}/generations/{gen_id}',
                            headers={'Authorization':f'Bearer {API_KEY}','User-Agent':'Mozilla/5.0'})
                        with urllib.request.urlopen(sr, timeout=20) as s:
                            st = json.loads(s.read())
                            stat = st.get('status')
                            print(f"  ({i+1}/30) {stat}")
                            sys.stdout.flush()
                            if stat == 'completed':
                                print(f"✅ {slide_name} DONE!\n📸 {st.get('asset_url')}")
                                return st.get('asset_url')
                            elif stat == 'failed':
                                print(f"❌ FAILED: {st.get('error_message')}")
                                return None
                    except:
                        time.sleep(5)
        except Exception as e:
            print(f"  ⚠️ Retry {attempt+1}/3... ({e})")
            time.sleep(5)

urls['slide5'] = generate("Slide 5 - Contoh Boss", """Instagram carousel slide 3:4 aspect ratio ukuran feed Instagram. Flat vector illustration style komik.

Background gradasi soft cream ke deep teal blue.

Ilustrasi timeline singkat:

MASA KECIL: Anak kecil di depan guru galak yang nunjuk-nunjuk sambil bentak KAMU GAK BAKAL BISA. Anak menunduk malu. Label TRAUMA ASLI figur otoritas yang merendahkan.

KANTOR 1: Boss pertama galak nunjuk-nunjuk. Adegan mirip. Karakter dewasa kerja ekstra keras berharap dipuji. Boss tetap galak. REMAKE 1.

KANTOR 2: Boss kedua sama. Dinamika sama. Karakter kerja lembur tiap hari berharap kali ini dia ngelihat kerja kerasku. REMAKE 2.

Di samping ada sticky note kecil: Kenapa gue selalu dapet boss yang kayak gini? dengan panah ke trauma asli.

Teks HEADLINE di atas:
CONTOH 2: BOSS YANG GAK ADIL

Teks penutup bawah:
Kamu gak sial. Kamu punya radar yang DIPROGRAM untuk mencari figur otoritas yang merendahkan karena misi masa kecilmu belum selesai.

Bawah sadarmu: Kalo gue bisa bikin BOSS ini ngakuin gue berarti GURU dulu SALAH.

Desain komik real talk.""")

urls['slide6'] = generate("Slide 6 - Tanda & Cara Keluar", """Instagram carousel slide 3:4 aspect ratio ukuran feed Instagram. Flat vector illustration style infografis split.

Background gradasi soft cream ke deep teal blue. Aksen orange.

Ilustrasi split dua kolom:

Kolom kiri KENALI nuansa agak gelap: Karakter berdiri di depan cermin. Di cermin terlihat semua remake dari hidupnya 3 pasangan berbeda 3 boss berbeda 3 teman berbeda tapi ekspresi dan posenya SAMA. Ada label POLA. Di bawah cermin ada checklist:
Aku selalu tertarik sama tipe yang sama walau tau itu buruk.
Setelah putus pindah kerja aku nemu yang mirip lagi.
Aku punya perasaan ini familiar tapi gak tau kenapa.
Aku terus berharap KALI INI BERBEDA.

Kolom kanan KELUAR nuansa hangat terang: Karakter duduk jurnal di tangan lampu menyala. Tiga step:
1. TRACE BACK Pola ini mulai dari mana? Siapa pemeran aslinya? Ayah Ibu Guru Mantan pertama.
2. BERESIN Akui lukanya. Aku sakit waktu itu. Jangan skip. Jangan minimalin. Feel it.
3. STOP THE CYCLE Pas radar mulai bunyi INI DIA jeda. Sadari ini remake. Bukan asli. Aku gak harus ikut.

Teks HEADLINE di atas:
TANDA-TANDA DAN CARA KELUAR

Desain split infografis rapi.""")

urls['slide7'] = generate("Slide 7 - Closing", """Instagram carousel closing slide 3:4 aspect ratio ukuran feed Instagram. Flat vector illustration style hangat.

Background gradasi soft cream ke deep teal blue hangat terang. Aksen orange halus.

Ilustrasi: karakter duduk di tepi jalan. Di belakangnya loop infinity yang tadinya jadi jalannya sekarang udah PUTUS ada celah di satu titik. Karakter memegang gunting di satu tangan dia yang mutusin loopnya.

Di depannya jalan lurus ke depan bukan melingkar. Ada pemandangan baru pohon cahaya sesuatu yang BELUM PERNAH dia jalani.

Di samping karakter inner child duduk tidak lagi memegang remote REPLAY. Remote-nya udah disimpan. Inner child pegang bunga kecil dan lihat ke depan ke arah jalan baru.

Teks HEADLINE besar font bold di bagian atas:
LOOP ITU BISA DIPUTUSIN.

Teks body medium di tengah:
Bukan dengan nyelesaiin misi lama. Tapi dengan SADAR bahwa misi itu gak perlu diselesaiin.

Teks hook penutup:
Kamu gak perlu bikin orang lain berubah. Cukup kamu yang berubah.

Teks closing:
Putusin loopnya. Jalan baru menunggu.

Teks CTA pojok bawah:
Follow balimentari

Teks kecil di atas CTA:
Simpen. Ini deep.

Desain closing hangat damai memotivasi.""")

print("\n✅ BATCH 2 COMPLETE!")
print("\nURLs:", json.dumps(urls, indent=2))
