#!/usr/bin/env python3
"""Scan teks CJK di konten LIVE website klien (WP REST /wp-json/wp/v2/posts)."""
import json, re, sys, time, urllib.request, urllib.error
from concurrent.futures import ThreadPoolExecutor

CJK = re.compile(r"[\u3000-\u303f\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff]")
SITES = [
    "https://studiosoft.id",
    "https://abimataconsultant.com",
    "https://leitsurabaya.com",
    "https://www.tslaw.id",
    "https://dasindonesia.com",
    "https://www.theskincodeclinic.com",
    "https://everybeofficial.com",
    "https://www.dmark.id",
    "https://yasmanatura.co.id",
    "https://surabaya-skincentre.com",
    "https://rsia.kendangsari.com",
    "https://ekaduta.com",
]


def fetch(site):
    """Ambil semua post (paged) → list of (id, link, jenis, teks).

    PENTING: pakai cache-buster `cb=` di query string. Cloudflare meng-cache
    respons WP REST (terbukti di studiosoft.id: `cf-cache-status: HIT`,
    `cache-control: max-age=2592000`) dengan kunci URL penuh → tanpa cache-buster,
    hasil scan bisa memantulkan isi LAMA sampai 30 hari.
    """
    out, page = [], 1
    while True:
        url = (f"{site}/wp-json/wp/v2/posts?per_page=100&page={page}"
               f"&_fields=id,link,title,content&cb={int(time.time())}{page}")
        try:
            req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
            with urllib.request.urlopen(req, timeout=90) as r:
                docs = json.loads(r.read())
        except Exception as ex:
            out.append((None, f"[ERROR {getattr(ex,'code',ex)}]", None, None))
            break
        if not docs:
            break
        for d in docs:
            out.append((d.get("id"), d.get("link"), "title", (d.get("title") or {}).get("rendered", "")))
            out.append((d.get("id"), d.get("link"), "content", (d.get("content") or {}).get("rendered", "")))
        if len(docs) < 100:
            break
        page += 1
    return out


def scan(site):
    items = fetch(site)
    errs = [i for i in items if i[2] is None]
    posts = len({i[1] for i in items if i[1]})
    hits = []
    for pid, link, kind, txt in items:
        if not txt:
            continue
        m = CJK.findall(txt)
        if m:
            plain = re.sub(r"<[^>]+>", " ", txt)
            plain = re.sub(r"\s+", " ", plain)
            i = CJK.search(plain)
            hits.append((pid, link, kind, "".join(sorted(set(m))), plain[max(0, i.start()-90):i.start()+90]))
    print(f"\n=== {site}  ({posts} post, {len(errs)} error)")
    if errs:
        print("   ⚠️", errs[0][1])
    if not hits:
        print("   ✅ 0 teks CJK")
    for pid, link, kind, chars, ctx in hits:
        print(f"   ❌ post {pid} [{kind}] chars={chars}\n      {link}\n      …{ctx}…")
    return site, len(hits), posts


if __name__ == "__main__":
    sites = sys.argv[1:] or SITES
    with ThreadPoolExecutor(max_workers=4) as ex:
        res = list(ex.map(scan, sites))
    print("\n--- RINGKASAN")
    for site, n, posts in res:
        print(f"{'❌' if n else '✅'} {site}: {n} temuan / {posts} post")
