#!/usr/bin/env python3
"""Cross-post 11 poster IG TS Law "Mitos atau Fakta" ke FB + Threads (perintah Bos 21 Sep 2026).

Aturan tetap (references/tslaw-ig-harian.md + konten-video-crosspost.md):
  - tanggal SAMA dengan jadwal IG (22 Sep, 25 Sep, 28 Sep, ... 22 Okt 2026)
  - Threads 09:00 WIB (02:00Z) — di luar 7-slot pipeline harian (yang pakai 17:00)
  - FB 19:30 WIB (12:30Z)
  - Threads caption WAJIB <= 500 char (potong sendiri, jaga hook + CTA + pertanyaan + hashtag)
  - FB caption = sama dengan IG (caption() dari tslaw_mitos_fakta_schedule)
  - replies=[] untuk FB (FB tidak support replies) dan Threads (tidak diperlukan)
  - hashtag huruf kecil, 0 mention
"""
import sys
import re
import time
from datetime import datetime, timezone, timedelta

WS = "/home/mantapman/.hermes/profiles/atun/workspace"
sys.path.insert(0, WS)
from repliz_client import get_client  # noqa: E402
from tslaw_mitos_fakta_schedule import POSTS, caption  # noqa: E402

THREADS = "6a35f8b7c5ff4ce3a322b2ed"
FB = "6a3b41d1c5ff4ce3a32753e8"
BASE = "https://mantapserver.tail3947bb.ts.net/openclaw-img/"
TOPIC = "Mitos atau Fakta Hukum"
WIB = timezone(timedelta(hours=7))

TAIL = "Konsultasi: https://tslaw.id · WA +62 819-0922-2026"
TAGS = "#tslaw #mitosataufakta #literasihukum #konsultasihukum"

