#!/usr/bin/env python3
"""
Jadwal FULL AGUSTUS — 6 s.d. 31 Agustus 2026 (26 hari).
Threads + FB + LinkedIn sesuai aturan platform.
ANTI-REDUNDANSI: tiap artikel dipakai EXACTLY SEKALI (tracked via used_links).
Gaya caption divariasikan (5 template per platform) biar gak monoton.
"""
import sys, json, random, re, urllib.request
from datetime import datetime, timedelta
sys.path.insert(0, "/home/mantapman/.hermes/profiles/atun/workspace")
from repliz_client import get_client, ACC, HEADERS, BASE

client = get_client()

A = {
    "ss_th": ACC.STUDIOSOFT_THREADS, "ss_fb": ACC.STUDIOSOFT_FB, "ss_li": ACC.STUDIOSOFT_LINKEDIN,
    "das_th": ACC.DAS_THREADS, "das_fb": ACC.DAS_FB,
    "leit_th": ACC.LEIT_THREADS, "leit_fb": ACC.LEIT_FB, "leit_li": ACC.LEIT_LINKEDIN,
    "tslaw_th": ACC.TSLAW_THREADS, "tslaw_fb": ACC.TSLAW_FB, "tslaw_li": ACC.TSLAW_LINKEDIN,
    "dmark_fb": ACC.DMARK_FB, "dmark_li": ACC.DMARK_LINKEDIN,
}

# ── STOK ARTIKEL (dari fetch) ──
with open("stok_artikel_augustus.json") as f:
    STOK = json.load(f)

used_links = set()

# ── ANTI-REDUNDANSI: exclude SEMUA artikel yang sudah dijadwalkan di Repliz ──
def load_used_from_repliz():
    """Ambil semua schedule yang ada & punya link artikel → tandai sebagai used."""
    links = set()
    for page in range(1, 12):
        try:
            req = urllib.request.Request(f"{BASE}/public/schedule?page={page}&limit=100", headers=HEADERS, method="GET")
            with urllib.request.urlopen(req, timeout=25) as r:
                d = json.loads(r.read())
            docs = d.get("docs", [])
            if not docs:
                break
            for doc in docs:
                desc = doc.get("description") or ""
                found = re.findall(r"https?://[^\s\n]+", desc)
                for u in found:
                    if any(x in u for x in ["dasindonesia.com", "studiosoft.id", "leitsurabaya.com", "tslaw.id", "dmark.id"]):
                        links.add(u.replace("www.", "").rstrip("/"))
        except Exception as e:
            print(f"  (warn) fetch schedule page {page}: {str(e)[:50]}")
            break
    print(f"🔍 {len(links)} link artikel sudah pernah dijadwalkan di Repliz → di-exclude")
    return links

used_links |= load_used_from_repliz()

def take_article(brand):
    """Ambil 1 artikel fresh yang belum pernah dipakai."""
    pool = STOK.get(brand, [])
    for art in pool:
        key = art["link"].replace("www.", "").rstrip("/")
        if key not in used_links:
            used_links.add(key)
            return art
    return None

def clean_title(title):
    if isinstance(title, dict):
        title = title.get("rendered") or title.get("title") or ""
    t = str(title).replace("&#038;", "&").replace("&amp;", "&")
    t = t.replace("| LEIT", "").replace("| DMark", "").strip()
    return t

# ── TEMPLATE CAPTION per platform (variasi) ──
def cap_threads(brand, art, variant):
    t = clean_title(art["title"])
    link = art["link"]
    h = {
        "DAS": "#DASBengkelIndonesia #PerawatanMobil",
        "StudioSoft": "#StudioSoft #DigitalMarketing #SEO",
        "LEIT": "#LEIT #BelajarInggris #Leadership",
        "TSLaw": "#TSLaw #LegalitasUsaha",
        "DMark": "#DMark #Branding",
    }[brand]
    v = variant % 5
    if v == 0:
        return f"Jarang yang bahas ini, padahal penting banget: {t}.\n\nBanyak yang baru sadar setelah kejadian — padahal kalau tahu lebih awal, bisa dihindari. Simak penjelasannya biar gak ketinggalan info.\n\nLengkap di sini 👇\n{link}\n\n{h}"
    if v == 1:
        return f"Pernah kepikiran gak soal ini? {t}.\n\nSering dianggap sepele, padahal dampaknya besar buat jangka panjang. Yuk pahami dulu sebelum ambil keputusan.\n\nBaca selengkapnya 👇\n{link}\n\n{h}"
    if v == 2:
        return f"{t} — ini yang perlu kamu tahu.\n\nGak perlu jadi ahli buat paham. Penjelasan lengkapnya disusun simpel biar langsung ngerti dan bisa dipraktikkan.\n\nCek di sini 👇\n{link}\n\n{h}"
    if v == 3:
        return f"Banyak yang tanya soal {t.lower()}. Daripada nebak-nebak, mending baca penjelasan lengkapnya.\n\nSemua dibahas tuntas dari awal sampai praktiknya. Langsung aja ke sumbernya 👇\n{link}\n\n{h}"
    return f"Satu hal yang sering dilupakan: {t.lower()}.\n\nPadahal ini kunci yang nentuin hasil jangka panjang. Jangan sampai kelewat — baca pembahasannya di sini 👇\n{link}\n\n{h}"

