#!/usr/bin/env python3
"""TSLaw: buat artikel kesembilanbelas (draft) - Notaris dan PPAT di Surabaya.
Tahapan: siapkan foto (crop 1000x567 webp) -> cek semua tautan internal 200 -> cek kanibalisasi ->
unggah media + alt -> buat post draft (REST, JSON) -> meta Yoast (REST) -> verifikasi baca ulang.
Jalankan tanpa argumen = dry run; dengan --apply = benar-benar membuat di WordPress."""
import base64, json, os, re, sys, time, urllib.request, urllib.error

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from tslaw_listikel_19 import A19

DOM = "tslaw.id"
USER, PASS = "bambangbot", "EFKm EYGx VQCP Y9go ncPr uM2Y"
AUTH = base64.b64encode(f"{USER}:{PASS}".encode()).decode()
UA = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124 Safari/537.36"}
OUT = "/home/mantapman/.hermes/profiles/atun/workspace/tslaw_listikel"
KATEGORI = [14]          # Hukum Bisnis
FOTO_ID = "7651557"      # Pexels: dua orang memeriksa dokumen di ruang pelayanan
FOTO_YBIAS = 0.35
SALINAN = f"{OUT}/artikel19.html"
ALT = ("Dua orang memeriksa berkas akta dan sertifikat di ruang pelayanan, gambaran urusan notaris dan PPAT "
       "di Surabaya")


def rest(path, method="GET", data=None):
    h = {"Authorization": f"Basic {AUTH}", **UA}
    body = None
    if data is not None:
        body = json.dumps(data).encode()
        h["Content-Type"] = "application/json"
    r = urllib.request.Request(f"https://{DOM}{path}", data=body, headers=h, method=method)
    for i in range(4):
        try:
            with urllib.request.urlopen(r, timeout=180) as x:
                return x.status, json.loads(x.read())
        except urllib.error.HTTPError as e:
            return e.code, e.read().decode()[:300]
        except Exception as e:
            print(f"    (ulang {i+1}: {str(e)[:60]})")
            time.sleep(8)
    return 0, "gagal"


def potong_foto(pexels_id, nama, ybias=0.0):
    from PIL import Image
    u = f"https://images.pexels.com/photos/{pexels_id}/pexels-photo-{pexels_id}.jpeg?auto=compress&cs=tinysrgb&w=1600"
    data = urllib.request.urlopen(urllib.request.Request(u, headers=UA), timeout=120).read()
    tmp = f"{OUT}/_tmp_{nama}.jpg"
    open(tmp, "wb").write(data)
    im = Image.open(tmp).convert("RGB")
    tw, th = 1000, 567
    w, h = im.size
    r = tw / th
    if w / h > r:
        cw = int(h * r); x0 = (w - cw) // 2
        im = im.crop((x0, 0, x0 + cw, h))
    else:
        ch = int(w / r); y0 = int((h - ch) * ybias)
        im = im.crop((0, y0, w, y0 + ch))
    f = f"{OUT}/{nama}"
    im.resize((tw, th), Image.LANCZOS).save(f, "WEBP", quality=80, method=6)
    os.remove(tmp)
    return f


def hitung(html):
    teks = re.sub(r"<(script|style)[^>]*>.*?</\1>", " ", html, flags=re.S | re.I)
    return len([w for w in re.split(r"\s+", re.sub(r"<[^>]+>", " ", teks)) if w])