THREADS_CAP = {
    1: "Viral di media sosial bukan berarti orangnya bersalah.\n\n"
       "Ramai dibicarakan belum membuktikan apa pun. Seseorang tetap dianggap tidak bersalah sampai ada putusan "
       "pengadilan yang berkekuatan hukum tetap.\n\n"
       "Sarah Oktavia Prasanti, S.H. mengingatkannya di poster seri ini.\n\n"
       "Apa yang paling sering bikin orang cepat menghakimi di kolom komentar?",
    2: "Tidak bayar utang otomatis masuk penjara? Tidak sesederhana itu.\n\n"
       "Ketidakmampuan membayar utang pada dasarnya persoalan perdata. Ranahnya bisa berubah kalau sejak awal memang "
       "ada unsur penipuan.\n\n"
       "Nabila Khalisa Paramita, S.H. menjelaskan bedanya di poster ini.\n\n"
       "Kalau menghadapi utang piutang, Anda pilih somasi atau musyawarah dulu? Tulis di komentar.",
    3: "Perjanjian baru sah kalau dibuat di hadapan notaris? Belum tentu.\n\n"
       "Perjanjian bisa sah asalkan para pihak sepakat, cakap hukum, objeknya jelas, dan sebabnya halal. Notaris "
       "memperkuat pembuktian, bukan satu-satunya syarat sah.\n\n"
       "Dicky Andika Hartanto, S.H. menegaskannya di poster ini.\n\n"
       "Klausul perjanjian apa yang menurut Anda paling sering diabaikan? Tulis di komentar.",
    4: "Debitur telat bayar, kreditur langsung ambil jaminan? Tidak bisa begitu.\n\n"
       "Cidera janji tidak otomatis membuat kreditur memiliki objek jaminan. Penyelesaiannya harus lewat mekanisme "
       "hukum yang berlaku, dan pemilik jaminan tetap punya hak.\n\n"
       "Nabila Khalisa Paramita, S.H. menjelaskannya di poster ini.\n\n"
       "Pernah menemui jaminan yang diambil tanpa prosedur? Boleh dibagi di komentar.",
    5: "Dilaporkan ke polisi berarti sudah pasti bersalah? Itu dua hal berbeda.\n\n"
       "Laporan polisi adalah awal pemeriksaan, bukan vonis. Setiap orang tetap diperlakukan dengan asas praduga "
       "tak bersalah sampai ada putusan berkekuatan hukum tetap.\n\n"
       "Sarah Oktavia Prasanti, S.H. mengingatkannya di poster ini.\n\n"
       "Kenapa masih banyak yang menyamakan laporan dengan pembuktian? Tulis di komentar.",
    6: "Bantuan hukum cuma untuk orang yang mampu bayar pengacara? Tidak juga.\n\n"
       "Masyarakat bisa mencari pendampingan lewat lembaga bantuan hukum terakreditasi, Posbankum, atau layanan "
       "konsultasi hukum pemerintah. Yang penting tahu ke mana harus datang.\n\n"
       "Dicky Andika Hartanto, S.H. menjelaskan jalurnya di poster ini.\n\n"
       "Anda tahu layanan bantuan hukum terdekat di kota Anda? Tulis di komentar.",
    7: "Polisi boleh menyita barang tanpa surat? Pahami dulu prosedurnya.\n\n"
       "Pada umumnya penyitaan harus mengikuti prosedur dan izin yang dipersyaratkan, meski ada pengecualian tertentu "
       "dalam hukum acara pidana.\n\n"
       "Nabila Khalisa Paramita, S.H. merangkumnya di poster ini.\n\n"
       "Kalau petugas meminta barang Anda, apa hal pertama yang Anda tanyakan? Tulis di komentar.",
    8: "Panggilan resmi dari penegak hukum boleh diabaikan? Sebaiknya tidak.\n\n"
       "Saksi yang menerima panggilan resmi diharapkan hadir dan memberi keterangan sesuai yang diketahuinya. Kalau "
       "berhalangan, sampaikan alasannya lewat jalur yang tepat.\n\n"
       "Sarah Oktavia Prasanti, S.H. menegaskannya di poster ini.\n\n"
       "Ada yang pernah menerima panggilan sebagai saksi? Ceritakan di komentar.",
    9: "KTP ditahan sebagai jaminan utang? Sebaiknya jangan.\n\n"
       "KTP adalah dokumen identitas, bukan surat berharga yang bisa dijadikan jaminan. Menyerahkan identitas asli "
       "tanpa memahami dasarnya membuka peluang penyalahgunaan data.\n\n"
       "Dicky Andika Hartanto, S.H. mengingatkannya di poster ini.\n\n"
       "Pernah diminta menyerahkan KTP untuk pinjaman? Bagaimana Anda menyikapinya? Tulis di komentar.",
    10: "Tanda tangan digital tidak sah secara hukum? Perlu dikoreksi.\n\n"
        "Tanda tangan elektronik dapat punya kekuatan hukum bila dibuat sesuai syarat dan ketentuan yang berlaku. "
        "Kuncinya ada di penyelenggara dan dokumentasinya.\n\n"
        "Sarah Oktavia Prasanti, S.H. menguraikannya di poster ini.\n\n"
        "Apa yang paling Anda perhatikan sebelum tanda tangan dokumen digital? Tulis di komentar.",
    11: "Pekerja yang mengundurkan diri otomatis kehilangan semua hak? Tidak selalu.\n\n"
        "Hak setelah mengundurkan diri bergantung pada alasan pengunduran diri, masa kerja, perjanjian kerja, dan "
        "aturan yang berlaku. Tidak otomatis hilang semua.\n\n"
        "Nabila Khalisa Paramita, S.H. menjelaskannya di poster ini.\n\n"
        "Pernah mengundurkan diri tapi masih ada hak yang belum dibayar? Ceritakan di komentar.",
}


def threads_caption(no):
    return f"{THREADS_CAP[no]}\n\n{TAIL}\n\n{TAGS}"


def all_docs(c):
    docs = []
    for p in range(1, 80):
        r = None
        for a in range(8):
            try:
                r = c.get_schedules(page=p, limit=100)
                break
            except Exception as e:
                print("   retry list:", e)
                time.sleep(5 + 3 * a)
        if r is None:
            break
        b = r.get("docs", [])
        if not b:
            break
        docs += b
        if len(b) < 100:
            break
    return docs


def build_index(c, aid):
    """set basename media yang SUDAH terpasang di akun (status bukan error) + peta basename -> (id, scheduleAt)."""
    idx = {}
    for d in all_docs(c):
        if d.get("accountId") != aid:
            continue
        if d.get("status") not in ("pending", "success", "processing", "draft"):
            continue
        for m in (d.get("medias") or []):
            fn = ((m or {}).get("url") or "").split("/")[-1].split("?")[0].lower()
            if fn:
                idx.setdefault(fn, (d.get("_id"), d.get("scheduleAt")))
    return idx


def create(c, aid, cap, at_utc, judul, fname, no):
    url = f"{BASE}{fname}"
    last = None
    for attempt in range(1, 5):
        try:
            res = c.create_schedule(aid, cap, at_utc, title=judul, topic=TOPIC, type_="image",
                                    medias=[{"url": url, "type": "image", "alt": fname}], replies=[])
            return res.get("scheduleId") or res.get("_id") or res.get("id")
        except Exception as e:
            last = e
            print(f"    ⚠️ attempt {attempt} gagal: {e}")
            time.sleep(12)
    print(f"    ❌ create gagal 4x: {last}")
    return None


