#!/usr/bin/env python3
"""Catch-up TikTok: video Pak Otto yang SUDAH tayang di Instagram tapi TikTok-nya
pernah ERROR (belum pernah tayang).

Ditemukan dari audit 14 Sep 2026 (semua status, per accountId):
  - soto_reel_bos.mp4          -> IG success 22 Agu | TikTok error 2 Sep (ETIMEDOUT)
  - soto_pakotto_video4.mp4    -> IG success 1 Sep  | TikTok error 1 Sep (ETIMEDOUT)
  - soto_pakotto_video5.mp4    -> IG success 1 Sep  | TikTok error 1 Sep (404)
  - soto_pakotto_video8.mp4    -> IG success 7 Sep  | TikTok error 7 Sep (ETIMEDOUT)

Jadwal: TikTok, tiap hari jam 17:00 WIB (10:00 UTC), 1 post/hari.
Caption: dari caption yang sudah tayang (IG), hashtag di-lowercase (aturan Bos),
jam buka dikoreksi ke "Buka Setiap Hari: 10.00 - 21.00 WIB".
Idempoten: skip kalau media sudah ada di jadwal TikTok (status apa pun).
Verifikasi: URL harus 200 lewat jalur INTERNET (2 ingress) sebelum create.
"""
import json
import subprocess
import sys
import urllib.request
from datetime import datetime, timedelta, timezone

sys.path.insert(0, "/home/mantapman/.hermes/profiles/atun/workspace")
from repliz_client import HEADERS, BASE  # noqa: E402

TIKTOK = "6a86d70362caae1e04ffedef"
BASE_URL = "https://mantapserver.tail3947bb.ts.net/openclaw-img"
WIB = timezone(timedelta(hours=7))
INGRESS = ["103.84.155.153", "103.84.155.217"]

LOKASI = """📍 Jl. Graha Anggrek Mas No. C-16, Ruko Pagerwojo, Buduran, Sidoarjo
⏰ Buka Setiap Hari: 10.00 - 21.00 WIB
📲 081230777713"""

ITEMS = [
    {
        "file": "soto_reel_bos.mp4",
        "title": "Soto Pak Otto — Reels Bos (TikTok)",
        "cap": f"""Soto Semarang Pak Otto — rasa Semarang, hati Sidoarjo 🍜

Kuah bening, ayam kampung asli, sate kerang juara. Makan enak nggak harus mahal — soto cuma Rp10 ribu tok 😄

{LOKASI}

Kulineran malam di Sidoarjo? Mampir aja, kami tunggu! 🔥

#sotosemarangpakotto #sotosidoarjo #kulinermalam #kulinersidoarjo #kulinermurah #fyp #fypindonesia""",
        "offset_days": 0,   # 14 Sep 2026 17:00 WIB
    },
    {
        "file": "soto_pakotto_video4.mp4",
        "title": "Soto Pak Otto — POV (TikTok)",
        "cap": f"""POV: Masuk Warung Pak Otto, niatnya cuma lihat-lihat… keluarnya kenyang! 🤤🍽️

Beneran, nggak ada yang bisa lolos dari aroma soto ayam kampung yang baru dihidangin. Cuma mau cek menu, eh ujung-ujungnya pesan semangkuk + mendoan panas + sate kerang. 😄

Kalau udah begini, mampirnya jangan sendiri — ajak teman biar rame! 🍜✨

{LOKASI}

#sotosemarangpakotto #pov #kulinersidoarjo #sotosemarang #kulinermalam #warungsemarang #fyp #fypindonesia""",
        "offset_days": 1,   # 15 Sep 2026 17:00 WIB
    },
    {
        "file": "soto_pakotto_video5.mp4",
        "title": "Soto Pak Otto — Video 5 (TikTok)",
        "cap": f"""Soto Semarang Ayam Kampung yang hangatnya nempel di hati — pas banget buat nemenin malam minggu. 🍜✨

Kuah bening gurih, ayam kampung empuk, plus sambal yang bikin nagih. Dijamin makin enak dinikmati ramai-ramai.

{LOKASI}

Pernah cobain soto Semarang di sini? Menu favorit kalian apa? Cerita di komentar ya! 👇

#sotosemarangpakotto #sotosemarang #kulinersidoarjo #kulinermalam #warungsemarang #sotoayamkampung #fyp #fypindonesia""",
        "offset_days": 2,   # 16 Sep 2026 17:00 WIB
    },
    {
        "file": "soto_pakotto_video8.mp4",
        "title": "Soto Pak Otto — Video 8 (TikTok)",
        "cap": f"""Seru-seruan di Warung Pak Otto — soto Semarang ayam kampung yang selalu fresh dari pagi! 🍜✨

Kuah bening gurih, ayam empuk, sambal pedasnya pas. Ditambah tempe mendoan 2 ribuan & lumpia Semarang 7 ribuan — makin mantap!

Ga perlu ke Semarang, cukup ke Pagerwojo Sidoarjo! 😋

{LOKASI}

Udah pernah mampir? Menu favoritmu apa? Cerita di komentar ya! 👇

#sotosemarangpakotto #sotosemarang #kulinersidoarjo #kulinermalam #warungsemarang #sotoayamkampung #fyp #fypindonesia""",
        "offset_days": 3,   # 17 Sep 2026 17:00 WIB
    },
]


