#!/usr/bin/env python3
"""Schedule FB DAS Bengkel Indonesia — 11 Sep 2026
Cron fb-das-harian jalan 10:00 UTC = 17:00 WIB → slot 17:00 WIB sudah LEWAT saat script jalan
→ pakai slot KOSONG berikutnya hari ini: 20:00 WIB (13:00 UTC) — preseden schedule_das_fb_20260901..10.py.

Artikel: https://dasindonesia.com/bengkel-premium-terbaik-di-surabaya-ciri-layanan-dan-cara-memilih-yang-tepat
- LIVE (HTTP 200, dicek 11 Sep 2026 via curl langsung — WP REST host ini lambat tapi jalan)
- BELUM pernah dipakai: diff 205 artikel live vs 58 link terpakai (post_das_fb_history.json + seluruh
  jadwal akun DAS FB SEMUA status) → 145 kandidat bersih; slug ini 0 hit (cek_slug_das_fb.py, scan 3976 jadwal)
- Prompt menawarkan penyebab-mesin-mobil-overheat & kapan-mobil-perlu-engine-overhaul, tapi KEDUANYA SUDAH
  terpakai (overheat 16 Jul, overhaul 8 Sep) → pilih artikel live & bersih lain.

Format: image 1080x1350 (bg #1a1a2e, teks putih, aksen #f97316) + caption 3 paragraf + link + pancingan
diskusi (tone netral, diskusi_engine otomotif).
Aturan DAS: NO kata harga/biaya/murah/mahal/hemat; 0 mention internal; 0 hashtag (pola Sep 2026).
"""
import json, os, re, sys, subprocess, time, urllib.request, urllib.error

from repliz_client import upload_image_to_server, HEADERS, BASE, ACC

FB_DAS_ID = ACC.DAS_FB  # 6a3b41e1c5ff4ce3a327543e
LOG_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'post_das_fb_history.json')
IMG_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'das_fb_20260911.png')
ARTICLE_URL = "https://dasindonesia.com/bengkel-premium-terbaik-di-surabaya-ciri-layanan-dan-cara-memilih-yang-tepat"

TGL = "2026-09-11"
JAM_WIB = "20:00"
schedule_iso = "2026-09-11T13:00:00.000Z"   # 20:00 WIB

CAPTION = """Banyak mobil premium "sakit" bukan karena usia, tapi karena salah penanganan. Sebagian pemilik mobil kelas atas baru sadar satu hal setelah masalahnya membesar: yang menentukan mesin awet atau cepat rusak bukan merek mobilnya, tapi siapa yang menyentuh mesin itu.

Bengkel premium sejati bukan soal gedung megah atau nama besar. Standarnya ada di cara kerja: diagnosis sebelum bongkar, pengukuran presisi dengan compression tester, scan tool, torque wrench, dan micrometer, alur kerja yang jelas dari diagnosis sampai serah terima, serta teknisi yang paham betul prinsip kerja piston, ring, crankshaft, hingga sistem timing.

Kalau Anda ingin menilai sendiri bengkel yang tepat untuk mobil kesayangan, kami sudah rangkum 6 cirinya — plus daftar pertanyaan yang wajib Anda tanyakan sebelum menyerahkan mobil — di artikel berikut:
""" + ARTICLE_URL + """

Apa yang paling Anda pertimbangkan saat memilih bengkel? Share dong."""


def load_history():
    if os.path.exists(LOG_FILE):
        with open(LOG_FILE) as f:
            return json.load(f)
    return {'posts': []}


def is_duplicate(history, article_url):
    for p in history['posts']:
        if (p.get('article_url') or '').rstrip('/') == article_url.rstrip('/'):
            return True
    return False


def scan_account(day):
    """Semua jadwal akun DAS FB: (pending hari ini) + set link yang pernah dipakai."""
    pend, used = [], set()
    page = 1
    while True:
        req = urllib.request.Request(f'{BASE}/public/schedule?page={page}&limit=100',
                                     headers=HEADERS, method='GET')
        with urllib.request.urlopen(req, timeout=60) as r:
            data = json.loads(r.read())
        for d in data.get('docs', []):
            if d.get('accountId') != FB_DAS_ID:
                continue
            for l in re.findall(r'https?://dasindonesia\.com[^\s]*', (d.get('description') or '')):
                used.add(l.rstrip('/'))
            if d.get('status') in ('pending', 'draft') and (d.get('scheduleAt') or '').startswith(day):
                pend.append((d.get('scheduleAt'), d.get('_id')))
        if page >= data.get('totalPages', 1):
            break
        page += 1
    return pend, used


def verify_caption(cap):
    banned = ['harga', 'biaya', 'murah', 'mahal', 'hemat', 'juta', 'rupiah']
    n_par = len([x for x in cap.split('\n\n') if x.strip()])
    checks = {
        '0 mention @': not re.search(r'@\w+', cap),
        'ada link dasindonesia (link == artikel)': ARTICLE_URL in cap,
        'ada ajakan diskusi': any(w in cap.lower() for w in ['komentar', 'diskusi', 'pendapat', 'menurut', 'share']),
        'tanpa kata harga/biaya': not any(w in cap.lower() for w in banned),
        'paragraf >= 2': n_par >= 2,
        'paragraf <= 4': n_par <= 4,
        'tidak ada hashtag huruf besar': not any(t != t.lower() for t in re.findall(r'#(\w+)', cap)),
    }
    for k, v in checks.items():
        print(f"   [{'✅' if v else '❌'}] {k}")
    print(f"   (paragraf: {n_par}, panjang caption: {len(cap)} char)")
    return all(checks.values())