def cap_fb(brand, art, variant):
    t = clean_title(art["title"])
    link = art["link"]
    h = {
        "DAS": "#DASBengkelIndonesia #BengkelSpesialis #PerawatanMobil #EngineOverhaul",
        "StudioSoft": "#DigitalMarketing #SEO #Website #BisnisOnline #StudioSoft",
        "LEIT": "#KursusInggris #BelajarBahasa #Leadership #Surabaya #LEIT",
        "TSLaw": "#LegalitasUsaha #HukumBisnis #UMKM #TSLaw",
        "DMark": "#Branding #DigitalMarketing #Kreatif #DMark",
    }[brand]
    v = variant % 5
    if v == 0:
        return f"{t}\n\nIni topik yang sering ditanyakan, tapi jarang dijelaskan tuntas. Banyak yang sudah mencoba sendiri, namun hasilnya kurang maksimal karena kurang paham langkah yang benar.\n\nKami merangkum pembahasan lengkapnya — dari konsep dasar sampai langkah praktis yang bisa langsung diterapkan. Cocok untuk Anda yang ingin mengambil keputusan lebih bijak.\n\nSelengkapnya di artikel berikut 👇\n{link}\n\n{h}"
    if v == 1:
        return f"Tahukah Anda? {t}.\n\nTopik ini penting karena menyangkut keputusan yang berdampak jangka panjang. Sayangnya, masih banyak informasi keliru yang beredar dan bikin bingung.\n\nKami coba jelaskan dengan bahasa yang mudah dipahami, disertai contoh dan langkah yang jelas. Semoga membantu Anda mengambil keputusan yang tepat.\n\nBaca artikel lengkapnya di sini 👇\n{link}\n\n{h}"
    if v == 2:
        return f"Jangan sampai salah paham soal: {t}.\n\nBanyak yang bertanya-tanya tentang hal ini setiap hari. Artikel ini kami buat untuk menjawab pertanyaan-pertanyaan tersebut secara lengkap dan terstruktur.\n\nSilakan dibaca pelan-pelan, dan jangan ragu untuk menyimpan postingan ini sebagai referensi. Informasi lengkapnya di link berikut 👇\n{link}\n\n{h}"
    if v == 3:
        return f"{t} — panduan lengkapnya ada di sini.\n\nKami sering menerima pertanyaan seputar topik ini. Daripada menjawab satu per satu, kami rangkum semuanya dalam satu artikel yang mudah dipahami.\n\nLangsung saja baca artikelnya, semoga bermanfaat untuk Anda dan bisnis Anda. 👇\n{link}\n\n{h}"
    return f"Sudah tahu belum soal {t}?\n\nIni topik yang layak Anda ketahui sebelum mengambil langkah berikutnya. Penjelasannya kami buat lengkap namun tetap ringkas biar gampang dicerna.\n\nBaca selengkapnya di sini 👇\n{link}\n\n{h}"

def cap_li(brand, art, variant):
    t = clean_title(art["title"])
    link = art["link"]
    v = variant % 4
    if v == 0:
        return f"{t}\n\nTopik ini sering menjadi perhatian banyak profesional dan pelaku usaha. Sayangnya, informasi yang tersedia sering kali tersebar dan sulit dipahami.\n\nKami merangkum pembahasan lengkapnya dalam satu artikel — mencakup konteks, langkah praktis, dan hal-hal yang perlu dipertimbangkan sebelum mengambil keputusan.\n\nSilakan disimak, semoga bermanfaat. 👇\n{link}"
    if v == 1:
        return f"Beberapa hal penting tentang {t.lower()} yang layak Anda ketahui.\n\nDalam praktiknya, banyak keputusan diambil tanpa pemahaman yang cukup. Artikel ini kami susun untuk membantu Anda melihat gambaran lengkapnya.\n\nBaca selengkapnya di sini 👇\n{link}"
    if v == 2:
        return f"{t} — pandangan dan langkah praktisnya.\n\nKami membahasnya secara mendalam, dari latar belakang hingga implementasinya. Cocok dibaca sebelum Anda mengambil langkah strategis.\n\nArtikel lengkapnya ada di link berikut 👇\n{link}"
    return f"Mengapa {t.lower()} penting untuk dipahami?\n\nKarena keputusan yang baik dimulai dari pemahaman yang benar. Artikel ini menyajikan penjelasan yang jelas dan terstruktur.\n\nLangsung ke artikelnya di sini 👇\n{link}"

def enforce_max(text, maxlen=500):
    if len(text) <= maxlen:
        return text
    lines = text.split("\n")
    hashtags = ""
    body_lines = []
    for line in lines:
        if line.startswith("#") and not hashtags:
            hashtags = line
        else:
            body_lines.append(line)
    body = "\n".join(body_lines)
    max_body = maxlen - len(hashtags) - 1
    if max_body < 50:
        return text[:maxlen]
    body = body[:max_body].rstrip()
    return body + "\n" + hashtags