def req_json(url, data=None, method="GET"):
    body = json.dumps(data).encode() if data else None
    r = urllib.request.Request(url, data=body, headers={**HEADERS, "Content-Type": "application/json"}, method=method)
    with urllib.request.urlopen(r, timeout=90) as resp:
        raw = resp.read()
        return json.loads(raw) if raw else {}


def tiktok_media_aliases():
    """Basename media yang sudah ada di jadwal TikTok AKTIF (pending/success).
    Status `error` TIDAK dihitung — jadwal error tidak bisa tayang & harus di-create ulang."""
    out = set()
    page = 1
    while True:
        d = req_json(f"{BASE}/public/schedule?page={page}&limit=100")
        docs = d.get("docs") or []
        if not docs:
            break
        for s in docs:
            if s.get("accountId") == TIKTOK and (s.get("status") or "").lower() in ("pending", "success", "processing", "draft"):
                for m in s.get("medias") or []:
                    out.add((m.get("url") or "").split("?")[0].rstrip("/").split("/")[-1].lower())
        if page >= (d.get("totalPages") or 1):
            break
        page += 1
    return out


def url_ok_internet(url):
    """HTTP 200 lewat jalur INTERNET (resolve ke tiap ingress funnel)."""
    codes = []
    for ip in INGRESS:
        cp = subprocess.run(
            ["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", "-L", "--max-time", "30",
             "--resolve", f"mantapserver.tail3947bb.ts.net:443:{ip}", url],
            capture_output=True, text=True)
        codes.append(cp.stdout.strip())
    return codes


def main():
    existing = tiktok_media_aliases()
    now = datetime.now(WIB)
    ok = 0
    for it in ITEMS:
        name = it["file"]
        url = f"{BASE_URL}/{name}"
        target = (now + timedelta(days=it["offset_days"])).replace(hour=17, minute=0, second=0, microsecond=0)
        at = target.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.000Z")
        print("=" * 70)
        print(f"{name}  ->  {target:%d %b %Y %H:%M} WIB  ({at})")
        if name.lower() in existing:
            print("  ⏭  sudah ada di jadwal TikTok — SKIP")
            continue
        codes = url_ok_internet(url)
        print(f"  🌐 funnel check: lokasi1={codes[0]} lokasi2={codes[1]}")
        if any(c != "200" for c in codes):
            print("  ❌ URL tidak 200 di jalur internet — TIDAK dijadwalkan")
            continue
        if len(it["cap"]) > 2200:
            print(f"  ❌ caption {len(it['cap'])} char kepanjangan — batal")
            continue
        up = [t for t in __import__("re").findall(r"#(\w+)", it["cap"]) if t != t.lower()]
        if up:
            print(f"  ❌ hashtag huruf besar: {up} — batal")
            continue
        payload = {
            "accountId": TIKTOK,
            "title": it["title"],
            "description": it["cap"],
            "topic": "Menu Pak Otto",
            "type": "video",
            "medias": [{"url": url, "type": "video", "alt": name}],
            "scheduleAt": at,
            "replies": [],
        }
        try:
            res = req_json(f"{BASE}/public/schedule", payload, "POST")
            sid = res.get("scheduleId") or res.get("_id") or res.get("id")
            print(f"  ✅ created {sid} | caption {len(it['cap'])} char")
            ok += 1
        except Exception as e:
            print(f"  ❌ GAGAL — {e}")
    print(f"\nSelesai: {ok} jadwal TikTok dibuat.")


if __name__ == "__main__":
    main()
