#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""pasang_car_generik.py — pasang carousel 10 slide ke FEED IG StudioSoft + story mirror.

Pakai:
  python3 pasang_car_generik.py --folder ss_ig_car10_manufaktur --prefix ss_car10_manufaktur \
      --caption /tmp/cap_manufaktur.txt --hari 1 --go

  --hari 0 = slot 08:30 WIB HARI INI, 1 = besok, dst.
Gate: JPEG q85 → openclaw-img/, HTTP 200 di KEDUA ingress (abort kalau bukan 200),
idempoten (akun + slot sudah terisi → SKIP), verifikasi baca balik album & story.
"""
import argparse
import os
import subprocess
import sys
from datetime import datetime, timedelta, timezone

from PIL import Image
from repliz_client import get_client, ReplizError, IMG_BASE_URL

WIB = timezone(timedelta(hours=7))
WS = "/home/mantapman/.hermes/profiles/atun/workspace"
IMG_DIR = os.path.join(WS, "openclaw-img")
ACC_IG_SS = "6a38ac33c5ff4ce3a3231232"
INGRESS = ["103.84.155.153", "103.84.155.217"]
HOST = "mantapserver.tail3947bb.ts.net"


def cek_ingress(nama):
    url = f"https://{HOST}/openclaw-img/{nama}"
    for ip in INGRESS:
        code = subprocess.run(["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", "--max-time", "30",
                               "--resolve", f"{HOST}:443:{ip}", url],
                              capture_output=True, text=True).stdout.strip()
        if code != "200":
            return False, f"{nama} @{ip} → {code}"
    return True, ""


CW, CH = 1080, 1920


def kanvas_story(nama):
    """Slide 4:5 → media story 1080x1920 sewarna latar slide (WAJIB).

    Pitfall 2 Okt 2026 (screenshot Bos: teks story mirror carousel properti kepotong kiri-kanan):
    jangan pernah pasang slide 4:5 mentah ke type=story — IG memaksa media memenuhi kanvas 9:16,
    jadi ~228 px terpotong per sisi. Slide ditaruh utuh di tengah kanvas sewarna piksel sudut (8,8).
    """
    src = os.path.join(IMG_DIR, nama)
    if not os.path.exists(src):
        return None
    baru = f"ss_story_canvas_{nama}"
    dst = os.path.join(IMG_DIR, baru)
    if not (os.path.exists(dst) and os.path.getsize(dst) > 1000):
        im = Image.open(src).convert("RGB")
        if im.size == (CW, CH):
            return nama
        bg = im.getpixel((8, 8))
        if min(bg) >= 235:
            bg = (255, 255, 255)
        skala = min(CW / im.width, CH / im.height)
        kecil = im.resize((round(im.width * skala), round(im.height * skala)), Image.LANCZOS)
        knv = Image.new("RGB", (CW, CH), bg)
        knv.paste(kecil, ((CW - kecil.width) // 2, (CH - kecil.height) // 2))
        knv.save(dst, quality=90)
        print(f"   kanvas story: {nama} → {baru} (bg {bg})")
    return baru



def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--folder", required=True)
    ap.add_argument("--prefix", required=True)
    ap.add_argument("--caption", required=True)
    ap.add_argument("--judul", default="")
    ap.add_argument("--topik", default="Seri Properti & Manufaktur: SEO & Digital Marketing")
    ap.add_argument("--hari", type=int, default=0)
    ap.add_argument("--go", action="store_true")
    a = ap.parse_args()

    caption = open(a.caption, encoding="utf-8").read().strip()
    if len(caption) > 1500:
        print(f"⛔ caption {len(caption)} char > 1500 — perpendek dulu"); sys.exit(1)
    cjk = [ch for ch in caption if "\u3000" <= ch <= "\u9fff" or "\uac00" <= ch <= "\ud7af"]
    if cjk:
        print(f"⛔ caption memuat karakter CJK: {cjk[:5]}"); sys.exit(1)

    src_dir = os.path.join(WS, a.folder)
    print("=== 1. JPEG q85 ===")
    for i in range(1, 11):
        src = os.path.join(src_dir, f"{a.prefix}_{i:02d}.png")
        dst = os.path.join(IMG_DIR, f"{a.prefix}_{i:02d}.jpg")
        im = Image.open(src).convert("RGB")
        assert im.size == (1080, 1350), f"{src} {im.size}"
        im.save(dst, "JPEG", quality=85, optimize=True)
        print(f"   {a.prefix}_{i:02d}.jpg {os.path.getsize(dst)//1024} KB")

    print("=== 2. gate 200 dua ingress ===")
    for i in range(1, 11):
        ok, pesan = cek_ingress(f"{a.prefix}_{i:02d}.jpg")
        if not ok:
            print("   ⛔ ABORT:", pesan); sys.exit(1)
    print("   10/10 media 200 di KEDUA ingress ✅")

    sekarang = datetime.now(WIB) + timedelta(days=a.hari)
    tayang = sekarang.replace(hour=8, minute=30, second=0, microsecond=0)
    story = sekarang.replace(hour=8, minute=40, second=0, microsecond=0)
    at_utc = tayang.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.000Z")
    story_utc = story.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.000Z")

    c = get_client()
    print("=== 3. cek slot (idempoten) ===")
    terpakai = []
    page = 1
    while True:
        r = c.get_schedules(page=page, limit=100)
        docs = r.get("docs") or r.get("data") or []
        if not docs:
            break
        for d in docs:
            if d.get("accountId") == ACC_IG_SS and (d.get("scheduleAt") or "").startswith(at_utc[:13]):
                terpakai.append((d.get("_id"), d.get("type"), d.get("status")))
        if len(docs) < 100:
            break
        page += 1
    print(f"   slot {tayang.strftime('%d %b %H:%M')} WIB:", terpakai if terpakai else "kosong ✅")
    if terpakai:
        print("   SKIP: slot terisi."); return

    album = {
        "accountId": ACC_IG_SS, "title": a.judul or f"Carousel IG SS — {a.prefix}",
        "topic": a.topik, "type": "album", "description": caption,
        "medias": [{"url": f"{IMG_BASE_URL}/openclaw-img/{a.prefix}_{i:02d}.jpg",
                    "type": "image", "alt": f"Slide {i}"} for i in range(1, 11)],
        "scheduleAt": at_utc, "replies": [], "additionalInfo": {"isShareToFeed": True},
    }
    stori = {
        "accountId": ACC_IG_SS, "title": f"Story IG SS mirror {a.prefix}",
        "topic": a.topik, "type": "story", "description": "",
        "medias": [{"url": f"{IMG_BASE_URL}/openclaw-img/{kanvas_story(f'{a.prefix}_01.jpg')}",
                    "type": "image", "alt": "Slide 1"}],
        "scheduleAt": story_utc, "replies": [],
    }
    if not a.go:
        print(f"\n(dry run — caption {len(caption)} char | pakai --go)")
        print(caption)
        return

    nama_story = stori["medias"][0]["url"].split("/")[-1]
    ok, pesan = cek_ingress(nama_story)
    if not ok:
        print("   ⛔ ABORT (media story):", pesan); sys.exit(1)
    print(f"   media story {nama_story} 200 di KEDUA ingress ✅")

    print("=== 4. create album + story ===")
    r1 = c.post("/public/schedule", album)
    sid1 = r1.get("scheduleId") or r1.get("_id") or r1.get("id")
    r2 = c.post("/public/schedule", stori)
    sid2 = r2.get("scheduleId") or r2.get("_id") or r2.get("id")
    print(f"   album={sid1} @ {tayang.strftime('%d %b %H:%M')} WIB | story={sid2} @ {story.strftime('%d %b %H:%M')} WIB")
    print("=== 5. verifikasi baca balik ===")
    for label, sid_ in (("album", sid1), ("story", sid2)):
        d = c.get(f"/public/schedule/{sid_}")
        d = d.get("data") or d
        print(f"   {label}: status={d.get('status')} type={d.get('type')} at={d.get('scheduleAt')} "
              f"media={len(d.get('medias') or [])} akun={(d.get('account') or {}).get('name')} "
              f"caption={len(d.get('description') or '')} char")


if __name__ == "__main__":
    try:
        main()
    except ReplizError as e:
        print("ReplizError:", e); sys.exit(1)
