#!/usr/bin/env python3
"""TSLaw: bangun jaring tautan internal — tiap artikel menautkan 2 artikel paling mirip topiknya.
Pakai --apply untuk menulis; tiap artikel disalin dulu."""
import base64, html, json, os, re, sys, time, urllib.request, urllib.error, importlib.util
from collections import Counter

WS = "/home/mantapman/.hermes/profiles/atun/workspace"
spec = importlib.util.spec_from_file_location("cfg_tslaw", f"{WS}/cfg_tslaw.py")
m = importlib.util.module_from_spec(spec); spec.loader.exec_module(m)
DOM, AUTH = "www.tslaw.id", base64.b64encode(f'{m.CFG["user"]}:{m.CFG["pass"]}'.encode()).decode()
UA = {"User-Agent": "Mozilla/5.0"}
BACKUP = f"{WS}/tslaw_pemulihan/mesh"
os.makedirs(BACKUP, exist_ok=True)
PILAR = "https://www.tslaw.id/law-firm-surabaya/"
STOP = set("yang dan atau untuk pada dari ke di seputar dengan adalah ini itu akan tidak bisa cara panduan "
           "lengkap hukum bisnis usaha anda kita kami para dalam serta agar oleh sebagai lebih juga sudah "
           "masih saja saja tentang bagi tanpa harus apa kapan mengapa bagaimana".split())


def rest(p, 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}{p}", data=body, headers=h, method=method)
    for _ in range(3):
        try:
            with urllib.request.urlopen(r, timeout=200) as x:
                return x.status, json.loads(x.read())
        except urllib.error.HTTPError as e:
            return e.code, e.read().decode()[:200]
        except Exception:
            time.sleep(5)
    return 0, "gagal"


def kata_kunci(teks):
    return {w for w in re.findall(r"[a-z]{4,}", teks.lower()) if w not in STOP}


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

profil = {}
for p in posts:
    judul = re.sub("<[^>]+>", "", p["title"]["raw"])
    profil[p["id"]] = {"slug": p["slug"], "judul": judul,
                       "kunci": kata_kunci(judul + " " + p["slug"]),
                       "url": f"https://{DOM}/{p['slug']}/"}

rencana = []
for p in posts:
    raw = p["content"]["raw"] or ""
    if "Baca juga:" in raw or "BACA JUGA" in raw:
        continue
    skor = []
    for lain_id, lain in profil.items():
        if lain_id == p["id"]:
            continue
        tumpang = len(profil[p["id"]]["kunci"] & lain["kunci"])
        if tumpang >= 3:
            skor.append((tumpang, lain))
    skor.sort(key=lambda x: -x[0])
    pilihan = [s[1] for s in skor[:2]]
    if not pilihan:
        continue
    potongan = ", ".join(f'<a href="{x["url"]}">{x["judul"][:70]}</a>' for x in pilihan)
    tambahan_pilar = ""
    if PILAR not in raw:
        tambahan_pilar = ' dan <a href="' + PILAR + '">panduan memilih law firm Surabaya</a>'
    baris = f"\n<p><strong>Baca juga:</strong> {potongan}{tambahan_pilar}.</p>\n"
    pos = raw.find("<script")
    if pos == -1:
        pos = len(raw)
    baru = raw[:pos].rstrip() + baris + raw[pos:]
    rencana.append({"id": p["id"], "slug": p["slug"], "raw": raw, "baru": baru, "ke": [x["judul"][:40] for x in pilihan]})

print(f"akan ditautkan: {len(rencana)} artikel")
for r in rencana[:12]:
    print(f"   /{r['slug'][:46]:<48} → {r['ke']}")

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

ok = 0
for r in rencana:
    open(f"{BACKUP}/post_{r['id']}.txt", "w").write(r["raw"])
    rest(f"/wp-json/wp/v2/posts/{r['id']}", "POST", {"content": r["baru"]})
    st, cek = rest(f"/wp-json/wp/v2/posts/{r['id']}?context=edit&_fields=content")
    raw2 = cek.get("content", {}).get("raw", "") if isinstance(cek, dict) else ""
    bagus = "Baca juga:" in raw2 and len(raw2) > len(r["raw"])
    ok += 1 if bagus else 0
    if not bagus:
        print(f"   ⚠️ #{r['id']} gagal")
print(f"\nselesai: {ok}/{len(rencana)}")
