#!/usr/bin/env python3
"""
Pipeline generik publish artikel harian multi-website (versi Python-module).
Konten/config dibaca dari file .py (Python literal) -> tanpa masalah escape JSON.
Alur: gambar Pexels -> upload featured -> kategori -> tags -> Yoast -> jadwal 09:00 WIB -> log.

Pemakaian: python3 pipeline_artikel_harian.py <config.py>
"""
import json, os, base64, urllib.request, io, re, sys, urllib.parse, urllib.error, importlib.util
from datetime import datetime, timedelta, timezone
from PIL import Image

def load_config(path):
    spec = importlib.util.spec_from_file_location("art_cfg", path)
    mod = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(mod)
    return mod.CFG

def wp_request(domain, user, pw, endpoint, method="GET", data=None, timeout=45):
    auth = base64.b64encode(f"{user}:{pw}".encode()).decode()
    url = f"https://{domain}/wp-json/wp/v2/{endpoint}"
    body = json.dumps(data).encode() if data else None
    h = {"Authorization": f"Basic {auth}", "Content-Type": "application/json", "User-Agent": "StudioBot/1.0"}
    req = urllib.request.Request(url, data=body, headers=h, method=method)
    try:
        with urllib.request.urlopen(req, timeout=timeout) as r:
            return json.loads(r.read())
    except urllib.error.HTTPError as e:
        try:
            print(f"  HTTP {e.code}: {e.read().decode()[:250]}")
        except Exception:
            print(f"  HTTP {e.code}")
        return None
    except Exception as e:
        print(f"  Error: {e}")
        return None

def ensure_term(domain, user, pw, taxonomy, name):
    r = wp_request(domain, user, pw, f"{taxonomy}?per_page=100&orderby=name")
    items = r or []
    for it in items:
        if it.get("name","").lower() == name.lower():
            return it["id"]
    new = wp_request(domain, user, pw, taxonomy, "POST", {"name": name})
    if new and "id" in new:
        return new["id"]
    return None

