#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ss_cards_run.py — render + jadwalkan kartu StudioSoft (Threads + FB).

Perintah Bos 16 Sep 2026: "ok pakai Kita (bukan saya)" + "untuk jadwal silakan FB
jalankan juga" + "kasih juga link dari website ya agar artikelnya tershare".

Yang dilakukan:
  1. Link tiap kartu diverifikasi FREE (belum dipakai akun itu) + HTTP 200.
  2. Kartu dirender (square 1080×1080, rata kiri, header www.studiosoft.id, footer asli).
  3. Threads StudioSoft : 1 kartu/hari 08:00 WIB (image + caption berisi link) mulai 30 Sep 2026.
  4. FB StudioSoft      : 1 teks/hari 19:00 WIB (tanpa gambar — aturan 15 Sep, replies=[]) mulai 17 Sep.
  5. Verifikasi ulang via fetch dari API.

Default DRY RUN; pakai --apply untuk create jadwal.
"""
import json
import os
import re
import subprocess
import sys
from datetime import datetime, timedelta, timezone

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from PIL import Image
from repliz_client import ReplizClient, ACC, IMG_BASE_URL, IMG_DIR
import gen_uky_center as G
import ss_cards_content as C

WS = G.WS
HEADER = "www.studiosoft.id"
CANVAS = (1080, 1080)
OUT_DIR = os.path.join(WS, "ss_threads_images")
INGRESS = ["103.84.155.153", "103.84.155.217"]

# FREKUENSI (perintah Bos 16 Sep 2026): "tidak usah terlalu sering posting. cukup
# pasang di jam-jam prime time saja" → 2x/minggu per kanal:
#   Selasa & Jumat  08:00 WIB → Threads StudioSoft (pagi prime time)
#   Selasa & Jumat  19:30 WIB → FB StudioSoft (malam prime time)
PRIME_DAYS = (1, 4)          # 0=Senin ... 1=Selasa, 4=Jumat
THREADS_HOUR_UTC = (1, 0)    # 08:00 WIB
FB_HOUR_UTC = (12, 30)       # 19:30 WIB
FIRST_DAY = datetime(2026, 9, 30, tzinfo=timezone.utc)  # pertama Selasa/Jumat setelah 30 Sep = 2 Okt


def prime_dates(n, start=FIRST_DAY):
    """n tanggal prime time (Selasa & Jumat) mulai dari `start`."""
    out, d = [], start
    while len(out) < n:
        if d.weekday() in PRIME_DAYS:
            out.append(d)
        d += timedelta(days=1)
    return out


def http_ok(url):
    for ip in INGRESS:
        r = subprocess.run(
            ["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", "--max-time", "30",
             "--resolve", f"mantapserver.tail3947bb.ts.net:443:{ip}", url],
            capture_output=True, text=True)
        if r.stdout.strip() != "200":
            return False
    return True


def fetch_all(c):
    docs, p = [], 1
    while True:
        r = c.get_schedules(page=p, limit=100)
        d = r.get("docs") or []
        docs += d
        if not d or p >= (r.get("totalPages") or 1):
            break
        p += 1
    return docs


def used_links():
    """URL yang sudah pernah dipakai (anti-redundant) per akun."""
    out = {}
    try:
        out = json.load(open("/tmp/threads_used_all.json"))
    except Exception:
        pass
    return set(out.get("studiosoft") or [])


def render_cards(entries):
    made = []
    for e in entries:
        bg, fg = G.BG_MAP[e["bg"]]
        p = G.render(bg, fg, e["judul"], e["body"], e["footer"], "1/1",
                     filename=e["name"] + ".png", mode="left", out_dir=OUT_DIR,
                     canvas=CANVAS, title_size=85, body_size=36, header=HEADER)
        made.append((e, p))
    return made


def main():
    apply = "--apply" in sys.argv
    c = ReplizClient()
    used = used_links()

    # ── 1. validasi link ─────────────────────────────────────────────────
    print("── validasi link artikel ──")
    problems = []
    for e in C.CARDS:
        u = e["link"]
        is_free = u not in used
        ok = http_ok(u) if is_free else False
        print(f"  {'✅' if (is_free and ok) else '❌'} {e['name'][:34]:34} free={is_free} 200={ok} {u}")
        if not (is_free and ok):
            problems.append(e["name"])
    if problems:
        print("❌ link bermasalah:", problems)
        return 1

    # ── 2. caption check ─────────────────────────────────────────────────
    print("\n── caption (≤500 char) ──")
    bad = []
    for e in C.CARDS:
        cap = e["caption"].format(link=e["link"])
        if len(cap) > 500:
            bad.append((e["name"], len(cap)))
    print("  caption >500 char:", bad or "TIDAK ADA ✅")
    if bad:
        return 1

    # ── 3. render gambar ─────────────────────────────────────────────────
    print("\n── render kartu ──")
    made = render_cards(C.CARDS)
    for e, p in made[:3]:
        print(f"  ✅ {p} {Image.open(p).size}")

    # ── 4. upload + verifikasi media ─────────────────────────────────────
    print("\n── upload media + verifikasi 200 ──")
    media = {}
    for e, p in made:
        jpg = e["name"] + "_ss.jpg"
        src = Image.open(p)
        if src.mode != "RGB":
            src = src.convert("RGB")
        src.save(os.path.join(IMG_DIR, jpg), "JPEG", quality=90)
        url = f"{IMG_BASE_URL}/openclaw-img/{jpg}"
        if not http_ok(url):
            print(f"  ❌ {jpg} tidak 200 di kedua ingress — STOP")
            return 1
        media[e["name"]] = url
    print(f"  {len(media)} media siap & 200 di kedua ingress ✅")

    dates = prime_dates(len(C.CARDS))
    plan_ths = [(C.CARDS[i], (dates[i] + timedelta(hours=THREADS_HOUR_UTC[0],
                                                   minutes=THREADS_HOUR_UTC[1])))
                for i in range(len(C.CARDS))]
    plan_fb = [(C.CARDS[i], (dates[i] + timedelta(hours=FB_HOUR_UTC[0],
                                                  minutes=FB_HOUR_UTC[1])))
               for i in range(len(C.CARDS))]

    if not apply:
        for e, at in plan_ths:
            print(f"  THREADS {at.strftime('%Y-%m-%d %H:%MZ')} | {e['name']}")
        for e, at in plan_fb:
            print(f"  FB      {at.strftime('%Y-%m-%d %H:%MZ')} | {e['name']}")
        print("\n🧪 DRY RUN — tambahkan --apply untuk create jadwal.")
        return 0

    # ── 5. create jadwal ─────────────────────────────────────────────────
    ts = {}
    print("\n── create Threads StudioSoft (image + caption ber-link) ──")
    for e, at in plan_ths:
        cap = e["caption"].format(link=e["link"])
        r = c.create_schedule(ACC.STUDIOSOFT_THREADS, cap, at.strftime("%Y-%m-%dT%H:%M:%S.000Z"),
                              title=e["judul"].replace("\n", " "), topic="StudioSoft card",
                              type_="image",
                              medias=[{"type": "image", "url": media[e["name"]], "alt": e["name"]}],
                              replies=[])
        ts[e["name"]] = r.get("scheduleId") or r.get("_id") or r.get("id")
        print(f"  {at.strftime('%d %b %H:%MZ')} {e['name'][:32]:32} → {ts[e['name']]}")

    fb = {}
    print("\n── create FB StudioSoft (TEXT saja, replies=[]) ──")
    for e, at in plan_fb:
        cap = e["caption"].format(link=e["link"])
        r = c.create_schedule(ACC.STUDIOSOFT_FB, cap, at.strftime("%Y-%m-%dT%H:%M:%S.000Z"),
                              title=e["judul"].replace("\n", " "), topic="StudioSoft card",
                              type_="text", medias=[], replies=[])
        fb[e["name"]] = r.get("scheduleId") or r.get("_id") or r.get("id")
        print(f"  {at.strftime('%d %b %H:%MZ')} {e['name'][:32]:32} → {fb[e['name']]}")

    # ── 6. verifikasi ulang dari API ─────────────────────────────────────
    print("\n── verifikasi ulang (fetch baru dari API) ──")
    docs = {d.get("_id"): d for d in fetch_all(c)}
    ok = 0
    for name, sid in list(ts.items()) + list(fb.items()):
        d = docs.get(sid) or {}
        med = len(d.get("medias") or [])
        rep = len(d.get("replies") or [])
        expect_med = 1 if name in ts else 0
        good = (d.get("status") == "pending" and med == expect_med and rep == 0)
        ok += bool(good)
        print(f"  {'✅' if good else '⚠️'} {name[:30]:30} {d.get('status')} medias={med} "
              f"replies={rep} at={d.get('scheduleAt')}")
    print(f"\n{ok}/{len(ts)+len(fb)} jadwal terverifikasi")
    json.dump({"threads": ts, "fb": fb}, open(os.path.join(WS, "ss_cards_log.json"), "w"),
              indent=2, ensure_ascii=False)
    return 0 if ok == len(ts) + len(fb) else 1


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