#!/usr/bin/env python3
"""No 4: tambah link internal untuk artikel yang belum punya satu pun.
Target dipilih dari kemiripan topik (judul + slug). Idempoten. Dry run default."""
import base64, html, json, re, sys, time, urllib.request, urllib.error

S = "https://studiosoft.id"
AUTH = base64.b64encode(b"bambangbot:q26r RePo BVy6 pwU2 F3z7 ouyl").decode()
STOP = set("dan yang untuk dari dengan pada di ke ini itu bisa gak tidak para atau juga akan ada adalah ".split())


def api(path, data=None):
    h = {"Authorization": f"Basic {AUTH}", "User-Agent": "Mozilla/5.0"}
    body = None
    if data is not None:
        body = json.dumps(data).encode(); h["Content-Type"] = "application/json"
    r = urllib.request.Request(S + path, data=body, headers=h, method="POST" if data else "GET")
    err = None
    for _ in range(3):
        try:
            with urllib.request.urlopen(r, timeout=240) as x:
                return x.status, json.loads(x.read())
        except urllib.error.HTTPError as e:
            if e.code in (404, 500, 502, 503, 504):
                time.sleep(3); continue
            return e.code, e.read().decode()[:200]
        except Exception as e:
            time.sleep(3); err = e
    return 0, str(err)[:150] if err else 'gagal setelah 3 percobaan'


posts, page = [], 1
while True:
    st, d = api(f"/wp-json/wp/v2/posts?per_page=100&page={page}&context=edit&_fields=id,link,slug,title,content")
    if not isinstance(d, list):
        break
    posts += d
    if len(d) < 100:
        break
    page += 1
print(f"artikel: {len(posts)}")


def tok(s):
    return {w for w in re.findall(r"[a-zA-Z]{4,}", html.unescape(s).lower()) if w not in STOP}


peta = {p["id"]: {"judul": html.unescape(p["title"]["rendered"]), "link": p["link"],
                  "tok": tok(p["title"]["rendered"] + " " + p["slug"]), "isi": p["content"]["raw"]} for p in posts}

RENCANA = {}
for pid, d in peta.items():
    keluar = set(re.findall(r'href="https://studiosoft\.id/([^"#?]+)', d["isi"]))
    if keluar:
        continue
    skor = []
    for pid2, d2 in peta.items():
        if pid2 == pid:
            continue
        s = len(d["tok"] & d2["tok"])
        if s >= 2:
            skor.append((s, pid2))
    skor.sort(reverse=True)
    if not skor:
        continue
    RENCANA[pid] = [(pid2, peta[pid2]["judul"], peta[pid2]["link"]) for _, pid2 in skor[:3]]

print(f"artikel tanpa link internal: {sum(1 for d in peta.values() if not re.search(r'href=.https://studiosoft', d['isi']))}")
print(f"yang bisa diberi link dari kemiripan topik: {len(RENCANA)}\n")
for pid, target in list(RENCANA.items())[:10]:
    print(f"  #{pid} {peta[pid]['judul'][:48]}")
    for tid, judul, _ in target:
        print(f"      → #{tid} {judul[:56]}")

if "--apply" not in sys.argv:
    print("\n(dry run — pakai --apply untuk eksekusi)")
    sys.exit(0)

ok = gagal = 0
for i, (pid, target) in enumerate(RENCANA.items(), 1):
    isi = peta[pid]["isi"]
    item = [f'<li><a href="{link}">{judul}</a></li>' for _, judul, link in target if link not in isi]
    if not item:
        continue
    blok = "\n<h2>Baca juga</h2>\n<ul>" + "\n".join(item) + "</ul>\n"
    m = re.search(r"\n<h2[^>]*>\s*(FAQ|Pertanyaan|Kesimpulan)", isi, re.I)
    baru = (isi[:m.start()] + blok + isi[m.start():]) if m else (isi.rstrip() + "\n" + blok)
    st, _ = api(f"/wp-json/wp/v2/posts/{pid}", {"content": baru})
    _, chk = api(f"/wp-json/wp/v2/posts/{pid}?context=edit&_fields=content")
    jadi = isinstance(chk, dict) and "Baca juga</h2>" in chk.get("content", {}).get("raw", "")
    ok += 1 if jadi else 0
    gagal += 0 if jadi else 1
    if i % 10 == 0 or i == len(RENCANA):
        print(f"  progres {i}/{len(RENCANA)} | sukses {ok} | gagal {gagal}")
print(f"\nselesai: {ok} berhasil | {gagal} gagal")
