#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Pasang carousel DAS gaya template Bos (hitam/putih/merah) — Threads + Facebook.

DAS belum punya akun IG/LinkedIn di Repliz (hanya Threads `6a39e461c5ff4ce3a3233e09`
dan Facebook `6a3b41e1c5ff4ce3a327543e`), jadi hanya 2 kanal yang bisa dipasang.

Pakai:
  python3 pasang_carousel_das.py media [--src /tmp/das_carousel] [--prefix das_car_]
  python3 pasang_carousel_das.py run --tgl 2026-10-07 --judul "DAS — 6 Tanda Kampas Rem Sudah Menipis"
"""
import os, re, sys, json, argparse, subprocess, urllib.parse, urllib.request, time

sys.path.insert(0, "/home/mantapman/.hermes/profiles/atun/workspace")
from repliz_client import HEADERS, BASE, get_client

THREADS = "6a39e461c5ff4ce3a3233e09"
FB = "6a3b41e1c5ff4ce3a327543e"
IMG = "https://mantapserver.tail3947bb.ts.net/openclaw-img/"
INGRESS = ["103.84.155.153", "103.84.155.217"]

CAP_THREADS = """6 tanda kampas rem sudah menipis — dan yang paling sering diabaikan justru tanda pertama. 🛞

Dari bunyi berdecit, pedal yang makin dalam, sampai serbuk hitam di pelek. Geser slide-nya sampai habis ya.

Tanda mana yang pernah kamu alami? Tulis di komentar 👇

#tipsotomotif #perawatanmobil #bengkelmobil #surabaya"""

CAP_FB = """6 tanda kampas rem sudah menipis, dan yang paling sering diabaikan justru tanda pertama.

Dari bunyi berdecit saat mengerem, pedal yang terasa makin dalam, mobil yang menepi ke satu sisi, setir bergetar, serbuk hitam di pelek, sampai jarak tempuh yang sudah lewat 40.000 kilometer — semuanya ada di slide.

Yang perlu diingat: kampas rem itu komponen yang paling tidak boleh ditunggu. Kalau dibiarkan sampai logamnya ikut menggerus cakram, yang tadinya cukup ganti kampas jadi ganti kampas dan cakram sekaligus.

Kami periksa dulu ketebalan kampas, kondisi cakram, dan minyak rem — baru dibicarakan apa yang perlu dikerjakan.

Tanda mana yang pernah kamu alami di mobilmu? Tulis di komentar 👇

DAS Bengkel Indonesia — bengkel mobil premium di Surabaya
www.dasindonesia.com

#tipsotomotif #perawatanmobil #bengkelmobil #bengkelmobilsurabaya"""

ap = argparse.ArgumentParser()
ap.add_argument("mode", choices=["media", "run"])
ap.add_argument("--src", default="/tmp/das_carousel")
ap.add_argument("--prefix", default="das_car_")
ap.add_argument("--tgl", default="2026-10-07")
ap.add_argument("--judul", default="DAS — 6 Tanda Kampas Rem Sudah Menipis")
ap.add_argument("--topik", default="Perawatan Mobil")
ap.add_argument("--cap-threads-file", default=None, dest="cap_th")
ap.add_argument("--cap-fb-file", default=None, dest="cap_fb")
ap.add_argument("--jumlah", type=int, default=10)
a = ap.parse_args()

if a.cap_th:
    CAP_THREADS = open(a.cap_th).read().strip()
if a.cap_fb:
    CAP_FB = open(a.cap_fb).read().strip()

SLIDES = [f"{a.prefix}{i:02d}.jpg" for i in range(1, a.jumlah + 1)]
URLS = [IMG + f for f in SLIDES]


def all_schedules():
    docs, page = [], 1
    while True:
        q = urllib.parse.urlencode({"page": page, "limit": 100})
        req = urllib.request.Request(f"{BASE}/public/schedule?{q}", headers=HEADERS)
        with urllib.request.urlopen(req, timeout=60) as r:
            d = json.loads(r.read().decode())
        batch = d.get("docs") or []
        docs += batch
        if not batch or page * 100 >= (d.get("totalDocs") or 0):
            break
        page += 1
    return docs


