#!/usr/bin/env python3
"""DAILY IMAGE POSTING — cron 2026-09-12T18:00Z (= 13 Sep 2026 01:00 WIB)
Item index 42: uky_thread_12_white_filosofi.png (brand ukyhandoko) → Threads @ukyhandoko.

Tema gambar (hasil vision, slide 6/6 dari seri @ukyhandoko):
Judul: "Satu Filosofi yang Nggak Pernah Gagal"
Isi:  "Help enough people get what they want, and you'll get what you want."
      Bukan trik. Bukan manipulasi. Tapi genuinely bantu orang lain sukses.
      Itu kenapa di StudioSoft fokus utama bukan jualan — tapi bikin klien tumbuh.
      Duitnya datang dengan sendirinya.
Footer: @ukyhandoko • Founder StudioSoft

Aturan: Threads ≤500 char, gaya personal "saya", 3 paragraf, pancingan diskusi
(diskusi_engine, industri=digital_marketing), 0 hashtag, 0 mention internal, replies=[].
"""
import json, os, re, sys, subprocess
from datetime import datetime, timezone, timedelta

sys.path.insert(0, "/home/mantapman/.hermes/profiles/atun/workspace")
from repliz_client import get_client, ACC, IMG_BASE_URL, IMG_DIR
from PIL import Image
from diskusi_engine import ambil_pancingan, PANCINGAN

ROOT = "/home/mantapman/.hermes/profiles/atun/workspace"
ITEM_ID = "uky_thread_12_white_filosofi"
FILENAME = "12_white_filosofi.png"
SRC = os.path.join(ROOT, "uky_threads_images", FILENAME)
SLOT_UTC = "2026-10-03T01:00:00.000Z"   # 3 Okt 2026 08:00 WIB (slot 08:00 WIB bebas pertama)
UKY_T = ACC.UKY_THREADS
TITLE = "Satu Filosofi yang Nggak Pernah Gagal"
TOPIC = "Filosofi bantu orang lain dulu, bukan jualan"
EXPECTED_BASENAME = FILENAME.rsplit(".", 1)[0].lower() + ".jpg"

BODY = (
    "Ada satu filosofi yang saya pegang sampai sekarang: \"Help enough people get "
    "what they want, and you'll get what you want.\" 🤝\n\n"
    "Bukan trik. Bukan manipulasi. Di StudioSoft fokus saya bukan jualan dulu — "
    "tapi bikin klien benar-benar tumbuh. Kepercayaan datang sendiri, rezeki ikut jalan.\n\n"
    "Yang saya pelajari: kalau kita bantu cukup banyak orang menang, kita nggak "
    "mungkin kalah."
)

CTA_RE = re.compile(r"komentar|pendapat|diskusi|setuju|share|pengalaman|menurut", re.I)


def build_caption():
    """Body + pancingan diskusi (tone weighted 60/25/15).

    Pancingan tone 'sanjungan' tidak memuat ajakan komentar → undi beberapa kali,
    pakai pancingan pertama yang memuat CTA; fallback netral/opini terpendek.
    """
    for _ in range(10):
        hook = ambil_pancingan(industri="digital_marketing", tone=None)
        cap = BODY + "\n\n" + hook
        if len(cap) <= 500 and CTA_RE.search(hook):
            return cap
    kandidat = [s for t in ("netral", "opini") for s in PANCINGAN["digital_marketing"][t]
                if CTA_RE.search(s)]
    for s in sorted(kandidat, key=len):
        if len(BODY) + len(s) + 2 <= 500:
            return BODY + "\n\n" + s
    return BODY


def upload():
    """PNG → JPEG di openclaw-img, return URL publik."""
    os.makedirs(IMG_DIR, exist_ok=True)
    img = Image.open(SRC)
    if img.mode in ("RGBA", "LA", "P"):
        img = img.convert("RGB")
    out = os.path.join(IMG_DIR, FILENAME.rsplit(".", 1)[0] + ".jpg")
    img.save(out, format="JPEG", quality=90)
    url = f"{IMG_BASE_URL.rstrip('/')}/openclaw-img/{os.path.basename(out)}"
    return url, out


def check_public(url):
    """Simulasi jalur INTERNET (resolve ke ingress Tailscale) — bukan tailnet-direct."""
    codes = {}
    for ip in ("103.84.155.153", "103.84.155.217"):
        r = subprocess.run(
            ["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", "--max-time", "25",
             "--resolve", f"mantapserver.tail3947bb.ts.net:443:{ip}", url],
            capture_output=True, text=True)
        codes[ip] = r.stdout.strip()
    return codes


