#!/usr/bin/env python3
"""threads_reply_kerja.py — siapkan daftar kerja "reply sendiri 2x" untuk postingan Threads.

Perintah Bos 16 Okt 2026: pola seperti postingan TSC (@theskincode_clinic) — setiap postingan
dibalas sendiri oleh akunnya 2 kali. Script ini memilih postingan Threads yang BELUM punya 2 reply
berisi, lalu menulis berkas kerja (teks postingan + reply yang sudah ada) supaya balasannya bisa
ditulis, untuk dipasang lewat `threads_pasang_reply.py`.

Pakai:
  python3 threads_reply_kerja.py 2026-10-17 2026-10-18 --maks 30 [--fresh]
  (hasil: /tmp/threads_reply_kerja.json + ringkasan 1 baris per jadwal ke stdout)
"""
import argparse
import datetime
import json
import os
import sys
import time

WS = "/home/mantapman/.hermes/profiles/atun/workspace"
DUMP = "/tmp/threads_reply_dump.json"
KELUAR = "/tmp/threads_reply_kerja.json"
sys.path.insert(0, WS)
from repliz_client import get_client  # noqa: E402

WIB = datetime.timezone(datetime.timedelta(hours=7))
# hanya klien AKTIF (klien berhenti: LEIT, Soto Pak Otto, Nucleasoft, dll — jangan disentuh)
AKUN = {
    "6a334e89c5ff4ce3a3225a48": "uky",
    "6a335b9ec5ff4ce3a3225c2a": "ss",
    "6a35f8b7c5ff4ce3a322b2ed": "tslaw",
    "6a39e461c5ff4ce3a3233e09": "das",
    "6a4bbc5920e4f4f195e52960": "tsc",
    "6a44ed1920e4f4f195d8ecf7": "everybe",
}
MENIT_AMAN = 30   # jangan sentuh postingan yang tayang < 30 menit dari sekarang


def semua_jadwal(fresh=False):
    if not fresh and os.path.exists(DUMP) and time.time() - os.path.getmtime(DUMP) < 1800:
        return json.load(open(DUMP))
    c = get_client()
    docs, page = [], 1
    while page <= 120:
        r = None
        for a in range(5):
            try:
                r = c.get_schedules(page=page, limit=100)
                break
            except Exception:
                time.sleep(4 + 2 * a)
        if r is None:
            raise SystemExit("gagal baca jadwal Repliz")
        b = r.get("docs") or []
        docs += b
        if len(b) < 100:
            break
        page += 1
    json.dump(docs, open(DUMP, "w"))
    return docs


def induk_dari(d):
    """Kalau jadwal ini SENDIRI adalah reply: pulihkan id INDUK dari dict char-demi-char.

    Pipeline lama (mis. carousel StudioSoft 09:00) membuat reply sebagai JADWAL TERPISAH
    (09:01 & 09:02) dan menaruh id induk di field `replies` dalam bentuk dict karakter
    ({"0":"6","1":"a",...} = ObjectId 24 hex). Jadi jadwal seperti ini tidak perlu dibalas
    lagi — dan induknya sudah otomatis punya 1 reply dari tiap anak.
    """
    for r in d.get("replies") or []:
        if isinstance(r, dict):
            kunci = [k for k in r.keys() if k.isdigit()]
            if 8 <= len(kunci) < 40:
                return "".join(str(r[k]) for k in sorted(kunci, key=int))
    return None


def isi_ada(d):
    return [r for r in (d.get("replies") or [])
            if isinstance(r, dict) and ((r.get("description") or r.get("text") or "").strip())]


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("mulai")
    ap.add_argument("akhir")
    ap.add_argument("--maks", type=int, default=30)
    ap.add_argument("--sejak", default=None,
                    help="hanya postingan yang DIBUAT (createdAt) sejak tanggal ini (YYYY-MM-DD, UTC). "
                         "Dipakai untuk berhenti menambal jadwal lama: default = semua.")
    ap.add_argument("--fresh", action="store_true")
    a = ap.parse_args()

    awal = datetime.date.fromisoformat(a.mulai)
    akhir = datetime.date.fromisoformat(a.akhir)
    batas_aman = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=MENIT_AMAN)

    docs = semua_jadwal(a.fresh)

    # 1) hitung anak: tiap jadwal-reply menambah 1 reply ke induknya
    anak_per_induk = {}
    id_anak = set()
    for d in docs:
        p = induk_dari(d)
        if p:
            id_anak.add(d.get("_id"))
            anak_per_induk[p] = anak_per_induk.get(p, 0) + 1

    tugas = []
    dilewati_anak = 0
    for d in docs:
        akun = AKUN.get(d.get("accountId"))
        if not akun or d.get("status") != "pending":
            continue
        if d.get("_id") in id_anak:
            dilewati_anak += 1
            continue
        iso = d.get("scheduleAt") or ""
        if iso <= batas_aman.strftime("%Y-%m-%dT%H:%M:%S"):
            continue
        if a.sejak and (d.get("createdAt") or "")[:10] < a.sejak:
            continue
        t = datetime.datetime.fromisoformat(iso.replace("Z", "+00:00")).astimezone(WIB)
        if not (awal <= t.date() <= akhir):
            continue
        ada = isi_ada(d)
        jumlah = len(ada) + anak_per_induk.get(d.get("_id"), 0)
        if jumlah >= 2:
            continue
        tugas.append({
            "id": d.get("_id"), "akun": akun, "tanggal": str(t.date()),
            "jam_wib": t.strftime("%H:%M"), "type": d.get("type"),
            "title": d.get("title") or "", "topic": d.get("topic") or "",
            "jumlah_media": len(d.get("medias") or []),
            "jumlah_reply_ada": len(ada),
            "reply_ada": [(x.get("description") or x.get("text") or "") for x in ada],
            "teks_post": d.get("description") or "",
            "butuh_tambahan": 2 - jumlah,
        })

    tugas.sort(key=lambda x: (x["tanggal"], x["jam_wib"]))
    total = len(tugas)
    tugas = tugas[:a.maks]
    json.dump(tugas, open(KELUAR, "w"), indent=1, ensure_ascii=False)

    print(f"# {total} jadwal butuh reply di {awal}..{akhir}; ditulis {len(tugas)} ke {KELUAR}")
    print(f"# (dilewati {dilewati_anak} jadwal yang statusnya reply/anak dari postingan lain)")
    for x in tugas:
        print(f"{x['tanggal']} {x['jam_wib']} | {x['akun']:8s} | {x['id']} | {x['type']} "
              f"| reply_ada={x['jumlah_reply_ada']} butuh+{x['butuh_tambahan']} | {x['title'][:30]}")
        print(f"   TEKS: {x['teks_post'][:220].replace(chr(10), ' / ')}")
        for i, r in enumerate(x["reply_ada"], 1):
            print(f"   ADA-{i}: {r[:160]}")


if __name__ == "__main__":
    main()