def main():
    a = A19
    kata = hitung(a["isi"])
    meta_teks = re.sub(r"\s+", " ", a["meta"])
    print(f"=== PERSIAPAN ===\n  {a['slug']} | {kata} kata | meta {len(meta_teks)} char | judul SEO {len(a['seo'])} char")
    assert 1000 <= kata <= 1300, f"jumlah kata di luar 1000-1300: {kata}"
    assert len(meta_teks) <= 158, "meta lebih dari 158"
    assert a["fokus"] in meta_teks.lower(), "keyphrase tidak ada di meta"
    assert meta_teks.lower().startswith(a["fokus"]), "keyphrase tidak di awal meta"
    assert not re.findall(r"\{[A-Za-z_\[\]0-9]+\}", a["isi"]), "masih ada placeholder"
    assert not re.findall(r"[\u3000-\u9fff\uac00-\ud7af]", a["isi"]), "ada karakter CJK"
    assert chr(8212) not in a["isi"], "ada em dash"
    assert "E0T" not in a["isi"] and "E6T" not in a["isi"], "entri mentah masih tertinggal"
    assert "https://www.tslaw.id/practice-areas/" not in a["isi"], "tautan /practice-areas/ (404) dipakai"
    assert ".htm" not in a["isi"], "ada tautan .htm"
    assert '\"draft\"' not in a["isi"], "menyebut status draft di isi"
    wa = re.findall(r'href="(https://wa\.me/[^"]+)"', a["isi"])
    assert wa and all(re.fullmatch(r"https://wa\.me/\d+(\?[^\s\"]*)?", u) for u in wa), f"tautan WA cacat: {wa}"
    assert os.path.exists(SALINAN), "salinan lokal belum dibuat"
    print(f"  meta final           : {meta_teks}")
    print(f"  tombol WA            : {wa}")
    print(f"  keyphrase di isi     : {a['isi'].lower().count(a['fokus'])} kali")
    print(f"  salinan isi lokal    : {SALINAN} ({os.path.getsize(SALINAN)} byte)")

    print("\n=== CEK TAUTAN INTERNAL ===")
    for u in sorted(set(re.findall(r'href="(https://www\.tslaw\.id/[^"]*)"', a["isi"]))):
        try:
            with urllib.request.urlopen(urllib.request.Request(u, headers=UA), timeout=60) as x:
                ok = x.status
        except urllib.error.HTTPError as e:
            ok = e.code
        except Exception as e:
            ok = f"ERR {str(e)[:40]}"
        print(f"  {ok}  {u}")
        assert ok == 200, f"tautan bukan 200: {u} -> {ok}"

    print("\n=== PENJAGA KANIBALISASI ===")
    semua, off = [], 0
    while off < 300:
        st, p = rest(f"/wp-json/wp/v2/posts?status=publish,future,draft&per_page=100&offset={off}"
                     "&context=edit&_fields=id,slug,title,status,meta")
        if not isinstance(p, list) or not p:
            break
        semua += p
        off += 100
    print(f"  diperiksa: {len(semua)} artikel")
    kata_ku = set(re.sub(r"[^a-z0-9 ]", "", a["fokus"].lower()).split())
    for p in semua:
        m = p.get("meta") or {}
        fk = (m.get("_yoast_wpseo_focuskw") or "").lower().strip()
        t = p["title"]["raw"] if isinstance(p["title"], dict) else str(p["title"])
        if fk and fk == a["fokus"]:
            raise SystemExit(f"  STOP: fokus kata kunci sama dengan #{p['id']} ({fk})")
        kata_p = set(re.sub(r"[^a-z0-9 ]", "", (fk or t).lower()).split())
        if kata_ku and kata_p:
            skor = len(kata_ku & kata_p) / len(kata_ku | kata_p)
            if skor >= 0.34:
                print(f"  tetangga dekat: #{p['id']} skor {skor:.2f} | fokus='{fk}' | {t[:70]}")
    print("  tidak ada fokus kembar")

    foto = potong_foto(FOTO_ID, a["slug"] + ".webp", FOTO_YBIAS)
    from PIL import Image
    print(f"  foto siap            : {foto} ({os.path.getsize(foto)//1024} KB) {Image.open(foto).size}")

    if "--apply" not in sys.argv:
        print("\n(dry run - pakai --apply untuk membuat di WordPress)")
        return

    st, ada = rest(f"/wp-json/wp/v2/posts?slug={a['slug']}&status=any&_fields=id,slug,status,link")
    if isinstance(ada, list) and ada:
        print(f"\n  PERINGATAN: slug sudah ada: {ada} -> hentikan supaya tidak menimpa")
        return
    print(f"\n=== SLUG ===\n  {a['slug']} bebas dipakai")

    st, kat = rest(f"/wp-json/wp/v2/categories?include={','.join(map(str, KATEGORI))}&_fields=id,name,slug")
    if isinstance(kat, list):
        for k in kat:
            print(f"  kategori {k['id']} = {k['name']} ({k['slug']})")

    st, semua_tag = rest("/wp-json/wp/v2/tags?per_page=100&orderby=count&order=desc&_fields=id,name,slug,count")
    peta = {t["name"].lower(): t for t in semua_tag} if isinstance(semua_tag, list) else {}
    print("\n=== TAG ===")
    tag_ids = []
    for nama in a["tag_nama"]:
        t = peta.get(nama.lower())
        if t:
            tag_ids.append(t["id"])
            print(f"  pakai   {nama:<24} #{t['id']} ({t['count']} artikel)")
        else:
            time.sleep(1)
            st, baru = rest("/wp-json/wp/v2/tags", "POST", {"name": nama})
            if isinstance(baru, dict) and "id" in baru:
                tag_ids.append(baru["id"])
                print(f"  buat    {nama:<24} #{baru['id']}")
            elif isinstance(baru, str) and "term_exists" in baru:
                slug = re.sub(r"[^a-z0-9]+", "-", nama.lower()).strip("-")
                st2, cari = rest(f"/wp-json/wp/v2/tags?slug={slug}&_fields=id,name,slug")
                if isinstance(cari, list) and cari:
                    tag_ids.append(cari[0]["id"])
                    print(f"  ada     {nama:<24} #{cari[0]['id']} (lewat slug)")
                else:
                    print(f"  GAGAL   {nama}: term_exists tapi tidak ketemu slug {slug}")
            else:
                print(f"  GAGAL   {nama}: {str(baru)[:120]}")
    print(f"  tag dipakai: {tag_ids}")
    assert len(tag_ids) == 4, f"tag kurang dari 4: {tag_ids}"

    print("\n=== FOTO ===")
    h = {"Authorization": f"Basic {AUTH}", **UA, "Content-Type": "image/webp",
         "Content-Disposition": f'attachment; filename="{a["slug"]}.webp"'}
    req = urllib.request.Request(f"https://{DOM}/wp-json/wp/v2/media", data=open(foto, "rb").read(),
                                 headers=h, method="POST")
    try:
        with urllib.request.urlopen(req, timeout=240) as x:
            med = json.loads(x.read())
    except urllib.error.HTTPError as e:
        print(f"  GAGAL unggah foto: {e.code} {e.read().decode()[:200]}")
        return
    mid = med["id"]
    rest(f"/wp-json/wp/v2/media/{mid}", "POST", {"alt_text": ALT, "title": a["judul"]})
    st, cek = rest(f"/wp-json/wp/v2/media/{mid}?context=edit&_fields=id,alt_text,source_url")
    print(f"  media #{mid} -> {med.get('source_url')}")
    print(f"  alt tersimpan: {'ya' if (isinstance(cek, dict) and cek.get('alt_text') == ALT) else 'TIDAK - ' + str(cek)[:80]}")

    print("\n=== ARTIKEL (draft) ===")
    payload = {"title": a["judul"], "slug": a["slug"], "content": a["isi"], "status": "draft",
               "categories": KATEGORI, "tags": tag_ids, "featured_media": mid, "excerpt": meta_teks}
    st, p = rest("/wp-json/wp/v2/posts", "POST", payload)
    if st not in (200, 201):
        print(f"  GAGAL buat artikel: {st} {str(p)[:300]}")
        return
    pid = p["id"]
    print(f"  artikel #{pid} dibuat -> {p.get('link')}  (status: {p.get('status')})")

    print("\n=== META YOAST ===")
    st, r = rest(f"/wp-json/wp/v2/posts/{pid}", "POST", {"meta": {
        "_yoast_wpseo_focuskw": a["fokus"], "_yoast_wpseo_title": a["seo"],
        "_yoast_wpseo_metadesc": meta_teks}})
    st2, c = rest(f"/wp-json/wp/v2/posts/{pid}?context=edit&_fields=meta")
    m = c.get("meta", {}) if isinstance(c, dict) else {}
    if m.get("_yoast_wpseo_focuskw") == a["fokus"]:
        print(f"  meta Yoast via REST  : tersimpan (HTTP {st}) -> {json.dumps(m, ensure_ascii=False)[:220]}")
    else:
        print(f"  meta Yoast           : REST GAGAL -> {str(m)[:160]}")

    print("\n=== VERIFIKASI (baca ulang via REST) ===")
    st, c = rest(f"/wp-json/wp/v2/posts/{pid}?context=edit&_fields=id,slug,link,status,content,title,"
                 f"categories,tags,featured_media,meta,date,date_gmt")
    raw = c.get("content", {}).get("raw", "") if isinstance(c, dict) else ""
    kata2 = hitung(raw)
    sisa = re.findall(r"\{[A-Za-z_\[\]0-9]+\}", raw)
    cjk = re.findall(r"[\u3000-\u9fff\uac00-\ud7af]", raw)
    taut = len(re.findall(r'href="https://www\.tslaw\.id/', raw))
    htm = re.findall(r'href="(https://www\.tslaw\.id/[^"]*\.htm)"', raw)
    print(f"  #{pid} {c.get('status')} | {len(raw)} char | {kata2} kata")
    print(f"  slug        : {c.get('slug')}  (link: {c.get('link')})")
    print(f"  kategori    : {c.get('categories')} (Hukum Bisnis = 14)")
    print(f"  tag         : {len(c.get('tags', []))} buah -> {c.get('tags')}")
    print(f"  foto utama  : media #{c.get('featured_media')} (harus {mid})")
    print(f"  tombol WA   : {'ada' if 'wa.me/6281909222026' in raw else 'TIDAK'}")
    print(f"  FAQPage     : {'ada' if 'FAQPage' in raw else 'TIDAK'}")
    beranda = 'href="https://www.tslaw.id/"' in raw
    print(f"  beranda TS Law : {'ada' if beranda else 'TIDAK'}")
    print(f"  tautan internal: {taut} tautan ke tslaw.id | .htm tersisa: {len(htm)}")
    print(f"  keyphrase di isi : {raw.lower().count(a['fokus'])} kali")
    print(f"  placeholder sisa : {len(sisa)} {'(BERSIH)' if not sisa else sisa[:5]}")
    print(f"  karakter CJK     : {len(cjk)} {'(BERSIH)' if not cjk else cjk[:5]}")
    print(f"  em dash          : {raw.count(chr(8212))}")
    patah = 0
    for mm in re.finditer(r"<(p|li|h2|h3)(?: [^>]*)?>([^<]*)</\1>", raw):
        for b in mm.group(2).split("\n")[:-1]:
            if b.strip() and not b.rstrip().endswith((".", "!", "?", ":", ";", ",")):
                patah += 1
    print(f"  patahan baris    : {patah} {'(BERSIH)' if not patah else 'PERIKSA'}")
    print(f"  meta tersimpan: {json.dumps(c.get('meta', {}), ensure_ascii=False)[:280]}")
    print(f"\n  LAPORAN: judul={a['judul']}")
    print(f"           url draft={c.get('link')}")
    print(f"           kata={kata2} | keyphrase={a['fokus']} | meta={len(meta_teks)} char")
    json.dump({"id": pid, "link": c.get("link"), "raw": raw, "meta": c.get("meta")},
              open(f"{OUT}/_hasil19.json", "w"), ensure_ascii=False)


if __name__ == "__main__":
    main()
