#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Dojo Ksatria IG — video Timotius Arjuna (SUDUT BIRU) di kejuaraan taekwondo Surabaya.

Perintah Bos 25 Sep 2026: "Tun pasang ini di IG Ksatria Dojo. Penampilan dari Timotius
Arjuna (Sudut Biru)".

Aturan akun (SKILL.md): 1 reels/hari 09:00 WIB, video + _thumb.jpg, hashtag huruf kecil,
replies=[]. Video dari Bos berbentuk LANDSCAPE (848x464) → versi 9:16 blur-pad sudah
DISETUJUI Bos (15 Sep 2026) → langsung diterapkan, file landscape tetap disimpan.

Slot = antrean akhir akun (re-list pending) + 1 hari, 09:00 WIB. Kalau tidak ada pending
sama sekali → 09:00 WIB berikutnya yang belum lewat.

Usage:
    python3 schedule_dojo_timotius_arjuna.py                 # dry-run
    python3 schedule_dojo_timotius_arjuna.py --schedule      # create jadwal
    python3 schedule_dojo_timotius_arjuna.py --src /path.mp4 # sumber lain
Idempoten: kalau media dgn basename sama sudah ada (pending/success/processing/draft) → SKIP.
"""
import os
import re
import shutil
import subprocess
import sys
from datetime import datetime, timedelta, timezone

from PIL import Image

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from repliz_client import ReplizClient, ACC, IMG_BASE_URL

WIB = timezone(timedelta(hours=7))
ROOT = os.path.dirname(os.path.abspath(__file__))
IMG_DIR = os.path.join(ROOT, "openclaw-img")
LOG_FILE = os.path.join(ROOT, "dojo_ksatria_log.txt")

DEFAULT_SRC = ("/home/mantapman/.hermes/profiles/atun/cache/videos/"
               "video_7390ac368c22.mp4")
BASENAME = "dojo_timotius_arjuna_01"
RAW_NAME = BASENAME + ".mp4"
VIDEO_NAME = BASENAME + "_9x16.mp4"
THUMB_NAME = BASENAME + "_9x16_thumb.jpg"
THUMB_AT = 8.6          # detik frame thumbnail (adegan duel terlihat jelas)
INGRESS = ["103.84.155.153", "103.84.155.217"]
LIVE = ("pending", "success", "processing", "draft")

CAPTION = (
    "Timotius Arjuna, anggota Dojo Ksatria, berlaga dari sudut biru di kejuaraan "
    "taekwondo di Surabaya! 🥋🔥\n\n"
    "Kyorugi bukan cuma soal tendangan. Butuh keberanian buat maju, dan ketenangan saat "
    "tempo pertandingan naik, apalagi di lapangan yang ramai penonton dan juri.\n\n"
    "Semua itu hasil latihan panjang di dojo. Terus melangkah, Timotius. Satu dojo, satu "
    "keluarga. Dari Balai RW 02, Ketintang Baru, Surabaya.\n\n"
    "Yuk dukung Timotius di kolom komentar 👇\n\n"
    "#dojoksatria #timotiusarjuna #taekwondoindonesia #taekwondosurabaya #kyorugi "
    "#kejuaraan #atletmuda #beladiri #ketintang #surabaya"
)

BLUR_FILTER = (
    "[0:v]scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,"
    "boxblur=30:3[bg];[0:v]scale=1080:-2[fg];[bg][fg]overlay=(W-w)/2:(H-h)/2"
)


def log(msg):
    line = f"{datetime.now(WIB).strftime('%Y-%m-%d %H:%M:%S')} WIB | {msg}"
    with open(LOG_FILE, "a", encoding="utf-8") as f:
        f.write(line + "\n")
    print(line)


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


def is_dojo(x):
    return (x.get("accountId") == ACC.DOJO_KSATRIA_IG
            or (x.get("account") or {}).get("id") == ACC.DOJO_KSATRIA_IG)


def dojo_media(c):
    """Re-list akun Dojo dari API (jangan pakai snapshot lama)."""
    out = []
    for x in fetch_all(c):
        if not is_dojo(x):
            continue
        for m in (x.get("medias") or []):
            u = (m.get("url") or "").split("?")[0]
            out.append({"id": x.get("_id"), "status": x.get("status"),
                        "scheduleAt": x.get("scheduleAt"),
                        "base": os.path.basename(u).lower()})
    return out


def next_slot(media_rows, now=None):
    """09:00 WIB, 1 hari setelah jadwal terjadwal terakhir (atau besok kalau kosong)."""
    now = now or datetime.now(WIB)
    slot = now.replace(hour=9, minute=0, second=0, microsecond=0)
    if slot <= now:
        slot += timedelta(days=1)
    last = None
    for m in media_rows:
        sa = m.get("scheduleAt")
        if not sa or m.get("status") not in LIVE:
            continue
        d = datetime.fromisoformat(sa.replace("Z", "+00:00")).astimezone(WIB)
        if last is None or d > last:
            last = d
    if last is not None:
        while slot.date() <= last.date():
            slot += timedelta(days=1)
    return slot


def verify_url(url):
    ok = True
    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)
        code = r.stdout.strip()
        print(f"    ingress {ip}: {code}")
        if code != "200":
            ok = False
    return ok


def main():
    args = sys.argv
    sched = "--schedule" in args
    src = args[args.index("--src") + 1] if "--src" in args else DEFAULT_SRC

    if not os.path.exists(src):
        print(f"❌ file video tidak ada: {src}")
        return 1
    print(f"   sumber: {src} ({os.path.getsize(src)} bytes)")

    os.makedirs(IMG_DIR, exist_ok=True)
    dst_raw = os.path.join(IMG_DIR, RAW_NAME)
    dst_v = os.path.join(IMG_DIR, VIDEO_NAME)
    dst_t = os.path.join(IMG_DIR, THUMB_NAME)

    # --- salinan asli (landscape) ---
    if not os.path.exists(dst_raw):
        shutil.copy2(src, dst_raw)
        print(f"✅ salinan asli → {dst_raw}")

    # --- versi 9:16 blur-pad (disetujui Bos 15 Sep 2026) ---
    if not os.path.exists(dst_v):
        subprocess.run(
            ["ffmpeg", "-v", "error", "-y", "-i", dst_raw, "-filter_complex", BLUR_FILTER,
             "-c:v", "libx264", "-preset", "medium", "-crf", "23", "-maxrate", "3M",
             "-bufsize", "6M", "-profile:v", "high", "-level", "4.1", "-pix_fmt",
             "yuv420p", "-an", "-movflags", "+faststart", dst_v], check=True)
        print(f"✅ 9:16 blur-pad → {dst_v}")
    if not os.path.exists(dst_t):
        subprocess.run(["ffmpeg", "-v", "error", "-y", "-ss", str(THUMB_AT), "-i", dst_v,
                        "-frames:v", "1", "-vf", "scale=1080:1920", "-q:v", "3", dst_t],
                       check=True)
        print(f"✅ thumbnail → {dst_t} {Image.open(dst_t).size}")
    Image.open(dst_t).verify()

    pr = subprocess.run(["ffprobe", "-v", "error", "-show_entries",
                         "format=size,duration,bit_rate", "-show_entries",
                         "stream=width,height,codec_name", "-of",
                         "default=noprint_wrappers=1", dst_v],
                        capture_output=True, text=True)
    info = " ".join(pr.stdout.split())
    print("   ffprobe:", info)
    size_mb = os.path.getsize(dst_v) / 1024 / 1024
    print(f"   ukuran: {size_mb:.1f} MB")
    if size_mb > 40:
        print("❌ video > 40 MB — encode ulang dulu (pitfall VIDEO BESAR/HEVC)")
        return 1
    if "hevc" in info.lower():
        print("❌ masih HEVC — Repliz gagal unduh, encode H.264 dulu")
        return 1

    url_v = f"{IMG_BASE_URL}/openclaw-img/{VIDEO_NAME}"
    url_t = f"{IMG_BASE_URL}/openclaw-img/{THUMB_NAME}"
    print(f"   video : {url_v}\n   thumb : {url_t}")
    print("🔎 verifikasi jalur INTERNET (2 ingress)...")
    if not (verify_url(url_v) and verify_url(url_t)):
        print("❌ URL belum 200 di semua ingress — STOP")
        return 1

    tags = re.findall(r"#(\w+)", CAPTION)
    bad = [t for t in tags if t != t.lower()]
    print(f"   caption {len(CAPTION)} char | hashtag {len(tags)} | kapital: {bad or 'tidak ada'}")
    if bad:
        print("❌ ada hashtag huruf besar")
        return 1

    client = ReplizClient()
    rows = dojo_media(client)
    live = [m for m in rows if m["base"] == VIDEO_NAME.lower() and m["status"] in LIVE]
    if live:
        print(f"ℹ️  media sudah terjadwal ({[m['status'] for m in live]}) → SKIP create")
        for m in live:
            print("   ", m["id"], m["scheduleAt"])
        return 0

    slot = next_slot(rows)
    sched_at = slot.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.000Z")
    print(f"   slot: {slot.strftime('%d %b %Y %H:%M WIB')} → {sched_at}")

    if not sched:
        print("🧪 DRY RUN — tambahkan --schedule untuk create")
        return 0

    r = client.create_schedule(
        ACC.DOJO_KSATRIA_IG, CAPTION, sched_at,
        title="Reels Dojo Ksatria — Timotius Arjuna (sudut biru, taekwondo Surabaya)",
        topic="Taekwondo", type_="video",
        medias=[{"type": "video", "url": url_v, "thumbnail": url_t}],
        replies=[],
    )
    sid = r.get("scheduleId") or r.get("_id") or r.get("id")
    print(f"   create → {r}")
    if not sid:
        log(f"❌ create GAGAL (Timotius Arjuna): {str(r)[:200]}")
        return 1
    log(f"✅ {VIDEO_NAME} (Timotius Arjuna, sudut biru) → {sid} | {sched_at} "
        f"({slot.strftime('%d %b %Y 09:00 WIB')})")

    hits = [m for m in dojo_media(client) if m["base"] == VIDEO_NAME.lower()]
    print(f"🔁 verifikasi ulang: {len(hits)} jadwal dgn media {VIDEO_NAME}")
    for m in hits:
        print("   ", m["id"], m["status"], m["scheduleAt"])
    return 0 if len(hits) == 1 else 1


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