#!/usr/bin/env python3
"""Perbaiki tautan mati di StudioSoft.

Aturan:
- Tautan internal mati → dicari pengganti yang hidup berdasarkan kemiripan kata pada slug;
  kalau tidak ada, tautannya dilepas (teks jangkarnya tetap, jadi kalimat tidak rusak).
- Tautan luar mati → tautannya dilepas, teksnya tetap.
- Tautan luar ke domain mencurigakan (PBN/spam) → dilepas juga walau hidup.

Jalankan tanpa argumen = uji. Dengan --go = kerjakan (dengan cadangan).
"""
import base64, json, re, sys, time, urllib.request

WS = "/home/mantapman/.hermes/profiles/atun/workspace"
DOM = "studiosoft.id"
S = f"https://{DOM}"
AUTH = base64.b64encode(b"bambangbot:q26r RePo BVy6 pwU2 F3z7 ouyl").decode()
H = {"Authorization": f"Basic {AUTH}", "User-Agent": "Mozilla/5.0", "Content-Type": "application/json"}
UA = {"User-Agent": "Mozilla/5.0"}
ECURIGA = ("rentpbn", "my.id/jasa-seo", "backlink", "pbn", "stikeshb", "repository.", "blogspot")
LEWATI = ("/wp-json/", "facebook.com", "instagram.com", "twitter.com", "x.com", "tiktok.com", "youtube.com",
          "wa.me", "whatsapp.com")
PETA = {
    "https://studiosoft.id/blog": "https://studiosoft.id/artikel/",
    "https://studiosoft.id/blog/": "https://studiosoft.id/artikel/",
    "https://studiosoft.id/konsultasi/": "https://studiosoft.id/kontak/",
    "https://studiosoft.id/google-business-profile-untuk-klinik/":
        "https://studiosoft.id/google-business-profile-klinik/",
    "https://studiosoft.id/panduan-seo-untuk-klinik-dan-rumah-sakit/":
        "https://studiosoft.id/panduan-seo-klinik-rumah-sakit/",
    "https://studiosoft.id/analitik-digital-bisnis-properti/":
        "https://studiosoft.id/analitik-properti/",
    "https://studiosoft.id/digital-marketing-bisnis-keuangan/":
        "https://studiosoft.id/marketing-keuangan/",
    "https://studiosoft.id/digital-marketing-bisnis-retail/":
        "https://studiosoft.id/digital-marketing-retail/",
    "https://studiosoft.id/digital-marketing-bisnis-properti/":
        "https://studiosoft.id/digital-marketing-properti/",
    "https://studiosoft.id/digital-marketing-bisnis-manufaktur/":
        "https://studiosoft.id/marketing-manufaktur/",
    "https://studiosoft.id/seo-untuk-bisnis-properti/":
        "https://studiosoft.id/seo-properti/",
    "https://studiosoft.id/klinik-kecil-butuh-digital-marketing/":
        "https://studiosoft.id/jasa-digital-marketing-klinik/",
    "https://studiosoft.id/strategi-digital-marketing-rumah-sakit/":
        "https://studiosoft.id/7-strategi-digital-marketing-rumah-sakit-untuk-menambah-pasien-setiap-bulan/",
}

data = json.load(open(f"{WS}/drafts/ss_tautan_mati.json"))
# buang tautan yang tidak relevan diperiksa: URL API, sosial media yang menolak bot, dan balasan 403
# (403 = server menolak pemeriksa otomatis, belum tentu halaman mati)
data = {u: v for u, v in data.items()
        if not any(k in u for k in LEWATI) and v.get("status") != 403}
GO = "--go" in sys.argv


def rest(p, method="GET", data_=None):
    body = json.dumps(data_).encode() if data_ is not None else None
    r = urllib.request.Request(S + p, data=body, headers=H, method=method)
    for _ in range(3):
        try:
            with urllib.request.urlopen(r, timeout=180) as x:
                return json.loads(x.read())
        except Exception:
            time.sleep(4)
    raise RuntimeError("gagal ambil " + p)