def main():
    cap = build_caption()
    print(f"CAPTION ({len(cap)} chars):\n{cap}\n")
    assert len(cap) <= 500, f"caption {len(cap)} char > 500"
    assert not re.search(r"@\w+", cap), "ada mention!"
    assert CTA_RE.search(cap), "tidak ada pancingan diskusi"
    assert "#" not in cap, "ada hashtag (aturan: 0 hashtag untuk seri ini)"

    url, out = upload()
    print("LOCAL JPEG:", out, os.path.getsize(out), "bytes")
    print("PUBLIC URL:", url)
    codes = check_public(url)
    print("INTERNET-PATH CODES:", codes)
    if not any(c == "200" for c in codes.values()):
        print("❌ URL publik tidak 200 — STOP, jangan schedule (aturan media server).")
        return 1

    c = get_client()

    def list_uky():
        r = c.get_schedules(page=1, limit=100)
        pages = (r["totalDocs"] + 99) // 100
        docs = list(r["docs"])
        for p in range(2, pages + 1):
            docs.extend(c.get_schedules(page=p, limit=100)["docs"])
        hits = []
        for d in docs:
            acc = d.get("account") or {}
            if (d.get("accountId") or acc.get("id") or acc.get("_id")) != UKY_T:
                continue
            meds = d.get("medias") or []
            u = (meds[0].get("url") if meds else "") or ""
            # ⚠️ exact basename — substring match pernah salah cocokkan uky_quote_12_white_filosofi.jpg
            if os.path.basename(u.split("?")[0]).lower() == EXPECTED_BASENAME:
                hits.append(d)
        return hits

    # ── IDEMPOTENSI (create response pakai 'scheduleId', bukan '_id') ──
    pre = list_uky()
    if pre:
        sid = pre[0].get("id")
        print(f"⏭️  sudah ada {len(pre)} jadwal utk media ini → SKIP create (id={sid})")
    else:
        res = c.create_schedule(
            UKY_T, cap, SLOT_UTC,
            title=TITLE, topic=TOPIC,
            type_="image",
            medias=[{"url": url, "type": "image", "alt": FILENAME}],
            replies=[],
        )
        sid = res.get("scheduleId") or res.get("_id") or res.get("id")
        print("CREATE RESPONSE:", json.dumps(res)[:400])
    print("SID:", sid)

    # ── VERIFIKASI via re-list (jangan percaya response create) ──
    hits = list_uky()
    print(f"\nVERIFIKASI: {len(hits)} jadwal 12_white_filosofi di Threads uky")
    ok = False
    for d in hits:
        wib = datetime.fromisoformat(d["scheduleAt"].replace("Z", "+00:00")) + timedelta(hours=7)
        print(f"  id={d.get('id')} status={d.get('status')} type={d.get('type')} at={wib.strftime('%Y-%m-%d %H:%M')} WIB")
        print(f"  media={d['medias'][0]['url']}")
        print(f"  desc({len(d.get('description') or '')}) replies={len(d.get('replies') or [])}")
        if d.get("id") == sid and d.get("status") == "pending":
            ok = True
    if not (ok and len(hits) == 1):
        print("⚠️ verifikasi tidak pas (harus 1 pending dgn sid cocok)")
        return 1
    print("\n✅ TERVERIFIKASI: 1 jadwal pending, media + caption terpasang")

    # ── UPDATE STATE + LOG ──
    sp = os.path.join(ROOT, "image_posting_state.json")
    st = json.load(open(sp))
    st["index"] = (st["index"] + 1) % st["total"]
    json.dump(st, open(sp, "w"), indent=2)
    print("STATE →", st)

    lp = os.path.join(ROOT, "image_posting_log.json")
    log = json.load(open(lp))
    log.append({
        "timestamp": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.000Z"),
        "item_id": ITEM_ID, "brand": "ukyhandoko", "source": "uky_threads_images",
        "filename": FILENAME, "topic": TOPIC,
        "slot_note": "08:00 WIB terisi pipeline lain s/d 2 Okt (15 Sep=image 10, 16 Sep=image 11, 18-22 Sep=image 05-09, 30 Sep & 1 Okt slot image lain) → slot bebas 08:00 WIB pertama = 3 Okt",
        "schedule_times": {"threads_uky": SLOT_UTC + " (08:00 WIB 2026-10-03) - image 1"},
        "repliz_ids": {"threads_uky": sid},
        "caption_chars": len(cap), "media_url": url,
        "caption_final": cap,
        "next_index": st["index"],
    })
    json.dump(log, open(lp, "w"), indent=2, ensure_ascii=False)
    print("LOG →", lp, f"({len(log)} entri)")
    return 0


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