def gate(url):
    out = {}
    for label, extra in (("lokal", []), *[(ip, ["--resolve", f"mantapserver.tail3947bb.ts.net:443:{ip}"]) for ip in INGRESS]):
        p = subprocess.run(["curl", "-4", "-s", "-o", "/dev/null", "-w", "%{http_code}",
                            "--max-time", "25", *extra, url], capture_output=True, text=True)
        out[label] = (p.stdout or "000").strip()
    return out


if a.mode == "media":
    os.makedirs("openclaw-img", exist_ok=True)
    for i in range(1, a.jumlah + 1):
        src = os.path.join(a.src, f"das_car_{i:02d}.jpg")
        dst = os.path.join("openclaw-img", SLIDES[i - 1])
        with open(src, "rb") as f_in, open(dst, "wb") as f_out:
            f_out.write(f_in.read())
    print(f"copy {a.jumlah} file → openclaw-img/{a.prefix}*.jpg")
    gagal = 0
    for u in URLS:
        g = gate(u)
        ok = all(v == "200" for v in g.values())
        gagal += 0 if ok else 1
        print(f"  {'✅' if ok else '❌'} {u.split('/')[-1]} {g}")
    sys.exit(1 if gagal else 0)

# ── run ──
y, m, d = [int(x) for x in a.tgl.split("-")]
saat = f"{y:04d}-{m:02d}-{d:02d}T02:00:00.000Z"     # 09:00 WIB
JOBS = [("Threads", THREADS, saat, CAP_THREADS, 500, [{"text": ""}][:0]),
        ("Facebook", FB, saat, CAP_FB, 2200, [])]

CTA_RE = re.compile(r"komentar|tulis di|menurut kamu|setuju|pendapat", re.I)
MENTION_RE = re.compile(r"@\w+")
CJK = re.compile(r"[\u3000-\u30ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff\uff00-\uffef]")

for nama, acc, saat_, cap, maks, replies in JOBS:
    mm = []
    if len(cap) > maks:
        mm.append(f"panjang={len(cap)}")
    if not CTA_RE.search(cap[-160:] if nama == "Threads" else cap):
        mm.append("tanpa-CTA")
    if MENTION_RE.search(cap):
        mm.append("mention")
    if CJK.search(cap):
        mm.append("CJK")
    tags = re.findall(r"#(\w+)", cap)
    if any(t != t.lower() for t in tags):
        mm.append("hashtag-besar")
    print(f"[{nama}] len={len(cap)} tags={len(tags)} {'✅' if not mm else '❌ ' + ','.join(mm)}")
    if mm:
        sys.exit("⛔ caption bermasalah")

docs = all_schedules()
punya = {THREADS: set(), FB: set()}
for x in docs:
    aid = (x.get("account") or {}).get("_id")
    if aid in punya:
        for m_ in (x.get("medias") or []):
            punya[aid].add((m_.get("url") or "").split("/")[-1])

c = get_client()
for nama, acc, saat_, cap, maks, replies in JOBS:
    if SLIDES[0] in punya[acc]:
        print(f"[{nama}] ⏭️  sudah ada — skip")
        continue
    res = c.create_schedule(acc, cap, saat_, title=a.judul, topic=a.topik,
                           type_="album", medias=[{"url": u} for u in URLS], replies=replies)
    sid = res.get("scheduleId") or res.get("_id") or res.get("id")
    time.sleep(0.5)
    b = c.get_schedule(sid)
    bb = b.get("data", b) if isinstance(b, dict) else b
    med = [m_.get("url", "").split("/")[-1] for m_ in (bb.get("medias") or [])]
    print(f"[{nama}] {sid} | status={bb.get('status')} | {bb.get('scheduleAt')} | media={len(med)} | "
          f"urut={'OK' if med == SLIDES else med}")