def at_utc(tanggal, jam, menit, offset_jam):
    """tanggal WIB + jam WIB -> string UTC ISO."""
    dt = datetime.fromisoformat(f"{tanggal}T{jam:02d}:{menit:02d}:00+{offset_jam:02d}:00")
    return dt.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.000Z")


def main():
    go = "--go" in sys.argv
    # validasi caption dulu (selalu, walau dry-run)
    problems = []
    for no, tanggal, judul, isi, tags in POSTS:
        th = threads_caption(no)
        fb = caption(isi, tags)
        for label, cap in (("threads", th), ("fb", fb)):
            if label == "threads" and len(cap) > 500:
                problems.append(f"{no:02d} {label}: {len(cap)} char (>500)")
            if re.search(r"@\w+", cap):
                problems.append(f"{no:02d} {label}: ada mention")
            if [t for t in re.findall(r"#(\w+)", cap) if t != t.lower()]:
                problems.append(f"{no:02d} {label}: hashtag huruf besar")
        if "komentar" not in th.lower():
            problems.append(f"{no:02d} threads: tanpa ajakan komentar")
    for p in problems:
        print("❗", p)
    if problems:
        print("\nBATAL: perbaiki caption dulu.")
        return

    c = get_client()
    if not go:
        for no, tanggal, judul, isi, tags in POSTS:
            th_cap = threads_caption(no)
            fb_cap = caption(isi, tags)
            wib = datetime.fromisoformat(f"{tanggal}T09:00:00+07:00")
            print(f"{no:02d} | {wib.strftime('%d %b %Y')} | threads 09:00 = {len(th_cap)} char | "
                  f"fb 19:30 = {len(fb_cap)} char")
        print("\n(dry-run — tambahkan --go)")
        return

    idx_th = build_index(c, THREADS)
    idx_fb = build_index(c, FB)
    print(f"index: threads={len(idx_th)} media | fb={len(idx_fb)} media")
    rows = []
    for no, tanggal, judul, isi, tags in POSTS:
        fname = f"tslaw_mitos_fakta_{no:02d}.jpg"
        fb_cap = caption(isi, tags)
        th_cap = threads_caption(no)
        t_th = at_utc(tanggal, 9, 0, 7)
        t_fb = at_utc(tanggal, 19, 30, 7)
        wib = datetime.fromisoformat(f"{tanggal}T00:00:00+07:00")
        print(f"\n--- {no:02d} | {wib.strftime('%d %b %Y')} | threads {len(th_cap)} char | fb {len(fb_cap)} char")
        for label, aid, cap, at, idx in (("threads", THREADS, th_cap, t_th, idx_th),
                                         ("fb", FB, fb_cap, t_fb, idx_fb)):
            got = idx.get(fname.lower())
            if got:
                print(f"    = {label}: sudah ada {got[0]} ({got[1]}) — SKIP")
                rows.append((label, no, got[0], got[1]))
                continue
            sid = create(c, aid, cap, at, judul, fname, no)
            if sid:
                rows.append((label, no, sid, at))
                print(f"    ✅ {label}: {sid} @ {at}")
    if not go:
        print("\n(dry-run — tambahkan --go)")
        return

    print("\n=== VERIFIKASI (fetch ulang per ID) ===")
    ok = 0
    for label, no, sid, _ in rows:
        r = c.get_schedule(sid)
        doc = r.get("doc") or r
        cap = doc.get("description") or ""
        med = doc.get("medias") or []
        u = (med[0].get("url") if med else "") or ""
        rep = doc.get("replies") or []
        dt = datetime.fromisoformat(doc["scheduleAt"].replace("Z", "+00:00")).astimezone(WIB)
        tag_upper = [t for t in re.findall(r"#(\w+)", cap) if t != t.lower()]
        men = re.findall(r"@\w+", cap)
        good = (doc.get("status") == "pending" and u.endswith(f"tslaw_mitos_fakta_{no:02d}.jpg")
                and not tag_upper and not men and len(rep) == 0)
        ok += 1 if good else 0
        print(f"{label:8s} {no:02d} | {sid} | {doc.get('status')} | {dt.strftime('%Y-%m-%d %H:%M WIB')} | "
              f"{len(cap)} char | media={u.split('/')[-1]} | replies={len(rep)} | {'OK' if good else 'PERIKSA'}")
    print(f"\n{ok}/{len(rows)} jadwal OK")


if __name__ == "__main__":
    main()
