#!/usr/bin/env python3
"""StudioSoft Healthcare — hc34 = RE-AIR hc20 "Pentingnya Konten Edukasi Kesehatan untuk Meningkatkan Kepercayaan Pasien".

Konteks (cron run 12 Sep 2026, 02:00 WIB):
- Stok artikel healthcare studiosoft.id masih HABIS: WP REST (via proxy r.jina.ai) menunjukkan
  artikel terbaru tetap 3 Sep 2026 (AI Personal Assistant, non-healthcare) -> 0 artikel healthcare baru.
- hc20 & hc21 belum pernah tayang (semua jadwalnya error karena URL media BARE tanpa /openclaw-img/).
  Run ini me-re-air hc20 dengan URL funnel yang sudah diverifikasi lewat jalur INTERNET.
- hc33 (re-air hc19) sudah terpasang 14 Sep 17:00 WIB; sisanya nanti hc21.

ATURAN:
- LinkedIn StudioSoft: SKIP — artikel hc20 SUDAH punya post text LinkedIn (status success 6 Sep 2026)
  dan 191 jadwal text LinkedIn SS pending s/d 9 Okt.
- Threads + FB: album carousel OK. IG tidak disentuh.
- FB: album, replies KOSONG. Threads: album + 2 replies (link artikel + hashtag).
- CAROUSEL = 09:00 WIB (aturan Bos 11 Sep 2026) -> slot bebas pertama 09:00 WIB untuk Threads+FB.
- Hashtag huruf kecil semua, 0 mention, caption wajib pancingan diskusi.
"""
import json, os, re, subprocess, sys
from datetime import datetime, timezone, timedelta

sys.path.insert(0, "/home/mantapman/.openclaw/workspace-atun")
from repliz_client import ReplizClient, ACC
from diskusi_engine import tambahkan_diskusi

DRY = os.environ.get("DRY", "") == "1"

c = ReplizClient()

SLOT_UTC = os.environ.get("SLOT_UTC", "2026-09-12T02:00:00.000Z")   # 12 Sep 2026 09:00 WIB (carousel = jam 9)
SLOT_LABEL = "12 Sep 2026 09:00 WIB"
TITLE = "Pentingnya Konten Edukasi Kesehatan untuk Kepercayaan Pasien"
ARTICLE_URL = "https://studiosoft.id/konten-edukasi-kesehatan-kepercayaan-pasien"
HASHTAG_LINE = "#studiosoft #kontenedukasi #digitalmarketing #rumahsakit #klinik"
MEDIA_URLS = [
    "https://mantapserver.tail3947bb.ts.net/openclaw-img/ss_hc20_edukasi_01_cover.jpg",
    "https://mantapserver.tail3947bb.ts.net/openclaw-img/ss_hc20_edukasi_02_kenapa.jpg",
    "https://mantapserver.tail3947bb.ts.net/openclaw-img/ss_hc20_edukasi_03_isi.jpg",
    "https://mantapserver.tail3947bb.ts.net/openclaw-img/ss_hc20_edukasi_04_langkah.jpg",
    "https://mantapserver.tail3947bb.ts.net/openclaw-img/ss_hc20_edukasi_05_cta.jpg",
]

THREADS_BASE = """Pasien lebih percaya RS yang mengedukasi daripada yang cuma promosi diskon.

Cukup rutin bagikan:
✅ Info gejala & kapan harus ke dokter
✅ Mitos vs fakta kesehatan
✅ Tips pola hidup sehat
✅ Jawaban pertanyaan pasien

Konten yang bermanfaat menumbuhkan kepercayaan — sebelum pasien datang, mereka sudah yakin."""

FB_BASE = """RS dan klinik yang rajin berbagi edukasi kesehatan justru lebih dipercaya pasien daripada yang hanya promosi.

Mengapa? Karena konten yang bermanfaat menunjukkan kepedulian — bukan sekadar mengejar pasien.

Ide konten yang bisa dipakai:
1. Gejala umum dan kapan harus ke dokter
2. Mitos vs fakta seputar kesehatan
3. Tips mencegah penyakit lewat pola hidup sehat
4. Jawaban atas pertanyaan yang sering masuk

Rutin membagikannya di IG, FB, dan artikel website akan membangun kepercayaan sebelum pasien memutuskan datang.

Bold statement: RS yang hanya jualan tanpa edukasi diam-diam kehilangan kepercayaan pasien.

Baca artikel lengkapnya: %s""" % ARTICLE_URL

CTA_RE = re.compile(r"komentar|pendapat|diskusi|setuju|share|pengalaman|menurut", re.I)


