#!/usr/bin/env python3
"""TSC: ganti judul SEO + meta description beranda (halaman 409) TANPA menyentuh isi/desain.
Hanya meta Yoast yang ditulis. Isi halaman diverifikasi lewat sidik jari (hash) sebelum & sesudah."""
import base64, hashlib, html, json, os, re, sys, time, urllib.request, urllib.error, importlib.util
from xml.sax.saxutils import escape

WS = "/home/mantapman/.hermes/profiles/atun/workspace"
spec = importlib.util.spec_from_file_location("cfg_tsc", f"{WS}/cfg_tsc.py")
mod = importlib.util.module_from_spec(spec); spec.loader.exec_module(mod)
CFG = mod.CFG
DOM = CFG["domain"]
USER, PASS = CFG["user"], CFG["pass"]
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"}
PID = 409

JUDUL_BARU = "Dokter Kulit & Kelamin Krian Sidoarjo | The Skin Code"
META_BARU = ("Dokter spesialis kulit & kelamin di Krian, Sidoarjo: jerawat, infeksi kulit, keluhan kelamin, "
             "hingga estetika medis. Buat janji temu di The Skin Code Clinic.")
FOKUS_BARU = "dokter kulit sidoarjo"


def rpc(method, params=()):
    def val(v):
        if isinstance(v, bool):
            return f"<value><boolean>{1 if v else 0}</boolean></value>"
        if isinstance(v, int):
            return f"<value><int>{v}</int></value>"
        if isinstance(v, list):
            return "<value><array><data>" + "".join(val(x) for x in v) + "</data></array></value>"
        if isinstance(v, dict):
            return "<value><struct>" + "".join(f"<member><name>{escape(str(k))}</name>{val(x)}</member>"
                                               for k, x in v.items()) + "</struct></value>"
        return f"<value><string>{escape(str(v))}</string></value>"
    body = ("<?xml version=\"1.0\"?><methodCall><methodName>" + method + "</methodName><params>" +
            "".join(f"<param>{val(p)}</param>" for p in params) + "</params></methodCall>").encode()
    r = urllib.request.Request(f"https://www.{DOM}/xmlrpc.php", data=body,
                               headers={"Content-Type": "text/xml", "User-Agent": "Mozilla/5.0",
                                        "Authorization": f"Basic {AUTH}"}, method="POST")
    for _ in range(3):
        try:
            with urllib.request.urlopen(r, timeout=180) as x:
                return x.status, x.read().decode("utf-8", "replace")
        except urllib.error.HTTPError as e:
            return e.code, e.read().decode("utf-8", "replace")[:250]
        except Exception:
            time.sleep(4)
    return 0, "gagal"


def baris(isi, kunci):
    return [(m.group(1), m.group(2)) for m in re.finditer(
        r"<member><name>id</name><value><string>(\d+)</string></value></member>\s*"
        r"<member><name>key</name><value><string>" + re.escape(kunci) +
        r"</string></value></member>\s*<member><name>value</name><value><string>(.*?)</string>", isi, re.S)]


def hash_isi():
    r = urllib.request.Request(f"https://www.{DOM}/wp-json/wp/v2/pages/{PID}?context=edit&_fields=content",
                               headers={"Authorization": f"Basic {AUTH}", **UA})
    with urllib.request.urlopen(r, timeout=150) as x:
        raw = json.loads(x.read()).get("content", {}).get("raw", "")
    return hashlib.sha256(raw.encode()).hexdigest(), len(raw)


def live():
    h = urllib.request.urlopen(urllib.request.Request(f"https://www.{DOM}/?cek={int(time.time())}",
                                                      headers=UA), timeout=90).read().decode("utf-8", "replace")
    t = re.search(r"<title>(.*?)</title>", h, re.S)
    d = re.search(r'<meta name="description" content="([^"]*)"', h)
    return (html.unescape(t.group(1)).strip() if t else "-"), (html.unescape(d.group(1)).strip() if d else "-")


st, isi = rpc("wp.getPost", [1, USER, PASS, PID])
print("=== keadaan sekarang ===")
for kunci in ("_yoast_wpseo_title", "_yoast_wpseo_metadesc", "_yoast_wpseo_focuskw"):
    for mid, v in baris(isi, kunci):
        print(f"   {kunci:<24} id {mid}: {v[:80]}")
h_awal, n_awal = hash_isi()
t0, d0 = live()
print(f"   isi halaman: {n_awal} karakter | hash {h_awal[:16]}")
print(f"   live: judul «{t0}» ({len(t0)} char)")
print(f"         meta  «{d0[:80]}» ({len(d0)} char)")

print(f"\n=== rencana ===")
print(f"   judul ({len(JUDUL_BARU)} char): {JUDUL_BARU}")
print(f"   meta  ({len(META_BARU)} char): {META_BARU}")
print(f"   fokus : {FOKUS_BARU}")

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

print("\n=== menyimpan (hanya meta, isi halaman tidak dikirim) ===")
for kunci, nilai in (("_yoast_wpseo_title", JUDUL_BARU), ("_yoast_wpseo_metadesc", META_BARU),
                     ("_yoast_wpseo_focuskw", FOKUS_BARU)):
    rows = baris(isi, kunci)
    if not rows:
        st, res = rpc("wp.editPost", [1, USER, PASS, PID, {"custom_fields": [{"key": kunci, "value": nilai}]}])
        print(f"   {kunci:<24} (baru) → {'✅' if '<boolean>1</boolean>' in res else '❌ ' + res[:80]}")
    for mid, lama in rows:
        st, res = rpc("wp.editPost", [1, USER, PASS, PID,
                                      {"custom_fields": [{"id": int(mid), "key": kunci, "value": nilai}]}])
        print(f"   {kunci:<24} id {mid} → {'✅' if '<boolean>1</boolean>' in res else '❌ ' + res[:80]}")

time.sleep(4)
print("\n=== verifikasi ===")
h_akhir, n_akhir = hash_isi()
t1, d1 = live()
print(f"   isi halaman: {n_akhir} karakter | hash {h_akhir[:16]} → {'TIDAK BERUBAH (desain aman)' if h_akhir == h_awal else '⚠️ BERUBAH'}")
print(f"   judul live : «{t1}» ({len(t1)} char) → {'berubah' if t1 != t0 else 'belum'}")
print(f"   meta live  : ({len(d1)} char) {d1[:100]} → {'berubah' if d1 != d0 else 'belum'}")