def slot_to_utc(wib_str):
    dt = datetime.fromisoformat(wib_str)
    return (dt - timedelta(hours=7)).strftime("%Y-%m-%dT%H:%M:%S.000Z")

# ── JADWAL HARIAN (6-31 Agustus) ──
# DAS: Threads 08:00 + FB 17:00
# StudioSoft: LinkedIn 09:00 + FB 10:00 + Threads 11:00
# LEIT: rotasi (Sen 14:00 Th / Sel 11:00 Li / Rab 19:00 FB / Kam 14:00 Th / Jum 11:00 Li / Sab 19:00 FB / Min 14:00 Th)
# TSLaw: rotasi (Sen 16:00 FB / Sel 20:00 Th / Rab 20:00 Li / Kam 16:00 FB / Jum 20:00 Th / Sab 20:00 Li / Min 16:00 FB)
# DMark: LinkedIn 14:00 + FB 19:00

def day_schedule(d):
    """Return list of (account_key, wib_time) for date d."""
    wd = d.weekday()  # 0=Sen
    ds = d.strftime("%Y-%m-%d")
    slots = []
    slots.append(("das_th", f"{ds}T08:00:00"))
    slots.append(("das_fb", f"{ds}T17:00:00"))
    slots.append(("ss_li", f"{ds}T09:00:00"))
    slots.append(("ss_fb", f"{ds}T10:00:00"))
    slots.append(("ss_th", f"{ds}T11:00:00"))
    slots.append(("dmark_li", f"{ds}T14:00:00"))
    # DMark FB: 3x/minggu (Sen, Rab, Jum) biar stok aman
    if wd in (0, 2, 4):
        slots.append(("dmark_fb", f"{ds}T19:00:00"))
    # LEIT rotasi
    if wd in (0, 3, 6):
        slots.append(("leit_th", f"{ds}T14:00:00"))
    elif wd in (1, 4):
        slots.append(("leit_li", f"{ds}T11:00:00"))
    else:
        slots.append(("leit_fb", f"{ds}T19:00:00"))
    # TSLaw rotasi
    if wd in (0, 3, 6):
        slots.append(("tslaw_fb", f"{ds}T16:00:00"))
    elif wd in (1, 4):
        slots.append(("tslaw_th", f"{ds}T20:00:00"))
    else:
        slots.append(("tslaw_li", f"{ds}T20:00:00"))
    return slots

BRAND_OF = {
    "das_th": "DAS", "das_fb": "DAS",
    "ss_th": "StudioSoft", "ss_fb": "StudioSoft", "ss_li": "StudioSoft",
    "leit_th": "LEIT", "leit_fb": "LEIT", "leit_li": "LEIT",
    "tslaw_th": "TSLaw", "tslaw_fb": "TSLaw", "tslaw_li": "TSLaw",
    "dmark_fb": "DMark", "dmark_li": "DMark",
}

def main():
    print("📅 JADWAL FULL AGUSTUS (6-31 Agustus) — anti-redundansi")
    print("=" * 60)
    start = datetime(2026, 8, 6)
    end = datetime(2026, 8, 31)
    ok, fail, skipped = 0, 0, 0
    counter = {}
    results = []
    d = start
    while d <= end:
        for acc_key, wib in day_schedule(d):
            brand = BRAND_OF[acc_key]
            art = take_article(brand)
            if not art:
                print(f"  ⚠️ {d.date()} {acc_key}: stok {brand} HABIS, skip")
                skipped += 1
                continue
            variant = counter.get(acc_key, 0)
            counter[acc_key] = variant + 1
            if acc_key.endswith("_th"):
                text = cap_threads(brand, art, variant)
            elif acc_key.endswith("_fb"):
                text = cap_fb(brand, art, variant)
            else:
                text = cap_li(brand, art, variant)
            if acc_key.endswith("_th"):
                text = enforce_max(text, 500)
            sched = slot_to_utc(wib)
            try:
                r = client.schedule_text(A[acc_key], text, sched, title="")
                sid = r.get("scheduleId", "?")
                results.append({"date": d.date().isoformat(), "account": acc_key, "scheduleAt": wib, "scheduleId": sid, "article": art["link"]})
                ok += 1
                if ok % 20 == 0:
                    print(f"  ...{ok} terjadwal")
            except Exception as e:
                print(f"  ❌ {d.date()} {acc_key}: {type(e).__name__} {str(e)[:80]}")
                fail += 1
        d += timedelta(days=1)
    print("=" * 60)
    print(f"✅ {ok} terjadwal | ❌ {fail} gagal | ⏭️ {skipped} skip (stok habis)")
    with open("jadwal_agustus_results.json", "w") as f:
        json.dump(results, f, ensure_ascii=False, indent=1)
    print("📄 jadwal_agustus_results.json disimpan")

if __name__ == "__main__":
    main()
