#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
uky_swap_square.py — ganti media jadwal Threads @ukyhandoko yang BELUM tayang
(pending) ke desain BARU (square 1080x1080, rata kiri, blok di tengah, tanpa garis)
sesuai perintah Bos 16 Sep 2026.

Aturan:
  • Hanya jadwal status `pending` yang diswap (jadwal error/success tidak bisa/diabaikan).
  • Media baru di-upload dengan NAMA FILE BARU (uky_sq_*.jpg) → jalur fetch Repliz segar.
  • File lama TIDAK dihapus (jadwal lama & file lama tetap utuh).
  • URL diverifikasi 200 di KEDUA ingress funnel sebelum PUT.
  • Default DRY RUN; pakai --apply untuk eksekusi. Idempoten (skip kalau sudah uky_sq_).

Sumber gambar: uky_threads_images/<nama>.png   (sudah dirender ulang oleh gen_uky_center.py)
"""
import os
import re
import sys
import subprocess

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from PIL import Image
from repliz_client import ReplizClient, ACC, IMG_BASE_URL, IMG_DIR

INGRESS = ["103.84.155.153", "103.84.155.217"]
PREFIX = "uky_sq_"


def fetch_all(c):
    docs, page = [], 1
    while True:
        r = c.get_schedules(page=page, limit=100)
        d = r.get("docs") or r.get("data") or []
        docs += d
        if not d or page >= (r.get("totalPages") or 1):
            break
        page += 1
    return docs


def verify(url):
    ok = True
    for ip in INGRESS:
        r = subprocess.run(
            ["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", "--max-time", "30",
             "--resolve", f"mantapserver.tail3947bb.ts.net:443:{ip}", url],
            capture_output=True, text=True)
        code = r.stdout.strip()
        print(f"      {ip}: {code}")
        ok = ok and code == "200"
    return ok


def local_png(media_name):
    """uky_quote_11_white_meaning.jpg -> uky_threads_images/11_white_meaning.png
      05_white_brand-1.png          -> uky_threads_images/05_white_brand.png (buang sufiks duplikat -1)"""
    base = media_name.rsplit(".", 1)[0]
    base = re.sub(r"^uky_quote_", "", base)
    base = re.sub(r"-\d+$", "", base)
    return base, os.path.join("uky_threads_images", base + ".png")


def to_jpeg(png_path, out_name):
    img = Image.open(png_path)
    if img.mode in ("RGBA", "LA", "P"):
        img = img.convert("RGB")
    out = os.path.join(IMG_DIR, out_name)
    img.save(out, "JPEG", quality=90)
    return out


def main():
    apply = "--apply" in sys.argv
    c = ReplizClient()
    docs = fetch_all(c)
    uk = ACC.UKY_THREADS

    targets = []
    for d in docs:
        if (d.get("accountId") or (d.get("account") or {}).get("_id")) != uk:
            continue
        if d.get("status") != "pending":
            continue
        meds = d.get("medias") or []
        if not meds:
            continue
        url = meds[0].get("url") or ""
        name = url.rsplit("/", 1)[-1]
        if PREFIX in name:
            continue
        base, png = local_png(name)
        src = os.path.join(os.path.dirname(os.path.abspath(__file__)), png)
        targets.append((d, base, src, name))

    print(f"Jadwal pending Threads uky dengan gambar: {len(targets)}\n")
    plan = []
    for d, base, src, old in sorted(targets, key=lambda t: t[0].get("scheduleAt", "")):
        exists = os.path.exists(src)
        sq = Image.open(src).size if exists else "FILE-HILANG"
        print(f"  {d.get('scheduleAt')}  {old}  →  {PREFIX}{base}.jpg   src={src} {sq}")
        plan.append((d, base, src, old))

    missing = [p for p in plan if not os.path.exists(p[2])]
    if missing:
        print(f"\n❌ {len(missing)} file sumber tidak ada — STOP")
        for m in missing:
            print("   ", m[2])
        return 1

    # render + upload + verify
    print("\n── upload media baru + verifikasi 200 di kedua ingress ──")
    urls = {}
    for d, base, src, old in plan:
        new_name = f"{PREFIX}{base}.jpg"
        if not os.path.exists(os.path.join(IMG_DIR, new_name)):
            to_jpeg(src, new_name)
        url = f"{IMG_BASE_URL}/openclaw-img/{new_name}"
        print(f"  {new_name}: {os.path.getsize(os.path.join(IMG_DIR, new_name))} bytes")
        if not verify(url):
            print(f"❌ {new_name} tidak 200 di semua ingress — STOP")
            return 1
        urls[d["_id"]] = (url, d)

    if not apply:
        print(f"\n🧪 DRY RUN selesai — {len(urls)} media siap. Tambahkan --apply untuk PUT.")
        return 0

    print(f"\n── PUT media ke {len(urls)} jadwal ──")
    for sid, (url, d) in urls.items():
        payload = {
            "accountId": d.get("accountId") or uk,
            "title": d.get("title") or "",
            "description": d.get("description") or "",
            "topic": d.get("topic") or "",
            "type": d.get("type") or "image",
            "medias": [{"type": "image", "url": url, "alt": url.rsplit("/", 1)[-1]}],
            "scheduleAt": d.get("scheduleAt"),
            "replies": d.get("replies") or [],
        }
        r = c._request("PUT", f"/public/schedule/{sid}", payload)
        print(f"  {sid} → {str(r)[:120]}")

    # verifikasi ULANG dari API (fetch baru)
    print("\n── verifikasi ulang dari API ──")
    docs2 = {x.get("_id"): x for x in fetch_all(c)}
    ok = 0
    for sid, (url, _) in urls.items():
        x = docs2.get(sid) or {}
        got = [m.get("url") for m in (x.get("medias") or [])]
        good = got and got[0] == url and x.get("status") == "pending"
        ok += bool(good)
        print(f"  {'✅' if good else '⚠️'} {sid} status={x.get('status')} at={x.get('scheduleAt')} media={got}")
    print(f"\n{ok}/{len(urls)} jadwal terverifikasi memakai desain square baru.")
    return 0 if ok == len(urls) else 1


if __name__ == "__main__":
    sys.exit(main())