def main():
    history = load_history()
    pend, used = scan_account(TGL)
    print(f"  DAS FB pending {TGL}: {pend if pend else 'TIDAK ADA'}")
    if pend:
        print("❌ Sudah ada jadwal DAS FB hari ini — batal, jangan double-book")
        sys.exit(1)

    if is_duplicate(history, ARTICLE_URL):
        print(f"❌ Artikel sudah pernah dipakai di history: {ARTICLE_URL}")
        sys.exit(1)
    if ARTICLE_URL.rstrip('/') in used:
        print(f"❌ Artikel sudah pernah dipakai di akun DAS FB (Repliz): {ARTICLE_URL}")
        sys.exit(1)
    print(f"✅ Artikel layak dipakai (0 hit history + 0 hit Repliz semua status, {len(used)} link terpakai): {ARTICLE_URL}")

    # link artikel harus LIVE (dasindonesia.com lambat dari host ini → timeout besar + retry)
    code = "000"
    for _ in range(3):
        code = subprocess.run(
            ["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", "--max-time", "120",
             "-A", "Mozilla/5.0", ARTICLE_URL + "/"],
            capture_output=True, text=True).stdout.strip()
        if code == "200":
            break
    print(f"   Artikel HTTP: {code}")
    if code != "200":
        print("❌ Artikel tidak live (bukan 200) — batal")
        sys.exit(1)

    if not verify_caption(CAPTION):
        print("❌ Caption gagal verifikasi — batal")
        sys.exit(1)

    if not os.path.exists(IMG_PATH):
        print(f"❌ Gambar tidak ada: {IMG_PATH}")
        sys.exit(1)

    img_url = upload_image_to_server(IMG_PATH)
    print(f"   Image URL: {img_url}")
    if not img_url:
        print("❌ Upload image gagal — batal")
        sys.exit(1)

    ok_ingress = False
    for ip in ("103.84.155.153", "103.84.155.217"):
        code = subprocess.run(
            ["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", "--max-time", "25",
             "--resolve", f"mantapserver.tail3947bb.ts.net:443:{ip}", img_url],
            capture_output=True, text=True).stdout
        print(f"   Ingress {ip}: HTTP {code}")
        if code == "200":
            ok_ingress = True
    code_local = subprocess.run(
        ["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", "--max-time", "15", img_url],
        capture_output=True, text=True).stdout
    print(f"   Local fetch: HTTP {code_local}")
    if not ok_ingress:
        print("❌ URL gambar tidak bisa diakses via ingress funnel — batal (Repliz ambil dari internet)")
        sys.exit(1)

    payload = {
        'title': '',
        'description': CAPTION,
        'topic': 'Otomotif',
        'type': 'image',
        'medias': [{'url': img_url, 'type': 'image'}],
        'meta': {'title': '', 'description': '', 'url': ''},
        'additionalInfo': {
            'isAiGenerated': False, 'isDraft': False,
            'collaborators': [], 'mentions': [],
            'music': {'id': '', 'artist': '', 'name': '', 'thumbnail': ''},
            'products': [], 'tags': []
        },
        'replies': [],
        'accountId': FB_DAS_ID,
        'scheduleAt': schedule_iso,
    }
    print(f"   Schedule: {TGL} {JAM_WIB} WIB ({schedule_iso})")

    body = json.dumps(payload).encode()
    req = urllib.request.Request(f'{BASE}/public/schedule', data=body, headers=HEADERS, method='POST')
    try:
        with urllib.request.urlopen(req, timeout=60) as r:
            result = json.loads(r.read())
        sid = result.get('scheduleId') or result.get('_id') or result.get('id') or '?'
        print(f"✅ SCHEDULED — Schedule ID: {sid}")

        time.sleep(4)
        ver, _ = scan_account(TGL)
        print(f"   Verifikasi pending DAS FB {TGL}: {ver}")
        if not ver:
            print("❌ Tidak ketemu jadwal pending di API — cek manual, jangan catat history dulu")
            sys.exit(1)
        if len(ver) > 1:
            print(f"⚠️  Ada {len(ver)} pending hari ini — cek duplikat!")
        if sid == '?':
            sid = ver[0][1]

        history['posts'].append({
            'date': TGL,
            'time': JAM_WIB,
            'platform': 'facebook',
            'article_url': ARTICLE_URL,
            'short_desc': CAPTION.split('\n\n')[0][:100],
            'schedule_id': sid,
            'image_source': 'openclaw-img',
        })
        with open(LOG_FILE, 'w') as f:
            json.dump(history, f, indent=2, ensure_ascii=False)
        print(f"   History dicatat: {LOG_FILE}")
        print(f"   Total posts: {len(history['posts'])}")
    except urllib.error.HTTPError as e:
        err = e.read().decode()
        print(f"❌ ERROR {e.code}: {err[:500]}")
        sys.exit(1)


if __name__ == '__main__':
    main()