def hidup(u):
    try:
        with urllib.request.urlopen(urllib.request.Request(u, headers=UA), timeout=25) as r:
            return r.status == 200
    except Exception:
        return False


def kata(s):
    return {k for k in re.split(r"[-_/]+", s.lower()) if len(k) > 3}


print("=== daftar halaman hidup di situs ===")
HIDUP = {}
for jenis in ("posts", "pages"):
    hal = 1
    while hal <= 8:
        d = rest(f"/wp-json/wp/v2/{jenis}?per_page=50&page={hal}&status=publish&_fields=id,slug,link")
        if not isinstance(d, list) or not d:
            break
        for x in d:
            HIDUP[x["link"]] = x["slug"]
        if len(d) < 50:
            break
        hal += 1
print(f"   {len(HIDUP)} halaman hidup")


def cari_pengganti(u):
    """Cari halaman hidup yang paling mirip dengan tautan internal yang mati."""
    sasaran = kata(u)
    skor = []
    for link, slug in HIDUP.items():
        s = len(sasaran & kata(slug))
        if s:
            skor.append((s, link))
    skor.sort(reverse=True)
    if skor and skor[0][0] >= 3:
        return skor[0][1]
    return None


print("=== rencana perbaikan ===")
per_artikel = {}
for u, info in data.items():
    for d in info.get("dari", []):
        per_artikel.setdefault((d.get("jenis", "posts"), d["pid"]), []).append(
            {"url": u, "jangkar": d["jangkar"], "status": info.get("status")})

print(f"   {len(data)} tautan bermasalah · tersebar di {len(per_artikel)} artikel/halaman")
for u, info in list(data.items())[:40]:
    curiga = any(k in u.lower() for k in ECURIGA)
    print(f"   {str(info.get('status'))[:12]:<13} {'⚠ mencurigakan ' if curiga else ''}{u[:92]}")

cadangan_isi, ubah = {}, 0
for (jenis, pid), daftar in per_artikel.items():
    d = rest(f"/wp-json/wp/v2/{jenis}/{pid}?context=edit&_fields=content,slug,link")
    isi = d["content"]["raw"]
    asli = isi
    rincian = []
    for item in daftar:
        u = item["url"]
        pola = re.compile(r'<a[^>]+href="' + re.escape(u) + r'"[^>]*>(.*?)</a>', re.S)
        if not pola.search(isi):
            continue
        pengganti = None
        if "studiosoft.id" in u or u.startswith("/"):
            pengganti = PETA.get(u) or cari_pengganti(u)
        if pengganti:
            isi = pola.sub(lambda mo: f'<a href="{pengganti}">{mo.group(1)}</a>', isi)
            rincian.append(f"diganti → {pengganti}")
        else:
            isi = pola.sub(lambda mo: mo.group(1), isi)
            rincian.append(f"dilepas · {u[:70]}")
        ubah += 1
    if isi != asli:
        cadangan_isi[f"{jenis}:{pid}"] = asli
        print(f"\n   #{pid} [{jenis}] {d['slug'][:50]} — {len(rincian)} tautan")
        for r in rincian:
            print(f"        {r}")

if GO:
    for kunci, isi in cadangan_isi.items():
        jenis, pid = kunci.split(":")
        rest(f"/wp-json/wp/v2/{jenis}/{pid}", "POST", {"content": isi})
        time.sleep(0.8)
    json.dump(cadangan_isi, open(f"{WS}/ss_backup_tautan_mati.json", "w"), ensure_ascii=False)
    print(f"\n✅ {ubah} tautan diperbaiki di {len(cadangan_isi)} artikel/halaman · "
          f"cadangan: ss_backup_tautan_mati.json")
else:
    print(f"\n(uji) {ubah} tautan akan diperbaiki di {len(cadangan_isi)} artikel/halaman. "
          f"Pakai --go untuk mengerjakan.")
