#!/usr/bin/env python3
"""TSC: selesaikan penyelarasan meta 3 artikel yang belum tertulis + verifikasi dengan URL yang benar."""
import base64, html, json, 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, USER, PASS = CFG["domain"], CFG["user"], CFG["pass"]
AUTH = base64.b64encode(f"{USER}:{PASS}".encode()).decode()
UA = {"User-Agent": "Mozilla/5.0"}

TARGET = {
    1709: {"judul": "DNI Clinic Krian Kini The Skin Code Clinic: Apa yang Berubah",
           "meta": "DNI Clinic Krian resmi berganti nama menjadi The Skin Code Clinic. Ini yang berubah, yang tetap sama, dan cara pasien lama melanjutkan perawatan.",
           "fokus": "dni clinic krian"},
    8464: {"judul": "The Skin Code Clinic Krian | Klinik Kulit & Kelamin",
           "meta": "Klinik kulit dan kelamin di Krian, Sidoarjo. Menangani jerawat, infeksi kulit, keluhan kelamin, sampai perawatan estetika medis bersama dokter spesialis.",
           "fokus": "klinik kulit krian"},
    9268: {"judul": "FAQ Dokter Kulit Krian | The Skin Code Clinic",
           "meta": "Pertanyaan yang sering diajukan pasien dokter kulit di Krian: biaya konsultasi, jadwal praktik, jenis perawatan, dan cara membuat janji temu.",
           "fokus": "dokter kulit krian"},
}


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=150) as x:
                return x.read().decode("utf-8", "replace")
        except Exception:
            time.sleep(4)
    return ""


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 rest(p):
    r = urllib.request.Request(f"https://{DOM}{p}", headers={"Authorization": f"Basic {AUTH}", **UA})
    with urllib.request.urlopen(r, timeout=150) as x:
        return json.loads(x.read())


print("=== URL sebenarnya dari WordPress ===")
url_sebenarnya = {}
for pid in TARGET:
    d = rest(f"/wp-json/wp/v2/posts/{pid}?_fields=id,slug,link,status")
    url_sebenarnya[pid] = d.get("link")
    print(f"   #{pid} {d.get('status')} | {d.get('link')}")

print("\n=== menulis meta yang tertinggal ===")
for pid, v in TARGET.items():
    isi = rpc("wp.getPost", [1, USER, PASS, pid])
    for kunci, nilai in (("_yoast_wpseo_title", v["judul"]), ("_yoast_wpseo_metadesc", v["meta"]),
                         ("_yoast_wpseo_focuskw", v["fokus"])):
        rows = baris(isi, kunci)
        sudah = rows and all(x.strip() == nilai for _, x in rows)
        if sudah:
            print(f"   #{pid} {kunci:<24} sudah sesuai (dilewati)")
            continue
        if not rows:
            res = rpc("wp.editPost", [1, USER, PASS, pid, {"custom_fields": [{"key": kunci, "value": nilai}]}])
            f = re.search(r"<name>faultString</name><value><string>(.*?)</string>", res, re.S)
            print(f"   #{pid} {kunci:<24} (baris baru) → {'GAGAL ' + f.group(1)[:40] if f else '✅'}")
        for mid, _ in rows:
            res = rpc("wp.editPost", [1, USER, PASS, pid, {"custom_fields": [{"id": int(mid), "key": kunci, "value": nilai}]}])
            f = re.search(r"<name>faultString</name><value><string>(.*?)</string>", res, re.S)
            print(f"   #{pid} {kunci:<24} id {mid} → {'GAGAL ' + f.group(1)[:40] if f else '✅'}")

print("\n=== verifikasi live (memakai tautan asli) ===")
time.sleep(3)
for pid, url in url_sebenarnya.items():
    if not url:
        print(f"   #{pid}: tautan tidak terbaca")
        continue
    try:
        h = urllib.request.urlopen(urllib.request.Request(f"{url}?v={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)
        print(f"   #{pid} {url.replace('https://www.theskincodeclinic.com', '')[:44]}")
        print(f"        judul: {t.group(1).strip()[:62] if t else '-'}")
        print(f"        meta : ({len(d.group(1)) if d else 0} char) {d.group(1)[:72] if d else '-'}")
    except urllib.error.HTTPError as e:
        print(f"   #{pid} {url} → HTTP {e.code}")
    except Exception as e:
        print(f"   #{pid} → gagal {str(e)[:50]}")
