#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Judul cover + pembuka caption carousel TS Law dibuat lebih variatif & humanis.

Perintah Bos 12 Okt 2026: *"tolong itu judulnya lebih variatif bahasanya, lebih humanis dan meng edukasi"*
(keenam cover v2 masih berpola sama: "Mitos atau Fakta? N anggapan soal ...").

Yang diubah per seri: headline cover (slide 01) + kalimat pembuka/penutup caption + field `title` di Repliz.
Isi slide, jumlah item, link, hashtag, dan array `medias` TIDAK berubah.

  python3 pasang_judul_tslaw.py          # preview: render cover v3 + validasi caption (tidak menyentuh server)
  python3 pasang_judul_tslaw.py --go     # tukar cover di openclaw-img + PUT description & title 18 jadwal
"""
import json
import os
import re
import subprocess
import sys
import time

sys.path.insert(0, "/home/mantapman/.hermes/profiles/atun/workspace")
import pasang_carousel_tslaw_v2 as V2
from repliz_client import get_client, ACC

WS = V2.WS
IMG = V2.IMG
URLBASE = V2.URLBASE
HOST = V2.HOST
INGRESS = V2.INGRESS
AKUN = V2.AKUN

# seri → headline cover baru + pembuka/penutup caption + judul internal
VAR = {
    "mitos10": dict(
        cover="Mitos atau fakta?\nSepuluh anggapan\nhukum yang sering\nbikin salah langkah.",
        pembuka=("Mitos atau Fakta? Ada 10 anggapan hukum yang beredar luas dan sering dipercaya "
                 "begitu saja. ⚖️"),
        penutup=("Kesepuluhnya kami bahas di carousel ini, supaya keputusanmu berdasar aturan yang "
                 "berlaku, bukan asumsi."),
        judul="TS Law — Carousel Sepuluh anggapan hukum yang sering bikin salah langkah",
        th=("Mitos atau fakta? Sepuluh anggapan hukum ini beredar luas dan sering dipercaya, padahal "
            "belum tentu benar. ⚖️\n\n"
            "Chat WhatsApp katanya tidak bisa jadi bukti. Tidak bayar utang katanya langsung masuk "
            "penjara. Semua sengketa katanya wajib lewat pengadilan.\n\n"
            "Kesepuluhnya kami bahas di carousel ini, tiap slide ada bagian mitos dan faktanya.\n\n"
            f"{V2.TH_CTA}\n\n#mitosataufakta #hukumpidana #edukasihukum #tslaw"),
    ),
    "mitosproses": dict(
        cover="Urusan hukum tak\nselalu seperti kata\norang.\nTujuh anggapan yang\nsebaiknya diluruskan.",
        pembuka=("Urusan hukum sering terdengar lebih rumit dari kenyataannya. Ada 7 anggapan soal "
                 "proses hukum yang bikin orang salah langkah. ⚖️"),
        penutup=("Ketujuhnya kami bahas di carousel ini, dari somasi sampai mediasi, supaya kamu tahu "
                 "langkah yang benar menurut aturannya."),
        judul="TS Law — Carousel Tujuh anggapan soal proses hukum yang perlu diluruskan",
        th=("Urusan hukum sering terdengar lebih rumit dari kenyataannya. Tujuh anggapan soal proses "
            "hukum ini yang bikin orang salah langkah. ⚖️\n\n"
            "Somasi katanya sama dengan panggilan pengadilan. Damai katanya cukup disepakati lisan. "
            "Mediasi katanya cuma buang waktu.\n\n"
            "Ketujuhnya kami bahas di carousel ini, tiap slide ada sisi mitos dan faktanya.\n\n"
            f"{V2.TH_CTA}\n\n#mitosataufakta #hukumacara #edukasihukum #tslaw"),
    ),
    "mitoshak": dict(
        cover="Hak dan kewajiban\nsering disalahpahami.\nEnam anggapan yang\nsebaiknya kamu tahu\nsebelum bersepakat.",
        pembuka=("Hak dan kewajiban dalam perjanjian sering disalahpahami. Ada 6 anggapan yang "
                 "sebaiknya kamu tahu sebelum bersepakat. ⚖️"),
        penutup=("Keenamnya kami bahas di carousel ini, biar kamu tahu sampai mana hak dan kewajiban "
                 "masing-masing pihak."),
        judul="TS Law — Carousel Enam anggapan soal hak dan kewajiban sebelum bersepakat",
        th=("Hak dan kewajiban dalam perjanjian sering disalahpahami. Enam anggapan ini sebaiknya kamu "
            "tahu. ⚖️\n\n"
            "Uang muka katanya otomatis hangus kalau pembeli membatalkan. Tanpa kwitansi katanya "
            "pembayaran dianggap tidak pernah ada. Kesepakatan lewat chat katanya tidak berkekuatan "
            "apa pun.\n\n"
            "Keenamnya kami bahas di carousel ini, tiap slide ada sisi mitos dan faktanya.\n\n"
            f"{V2.TH_CTA}\n\n#mitosataufakta #hukumperdata #edukasihukum #tslaw"),
    ),
    "mitoskerja": dict(
        cover="Sebelum tanda tangan\nkontrak kerja,\nlima anggapan ini\nsebaiknya kamu tahu.",
        pembuka=("Sebelum tanda tangan kontrak kerja, ada 5 anggapan soal kerja dan perusahaan yang "
                 "sebaiknya kamu tahu. ⚖️"),
        penutup=("Kelimanya kami bahas di carousel ini, lengkap dengan aturan yang jadi dasarnya, "
                 "bukan cuma kebiasaan di kantor."),
        judul="TS Law — Carousel Lima anggapan soal kerja dan perusahaan sebelum tanda tangan",
        th=("Sebelum tanda tangan kontrak kerja, lima anggapan ini sebaiknya kamu tahu. ⚖️\n\n"
            "Resign katanya tanpa konsekuensi. Gaji katanya boleh ditahan sebagai jaminan. Kontrak kerja "
            "katanya bisa diperpanjang terus tanpa batas.\n\n"
            "Ketiganya diatur, bukan diserahkan ke kebiasaan kantor. Kelimanya kami bahas di carousel "
            "ini, tiap slide ada sisi mitos dan faktanya.\n\n"
            f"{V2.TH_CTA}\n\n#mitosataufakta #ketenagakerjaan #edukasihukum #tslaw"),
    ),
    "mitosbukti": dict(
        cover="Di ruang sidang,\nbukti yang bicara.\nEnam anggapan yang\nmasih sering keliru.",
        pembuka=("Di ruang sidang, bukti yang bicara. Ada 6 anggapan soal bukti dan hak yang masih "
                 "sering keliru. ⚖️"),
        penutup=("Keenamnya kami bahas di carousel ini, dari pembuktian sampai hak yang tetap kamu "
                 "punya saat diperiksa."),
        judul="TS Law — Carousel Enam anggapan soal bukti dan hak di ruang sidang",
        th=("Di ruang sidang, bukti yang bicara. Enam anggapan soal bukti dan hak ini masih sering "
            "keliru. ⚖️\n\n"
            "Tanpa saksi mata katanya perkara tidak jalan. Laporan dicabut katanya perkara berhenti. "
            "Tidak tahu aturannya katanya tidak bisa disalahkan.\n\n"
            "Ketiganya yang paling sering bikin orang memilih diam. Keenamnya kami bahas di carousel "
            "ini, tiap slide ada sisi mitos dan faktanya.\n\n"
            f"{V2.TH_CTA}\n\n#mitosataufakta #hukumacara #edukasihukum #tslaw"),
    ),
    "mitostanah": dict(
        cover="Soal tanah dan rumah,\njangan cuma percaya\nkata orang.\nTujuh anggapan yang\nperlu dicek dulu.",
        pembuka=("Soal tanah dan rumah, jangan cuma percaya kata orang. Ada 7 anggapan soal tanah dan "
                 "properti yang perlu dicek dulu. ⚖️"),
        penutup=("Ketujuhnya kami bahas di carousel ini, biar kamu lebih aman sebelum mengambil "
                 "keputusan soal properti."),
        judul="TS Law — Carousel Tujuh anggapan soal tanah dan rumah yang perlu dicek dulu",
        th=("Soal tanah dan rumah, jangan cuma percaya kata orang. Tujuh anggapan soal tanah dan "
            "properti ini perlu dicek dulu. ⚖️\n\n"
            "Sudah bayar lunas katanya otomatis jadi pemilik. Sertifikat hilang katanya tanahnya ikut "
            "hilang. Telat bayar cicilan sekali katanya rumah langsung disita.\n\n"
            "Ketujuhnya kami bahas di carousel ini, tiap slide ada sisi mitos dan faktanya.\n\n"
            f"{V2.TH_CTA}\n\n#mitosataufakta #hukumproperti #edukasihukum #tslaw"),
    ),
}


KATA_ANGKA = [
    (r"\bKesepuluhnya\b", "10 anggapan itu"),
    (r"\bKetujuhnya\b", "7 anggapan itu"),
    (r"\bKeenamnya\b", "6 anggapan itu"),
    (r"\bKelimanya\b", "5 anggapan itu"),
    (r"\bKetiganya\b", "3 hal itu"),
    (r"\bSepuluh\b", "10"), (r"\bTujuh\b", "7"), (r"\bEnam\b", "6"), (r"\bLima\b", "5"),
    (r"\bsepuluh\b", "10"), (r"\btujuh\b", "7"), (r"\benam\b", "6"), (r"\blima\b", "5"),
]
SISA_KATA_ANGKA = re.compile(
    r"\b(Kesepuluh|Sepuluh|sepuluh|Ketujuh|Tujuh|tujuh|Keenam|Enam|enam|Kelima|Lima|lima"
    r"|Kedelapan|Delapan|delapan)\b")


def angka(teks):
    """Bos 12 Okt 2026: 'tulisan angka saja 10 bukan sepuluh' — jumlah selalu pakai digit."""
    for pola, ganti in KATA_ANGKA:
        teks = re.sub(pola, ganti, teks)
    return teks


for _seri in VAR:
    for _k in ("cover", "pembuka", "penutup", "judul", "th"):
        VAR[_seri][_k] = angka(VAR[_seri][_k])


def caption_ig(seri):
    s = V2.SERI[seri]
    daftar = "\n".join(f"{i}. {t}" for i, t in enumerate(s["items"], 1))
    return (f"{VAR[seri]['pembuka']}\n\nKami rangkum dalam satu carousel biar gampang dibaca:\n\n"
            f"{daftar}\n\n{VAR[seri]['penutup']}{V2.TAIL}\n\n{s['tags']}")


def build_deck_v3(seri, outdir):
    """Deck v3 = deck v2 dengan headline cover diganti (slide lain apa adanya)."""
    src = os.path.join(WS, f"deck_tslaw_{seri}_v2.json")
    deck = json.load(open(src))
    cover = deck[0]
    assert cover["jenis"] == "cover"
    cover["headline"] = VAR[seri]["cover"]
    out = os.path.join(WS, f"deck_tslaw_{seri}_v3.json")
    with open(out, "w", encoding="utf-8") as f:
        json.dump(deck, f, ensure_ascii=False, indent=2)
    # render HANYA cover
    os.makedirs(outdir, exist_ok=True)
    tmp_deck = f"/tmp/_cover_only_{seri}.json"
    json.dump([cover], open(tmp_deck, "w"), ensure_ascii=False, indent=2)
    subprocess.run(["python3", "gen_tslaw_slide.py", "--deck", tmp_deck, "--outdir", outdir],
                   cwd=WS, check=True, capture_output=True)
    return out, f"{outdir}/tslaw_gen_01.png"


def gate(url):
    hasil = {}
    for label, extra in (("lokal", []),
                         *[(ip, ["--resolve", f"{HOST}: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)
        hasil[label] = (p.stdout or "000").strip()
    return hasil


def main():
    go = "--go" in sys.argv
    c = get_client()

    print("=== RENDER COVER v3 ===")
    png = {}
    for seri in VAR:
        _, p = build_deck_v3(seri, f"/tmp/{seri}_v3")
        png[seri] = p
        print(f"  {seri:12} {p}")

    print("\n=== VALIDASI CAPTION v3 ===")
    cap = {}
    for seri in VAR:
        cap[seri] = {"IG": caption_ig(seri), "FB": caption_ig(seri), "Threads": VAR[seri]["th"]}
        print(f"[{seri}] judul: {VAR[seri]['judul']}")
        print(f"    cover: {VAR[seri]['cover'].replace(chr(10), ' / ')}")
        for ch in ("IG", "FB", "Threads"):
            V2.validasi(ch, cap[seri][ch], 500 if ch == "Threads" else 2200,
                        wajib_link=(ch != "Threads"))
        teks = " ".join([VAR[seri]["cover"], VAR[seri]["judul"]] +
                        [cap[seri][ch] for ch in ("IG", "Threads")])
        sisa = SISA_KATA_ANGKA.findall(teks)
        print(f"    {('❌ masih ada kata angka: ' + ', '.join(sorted(set(sisa)))) if sisa else '✅ semua jumlah pakai digit'}")

    if not go:
        print("\n(preview saja — jalankan dengan --go untuk menukar cover + update caption & judul)")
        return

    print("\n=== TUKAR COVER ===")
    from PIL import Image
    for seri in VAR:
        im = Image.open(png[seri]).convert("RGB")
        assert im.size == (1080, 1350), (png[seri], im.size)
        dst = f"{IMG}/tslaw_{seri}_01.jpg"
        im.save(dst, "JPEG", quality=90, optimize=True)
        g = gate(f"{URLBASE}tslaw_{seri}_01.jpg")
        ok = all(v == "200" for v in g.values())
        print(f"  {'✅' if ok else '❌'} {seri:12} cover ditukar · gate {g}")
        if not ok:
            sys.exit(1)

    print("\n=== UPDATE CAPTION & JUDUL (18 jadwal) ===")
    docs = V2.semua_jadwal(c)
    for seri in VAR:
        n = V2.SERI[seri]["n"]
        slide = [f"tslaw_{seri}_{i:02d}.jpg" for i in range(1, n + 3)]
        target = [d for d in docs if d.get("accountId") in AKUN
                  and d.get("status") == "pending"
                  and str(d.get("type", "")).lower() == "album"
                  and (d.get("medias") or [{}])[0].get("url", "").endswith(f"tslaw_{seri}_01.jpg")]
        for d in target:
            ch = AKUN[d["accountId"]]
            sid = d["_id"]
            c.update_schedule(sid, {"title": VAR[seri]["judul"], "description": cap[seri][ch]})
            time.sleep(0.4)
            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 [])]
            ok = (bb.get("status") == "pending" and med == slide
                  and bb.get("description") == cap[seri][ch] and bb.get("title") == VAR[seri]["judul"])
            print(f"  [{'✅' if ok else '❌'}] {seri:12} {ch:7} {sid} | media={len(med)} | "
                  f"caption={len(bb.get('description') or '')} | {bb.get('status')}")


if __name__ == "__main__":
    main()