def build_threads(max_try=60):
    """Pancingan random bisa tanpa ajakan komentar -> undi ulang sampai lolos CTA + <=500 char.
    Utamakan varian yang memuat LINK artikel; fallback tanpa link di badan (link ada di reply)."""
    variants = [
        THREADS_BASE + "\n\nBaca artikelnya: " + ARTICLE_URL,
        THREADS_BASE,
    ]
    for base in variants:
        for _ in range(max_try):
            txt = tambahkan_diskusi(base, platform="threads", industri="rumah_sakit",
                                    tone="netral", force=True)
            if CTA_RE.search(txt) and len(txt) <= 500:
                return txt
    return None


def build_fb(max_try=40):
    for _ in range(max_try):
        txt = tambahkan_diskusi(FB_BASE, platform="facebook", industri="rumah_sakit",
                                tone="opini", force=True)
        if CTA_RE.search(txt):
            return txt
    return None


THREADS = build_threads()
FB = build_fb()

REPLY1 = ("Baca selengkapnya: %s\n\n"
          "Konsultasi strategi konten edukasi RS/klinik:\nwww.studiosoft.id" % ARTICLE_URL)
REPLY2 = HASHTAG_LINE


def check_caption(name, txt, limit=None, require_cta=True):
    ok = True
    if limit and len(txt) > limit:
        print("  ❌ %s: %d char > %d" % (name, len(txt), limit))
        ok = False
    m = re.findall(r"@\w+", txt)
    if m:
        print("  ❌ %s: ada mention %s" % (name, m))
        ok = False
    caps = [t for t in re.findall(r"#(\w+)", txt) if t != t.lower()]
    if caps:
        print("  ❌ %s: hashtag KAPITAL %s" % (name, caps))
        ok = False
    if require_cta and not CTA_RE.search(txt):
        print("  ❌ %s: tidak ada pancingan diskusi" % name)
        ok = False
    print("  %s %s: %d char" % ("✅" if ok else "⚠️", name, len(txt)))
    return ok


def verify_urls_internet():
    ips = subprocess.run(["dig", "+short", "mantapserver.tail3947bb.ts.net", "A", "@1.1.1.1"],
                         capture_output=True, text=True).stdout.split()
    ips = [i for i in ips if i.count(".") == 3]
    ok = True
    for u in MEDIA_URLS:
        for ip in ips[:2]:
            r = subprocess.run(["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}",
                                "--max-time", "20", "--resolve",
                                "mantapserver.tail3947bb.ts.net:443:%s" % ip, u],
                               capture_output=True, text=True)
            code = r.stdout.strip()
            print("  %s @%s: %s" % (u.split("/")[-1], ip, code))
            if code != "200":
                ok = False
    return ok


def scan(need, statuses):
    hits = []
    page = 1
    while True:
        d = c.get("/public/schedule?page=%d&limit=100" % page)
        for s in d.get("docs", []):
            if s.get("accountId") not in (ACC.STUDIOSOFT_THREADS, ACC.STUDIOSOFT_FB):
                continue
            if (s.get("status") or "").lower() not in statuses:
                continue
            if any(need in (m.get("url") or "") for m in (s.get("medias") or [])):
                hits.append((s.get("accountId"), (s.get("scheduleAt") or "")[:16],
                             (s.get("title") or "")[:45], s.get("type"),
                             len(s.get("medias") or []), len(s.get("replies") or [])))
        if page >= (d.get("totalPages") or 1):
            break
        page += 1
    return hits


def slot_conflict(aids, slot_utc):
    base = datetime.fromisoformat(slot_utc.replace("Z", "+00:00"))
    busy = set()
    page = 1
    while True:
        d = c.get("/public/schedule?page=%d&limit=100" % page)
        for s in d.get("docs", []):
            if s.get("accountId") in aids and (s.get("status") or "").lower() in ("pending", "scheduled", "draft"):
                st = (s.get("scheduleAt") or "")[:19]
                if st:
                    busy.add(st)
        if page >= (d.get("totalPages") or 1):
            break
        page += 1
    return [ (base + timedelta(minutes=off)).strftime("%Y-%m-%dT%H:%M:%S")
             for off in range(6)
             if (base + timedelta(minutes=off)).strftime("%Y-%m-%dT%H:%M:%S") in busy ]


def next_free_slot():
    """Cari hari pertama (mulai hari ini WIB) yang 09:00 WIB-nya bebas di Threads & FB."""
    aids = [ACC.STUDIOSOFT_THREADS, ACC.STUDIOSOFT_FB]
    base = datetime.fromisoformat(SLOT_UTC.replace("Z", "+00:00"))
    for day in range(8):
        cand = (base + timedelta(days=day)).strftime("%Y-%m-%dT02:00:00.000Z")
        if not slot_conflict(aids, cand):
            return cand
    return None


