#!/usr/bin/env python3
"""Deteksi kanibalisasi StudioSoft: bandingkan artikel yang menunggu tayang (future) dengan
artikel yang sudah terbit dan yang baru saja terbit (60 hari terakhir).

Keluaran: drafts/ss_kanibalisasi.json + ringkasan di layar.
"""
import base64, html, json, os, re, time, urllib.error, urllib.request
from datetime import datetime, timedelta, timezone

WS = "/home/mantapman/.hermes/profiles/atun/workspace"
S = "https://studiosoft.id"
AUTH = base64.b64encode(b"bambangbot:q26r RePo BVy6 pwU2 F3z7 ouyl").decode()
UA = {"User-Agent": "Mozilla/5.0"}
WIB = timezone(timedelta(hours=7))
STOP = set("""yang untuk dan dari dengan pada dalam adalah ini itu cara tips panduan lengkap penting
mengapa kenapa bagaimana di ke atau agar supaya bisnis usaha surabaya indonesia 2026 jasa kamu anda
bikin buat yang tanpa juga bisa akan sudah belum lebih paling serta para oleh itu ada""".split())


def rest(path):
    h = {"Authorization": f"Basic {AUTH}", **UA}
    r = urllib.request.Request(S + path, headers=h)
    for _ in range(3):
        try:
            with urllib.request.urlopen(r, timeout=180) as x:
                return json.loads(x.read())
        except urllib.error.HTTPError as e:
            return {"err": e.code}
        except Exception:
            time.sleep(4)
    return {}


def ambil(status, fields="id,slug,link,title,date,status,meta,content", per=100):
    keluar, page = [], 1
    while True:
        d = rest(f"/wp-json/wp/v2/posts?status={status}&per_page={per}&page={page}"
                 f"&orderby=date&order=desc&context=edit&_fields={fields}")
        if not isinstance(d, list) or not d:
            break
        keluar += d
        if len(d) < per:
            break
        page += 1
    return keluar


def bersih(p):
    raw = p.get("content", {}).get("raw", "") if isinstance(p.get("content"), dict) else ""
    judul = html.unescape(p["title"]["raw"] if isinstance(p["title"], dict) else str(p["title"]))
    m = p.get("meta") or {}
    tgl = datetime.fromisoformat(p["date"])
    return {"id": p["id"], "slug": p["slug"], "link": p["link"], "judul": judul, "tgl": tgl,
            "status": p["status"], "fokus": (m.get("_yoast_wpseo_focuskw") or "").strip(),
            "meta_judul": (m.get("_yoast_wpseo_title") or "").strip(),
            "kata": len(re.sub(r"<[^>]+>", " ", raw).split()),
            "awal": re.sub(r"\s+", " ", re.sub(r"<[^>]+>", " ", raw))[:260],
            "kunci": {w for w in re.findall(r"[a-z]{4,}", (p["slug"] + " " + judul + " " +
                                                            (m.get("_yoast_wpseo_focuskw") or "")).lower())
                      if w not in STOP}}


def jaccard(a, b):
    return len(a & b) / max(1, len(a | b))


future = [bersih(p) for p in ambil("future")]
terbit = [bersih(p) for p in ambil("publish")]
batas = datetime.now(WIB).replace(tzinfo=None) - timedelta(days=75)
terbit_baru = [p for p in terbit if p["tgl"] >= batas]

print(f"menunggu tayang: {len(future)} · terbit: {len(terbit)} (75 hari terakhir: {len(terbit_baru)})")

pasangan = []
for i, a in enumerate(future):
    for b in terbit:
        s = jaccard(a["kunci"], b["kunci"])
        fokus_sama = bool(a["fokus"]) and a["fokus"].lower() == b["fokus"].lower()
        if s >= 0.34 or fokus_sama:
            pasangan.append({"future": a, "lawan": b, "skor": round(s, 2), "fokus_sama": fokus_sama})

# kanibalisasi antar sesama artikel menunggu
antar = []
for i, a in enumerate(future):
    for b in future[i + 1:]:
        s = jaccard(a["kunci"], b["kunci"])
        if s >= 0.34 or (a["fokus"] and a["fokus"].lower() == b["fokus"].lower()):
            antar.append({"a": a, "b": b, "skor": round(s, 2)})

print(f"\n=== pasangan menunggu tayang vs sudah terbit (kemiripan >=0,34) : {len(pasangan)} ===")
for p in sorted(pasangan, key=lambda x: -x["skor"]):
    a, b = p["future"], p["lawan"]
    print(f"  {p['skor']:.2f} {'[fokus sama]' if p['fokus_sama'] else '            '} "
          f"#{a['id']} «{a['judul'][:52]}» [{a['tgl'].strftime('%d %b')}]")
    print(f"        vs #{b['id']} «{b['judul'][:52]}» [{b['tgl'].strftime('%d %b %Y')}] · fokus: {b['fokus'] or '-'}")

print(f"\n=== antar artikel menunggu tayang: {len(antar)} pasangan mirip ===")
for p in sorted(antar, key=lambda x: -x["skor"]):
    print(f"  {p['skor']:.2f} #{p['a']['id']} «{p['a']['judul'][:45]}» vs #{p['b']['id']} «{p['b']['judul'][:45]}»")

json.dump({"future": [{k: (v.isoformat() if k == 'tgl' else (sorted(v) if k == 'kunci' else v))
                       for k, v in p.items()} for p in future],
           "pasangan": [{"future_id": p["future"]["id"], "lawan_id": p["lawan"]["id"], "skor": p["skor"],
                         "fokus_sama": p["fokus_sama"]} for p in pasangan],
           "antar": [{"a": p["a"]["id"], "b": p["b"]["id"], "skor": p["skor"]} for p in antar]},
          open(f"{WS}/drafts/ss_kanibalisasi.json", "w"), ensure_ascii=False, indent=1)
print("\n→ drafts/ss_kanibalisasi.json")
