#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""TS Law — perbaiki carousel yang media-nya tidak bertipe "image".

Temuan: carousel 14 Okt gagal di IG & Threads dengan pesan "The parameter
image_url is required". Setelah dibandingkan, carousel yang BERHASIL (24 Sep,
8 Okt) punya medias[].type = "image" + alt terisi; carousel yang gagal dan
SEMUA carousel terjadwal 24 Okt-2 Nov punya type = "" dan alt = "".
Jadi 15 jadwal carousel ke depan berisiko gagal dengan sebab yang sama.

Yang dikerjakan:
  1. Semua carousel TS Law pending (>= 19 Okt): medias diisi type "image",
     alt = nama berkas tanpa ekstensi. URL tidak diubah.
  2. Carousel 14 Okt yang tidak tayang di IG & Threads dijadwalkan ulang
     ke Rabu 21 Okt 09:00 WIB (02:00Z). FB 14 Okt sudah tayang, tidak disentuh.

Pakai: python3 perbaiki_album_tslaw_18okt.py         (dry run)
       python3 perbaiki_album_tslaw_18okt.py --run   (eksekusi)
"""
import json
import subprocess
import sys
import urllib.parse
import urllib.request
from datetime import datetime, timezone

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

ACC = {"6a76a54d62caae1e04f30968": "IG", "6a35f8b7c5ff4ce3a322b2ed": "TH",
       "6a3b41d1c5ff4ce3a32753e8": "FB", "6a60101562caae1e04e901ac": "LI"}
GAGAL_14 = {"6ac35397173307838558141e": "IG", "6ac3539707008e0e9104842f": "TH"}
TUJUAN_14 = "2026-10-21T02:00:00.000Z"   # Rabu 21 Okt 09:00 WIB
MODE = "run" if "--run" in sys.argv else "dry"


def semua_jadwal():
    docs, page = [], 1
    while True:
        q = urllib.parse.urlencode({"page": page, "limit": 100})
        req = urllib.request.Request(f"{BASE}/public/schedule?{q}", headers=HEADERS)
        with urllib.request.urlopen(req, timeout=60) as r:
            d = json.load(r)
        b = d.get("docs", d.get("data", []))
        docs += b
        if not d.get("hasNextPage") or not b:
            break
        page += 1
    return docs


def url_hidup(url, cache={}):
    if url in cache:
        return cache[url]
    r = subprocess.run(["curl", "-4", "-s", "-o", "/dev/null", "-w", "%{http_code}",
                        "--max-time", "40", "-I", url], capture_output=True, text=True)
    cache[url] = r.stdout.strip()
    return cache[url]


def rapikan_medias(medias):
    baru = []
    for m in medias or []:
        url = str(m.get("url") or "")
        fn = url.split("/")[-1]
        baru.append({
            "url": url,
            "type": "image",
            "alt": fn.rsplit(".", 1)[0],
            "customThumbnail": bool(m.get("customThumbnail")),
            "thumbnail": m.get("thumbnail") or "",
        })
    return baru


cl = get_client()
now = datetime.now(timezone.utc).isoformat()
docs = semua_jadwal()
kerjakan = []
for s in docs:
    a = ACC.get(str(s.get("accountId")))
    if not a or s.get("type") != "album":
        continue
    sid = str(s.get("_id"))
    status = s.get("status")
    at = str(s.get("scheduleAt") or "")
    if sid in GAGAL_14:
        kerjakan.append((a, sid, status, at, TUJUAN_14, "tayang ulang 21 Okt"))
    elif status == "pending" and at >= "2026-10-19":
        kerjakan.append((a, sid, status, at, None, "rapikan media"))
    elif status == "error" and at >= "2026-10-01":
        print(f"⚠️  carousel error lain: {a} {sid} {at[:16]} {str(s.get('title'))[:40]} "
              f"| {str(s.get('errorMessage'))[:60]}")

print(f"{len(kerjakan)} carousel akan diproses")
gagal = 0
for a, sid, status, at, at_baru, kenapa in sorted(kerjakan, key=lambda x: x[3]):
    asli = cl.get_schedule(sid)
    medias = rapikan_medias(asli.get("medias"))
    mati = [m["url"].split("/")[-1] for m in medias if url_hidup(m["url"]) != "200"]
    label = f"{a:2s} {sid} {at[:16]} ({status}) n={len(medias)} {kenapa}"
    if mati:
        print(f"❌ {label} → media tidak 200: {mati} → SKIP")
        gagal += 1
        continue
    if at_baru:
        bentrok = [x for x in docs if str(x.get("accountId")) == asli.get("accountId")
                   and str(x.get("scheduleAt", "")).startswith(at_baru[:16]) and str(x.get("_id")) != sid]
        if bentrok:
            print(f"❌ {label} → slot {at_baru} sudah dipakai {bentrok[0].get('_id')} → SKIP")
            gagal += 1
            continue
    print(f"{'✅' if MODE == 'run' else '[DRY]'} {label}"
          + (f" → {at_baru[:16]}Z" if at_baru else ""))
    if MODE != "run":
        continue
    ubah = {"medias": medias}
    if at_baru:
        ubah["scheduleAt"] = at_baru
    cl.update_schedule(sid, ubah)
    back = cl.get_schedule(sid)
    tipe = sorted({str(m.get("type")) for m in (back.get("medias") or [])})
    print(f"   baca-balik: {back.get('scheduleAt')} status={back.get('status')} "
          f"n={len(back.get('medias') or [])} types={tipe} "
          f"alt0={(back.get('medias') or [{}])[0].get('alt')}")

print(f"\nselesai · gagal {gagal}")