def upload_image(domain, user, pw, url, filename):
    try:
        import requests as _req
        r = _req.get(url, headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36","Referer":"https://www.pexels.com/"}, timeout=45)
        r.raise_for_status()
        raw = r.content
        img = Image.open(io.BytesIO(raw)).convert("RGB")
        tw, th = 1000, 567
        w, h = img.size
        ratio = tw/th
        if w/h > ratio:
            nh, nw = h, int(h*ratio)
        else:
            nw, nh = w, int(w/ratio)
        img2 = img.resize((nw, nh), Image.LANCZOS)
        left=(nw-tw)//2; top=(nh-th)//2
        img2 = img2.crop((left, top, left+tw, top+th))
        buf = io.BytesIO(); img2.save(buf,"JPEG",quality=90)
        data = buf.getvalue()
        auth = base64.b64encode(f"{user}:{pw}".encode()).decode()
        u = f"https://{domain}/wp-json/wp/v2/media"
        h = {"Authorization":f"Basic {auth}",
             "Content-Disposition":f'attachment; filename="{filename}"',
             "Content-Type":"image/jpeg"}
        req2 = urllib.request.Request(u, data=data, headers=h, method="POST")
        with urllib.request.urlopen(req2, timeout=60) as r2:
            res = json.loads(r2.read())
        return res["id"], res["source_url"]
    except Exception as e:
        print(f"  Image error: {e}")
        return None, None

def build_html(konten, cta_title, cta_desc, wa_link, cta_text, home_url):
    parts=[]
    for s in konten:
        t=s["type"]
        if t=="p":
            parts.append(f'<p>{s["t"]}</p>')
        elif t=="h2":
            parts.append(f'<h2 class="wp-block-heading">{s["t"]}</h2>')
        elif t=="ul":
            li = "".join(f'<li>{x}</li>' for x in s["items"])
            parts.append(f'<ul>{li}</ul>')
    cta = f'''
<!-- wp:separator --><hr class="wp-block-separator has-alpha-channel-opacity"/><!-- /wp:separator -->
<!-- wp:heading {{"textAlign":"center"}} --><h2 class="wp-block-heading has-text-align-center">{cta_title}</h2><!-- /wp:heading -->
<!-- wp:paragraph {{"align":"center"}} --><p class="has-text-align-center">{cta_desc}</p><!-- /wp:paragraph -->
<!-- wp:buttons {{"layout":{{"type":"flex","justifyContent":"center"}}}} -->
<div class="wp-block-buttons">
<!-- wp:button {{"backgroundColor":"#1E40AF","textColor":"white","className":"is-style-fill"}} -->
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-white-color has-text-color has-background has-link-decoration wp-element-button" href="{wa_link}" style="background-color:#1E40AF;" target="_blank" rel="noreferrer noopener"><strong>💬 {cta_text}</strong></a></div>
<!-- /wp:button -->
</div>
<!-- /wp:buttons -->
<!-- wp:paragraph {{"align":"center"}} --><p class="has-text-align-center">Atau kunjungi <strong><a href="{home_url}">{home_url.replace("https://","")}</a></strong> untuk info lebih lanjut</p><!-- /wp:paragraph -->
'''
    parts.append(cta)
    return "\n".join(parts)

def main():
    cfg = load_config(sys.argv[1])
    dom = cfg["domain"]; user=cfg["user"]; pw=cfg["pass"]
    art = cfg["article"]
    print(f"\n{'='*62}\n📝 [{cfg['label']}] {art['judul']}\n{'='*62}")

    # kategori
    cat_ids=[]
    cats = wp_request(dom,user,pw,"categories?per_page=100&_fields=id,name") or []
    name_to_id = {c["name"].lower(): c["id"] for c in cats}
    for name in art.get("categories",[]):
        cid = name_to_id.get(name.lower())
        if cid: cat_ids.append(cid)
    print(f"   Kategori: {cat_ids}")

    # tags
    tag_ids=[]
    for name in art.get("tags",[]):
        tid = ensure_term(dom,user,pw,"tags",name)
        if tid: tag_ids.append(tid)
    print(f"   Tags: {tag_ids}")

    # featured
    img_id,img_url = upload_image(dom,user,pw, art["image_url"], art["slug"]+".jpg")

    # content
    wa_link = f"https://wa.me/{cfg['wa_number']}?text={urllib.parse.quote(cfg['wa_text'])}"
    content = build_html(art["content"], art["cta_title"], art["cta_desc"], wa_link, art["cta_text"], cfg["home_url"])
    wc = len(re.sub(r'<[^>]+>','',content).split())
    print(f"   ~{wc} kata")

    # jadwal: besok jam 09:00 WIB
    local = datetime.now(timezone.utc)+timedelta(hours=7)
    target = local.replace(hour=9,minute=0,second=0,microsecond=0)
    if target <= local:
        target = target + timedelta(days=1)
    gmt = target - timedelta(hours=7)
    date_local_s = target.strftime("%Y-%m-%dT%H:%M:%S")
    date_gmt_s = gmt.strftime("%Y-%m-%dT%H:%M:%S")
    print(f"   Jadwal tayang: {date_local_s} WIB")

    post_data = {
        "title": art["judul"], "slug": art["slug"], "content": content,
        "status": "future", "date": date_local_s, "date_gmt": date_gmt_s,
        "categories": cat_ids, "tags": tag_ids,
        "meta": {
            "_yoast_wpseo_title": f"{art['judul']} | {cfg['brand']}",
            "_yoast_wpseo_metadesc": art["meta_desc"],
            "_yoast_wpseo_focuskw": art["focus_kw"],
            "_yoast_wpseo_meta-robots-noindex":"0",
            "_yoast_wpseo_meta-robots-nofollow":"0",
            "_yoast_wpseo_opengraph-title": art["judul"],
            "_yoast_wpseo_opengraph-description": art["meta_desc"],
        },
    }
    if img_id: post_data["featured_media"]=img_id

    # ── GUARD ANTI-DUPLIKAT (kuat) ────────────────────────────────────────
    # Cek: apakah domain ini sudah punya post publish/future untuk TANGGAL
    # SASARAN (berapa pun slug/judulnya). Kalau sudah ada -> SKIP, jangan
    # publish ganda. Mencegah artikel dobel walau isi config berbeda tiap run.
    target_date = date_local_s[:10]            # contoh '2026-08-12'
    existing = wp_request(dom,user,pw,
        f"posts?status=publish,future,draft&per_page=100&_fields=id,slug,title,date") or []
    dup = None
    for ex in existing:
        if str(ex.get("date",""))[:10] == target_date:
            dup = ex
            break
    if dup:
        print(f"   ⚠️ SKIP: {dom} sudah punya post ID {dup.get('id')} ({dup.get('slug')}) utk {target_date} — anti-duplikat")
        return False
    # ── /GUARD ──────────────────────────────────────────────────────────────

    res = wp_request(dom,user,pw,"posts","POST",post_data)
    if res and "id" in res:
        print(f"   ✅ BERHASIL ID {res['id']} | link {res.get('link')} | status {res.get('status')}")
        log_f = os.path.join(os.path.dirname(__file__),"log_pipeline_harian.jsonl")
        with open(log_f,"a") as f:
            f.write(json.dumps({"date":date_gmt_s,"domain":dom,"label":cfg['label'],"id":res['id'],"link":res.get('link'),"judul":art['judul'],"slug":art['slug'],"words":wc})+ "\n")
        return True
    print("   ❌ GAGAL")
    return False

if __name__=="__main__":
    main()