def main():
    global SLOT_UTC, SLOT_LABEL
    wib = datetime.now(timezone(timedelta(hours=7)))
    print("Time WIB: %s" % wib.strftime("%Y-%m-%d %H:%M"))

    print("\nCEK SLOT 09:00 WIB (Threads+FB):")
    clash = slot_conflict([ACC.STUDIOSOFT_THREADS, ACC.STUDIOSOFT_FB], SLOT_UTC)
    if clash:
        print("  ⚠️ %s terisi: %s -> cari 09:00 hari berikutnya" % (SLOT_LABEL, clash))
        cand = next_free_slot()
        if not cand:
            print("  ❌ tidak ada slot 09:00 bebas 8 hari ke depan — batal.")
            return False
        SLOT_UTC = cand
        d = datetime.fromisoformat(cand.replace("Z", "+00:00")) + timedelta(hours=7)
        SLOT_LABEL = d.strftime("%d %b %Y 09:00 WIB")
    print("  ✅ slot: %s (%s)" % (SLOT_LABEL, SLOT_UTC))

    print("\nCEK CAPTION:")
    if not THREADS or not FB:
        print("  ❌ gagal menyusun caption dgn pancingan diskusi — batal.")
        return False
    ok = True
    ok &= check_caption("Threads", THREADS, 500)
    ok &= check_caption("FB", FB)
    ok &= check_caption("Reply1", REPLY1, require_cta=False)
    ok &= check_caption("Reply2", REPLY2, require_cta=False)
    if not ok:
        print("\n❌ Caption gagal aturan — batal.")
        return False
    print("\n--- THREADS preview ---\n%s\n[%d char]" % (THREADS, len(THREADS)))

    hits = scan("ss_hc20_edukasi_01_cover.jpg", ("pending", "scheduled", "draft"))
    if hits:
        print("\n⚠️ Media hc20 sudah ada di pending (idempoten, SKIP create):")
        for h in hits:
            print("  ", h)
        return True

    print("\nVERIFIKASI MEDIA JALUR INTERNET:")
    if not verify_urls_internet():
        print("❌ Ada media tidak 200 dari internet — batal.")
        return False

    if DRY:
        print("\n[DRY RUN] caption & media siap; tidak ada create.")
        return True

    base_dt = datetime.fromisoformat(SLOT_UTC.replace("Z", "+00:00"))
    r2 = (base_dt + timedelta(minutes=1)).strftime("%Y-%m-%dT%H:%M:%S.000Z")
    r3 = (base_dt + timedelta(minutes=2)).strftime("%Y-%m-%dT%H:%M:%S.000Z")
    medias = [c.make_media(u, "image", "slide%d" % (i + 1)) for i, u in enumerate(MEDIA_URLS)]

    results = {}
    print("\nTHREADS:")
    try:
        album = c.schedule_album(ACC.STUDIOSOFT_THREADS, THREADS, SLOT_UTC, medias, title=TITLE)
        pid = album.get("scheduleId") or album.get("_id") or album.get("id")
        print("  OK album -> %s" % pid)
        c.create_schedule(ACC.STUDIOSOFT_THREADS, REPLY1, r2, type_="text", replies=[pid])
        c.create_schedule(ACC.STUDIOSOFT_THREADS, REPLY2, r3, type_="text", replies=[pid])
        print("  OK 2 replies")
        results["threads"] = True
    except Exception as e:
        print("  GAGAL %s" % e)
        results["threads"] = False

    print("\nFACEBOOK:")
    try:
        album = c.schedule_album(ACC.STUDIOSOFT_FB, FB, SLOT_UTC, medias, title=TITLE)
        pid = album.get("scheduleId") or album.get("_id") or album.get("id")
        print("  OK album -> %s" % pid)
        results["fb"] = True
    except Exception as e:
        print("  GAGAL %s" % e)
        results["fb"] = False

    print("\n" + "=" * 55)
    ok = all(results.values())
    print("Semua platform dijadwalkan!" if ok else "Gagal: %s" % [k for k, v in results.items() if not v])

    if ok:
        print("\nVERIFIKASI (re-list pending):")
        for h in scan("ss_hc20_edukasi_01_cover.jpg", ("pending",)):
            print("  ", h)
        with open("/home/mantapman/.openclaw/workspace-atun/studiosoft_healthcare_log.txt", "a") as f:
            f.write("\n[%s WIB] hc34 (RE-AIR hc20) | %s | %s | Threads+FB album %s (%s), +2 replies Threads | "
                    "LinkedIn SKIP (artikel sdh punya text LI success 6 Sep) | catatan: stok artikel healthcare "
                    "masih HABIS (artikel terbaru di website tetap 3 Sep 2026, non-healthcare); hc20 belum pernah "
                    "tayang (error URL media bare) -> re-air dgn URL /openclaw-img/ terverifikasi 200 jalur internet. "
                    "BUTUH artikel healthcare baru dari Bos (sisa kandidat re-air: hc21).\n"
                    % (wib.strftime("%Y-%m-%d %H:%M"), TITLE, ARTICLE_URL, SLOT_LABEL, SLOT_UTC[11:16] + "Z"))
        print("Log ditulis.")
    return ok


if __name__ == "__main__":
    sys.exit(0 if main() else 1)
