#!/usr/bin/env python3
"""Pemantau posisi mingguan StudioSoft untuk klaster «digital agency surabaya» — data nyata dari Serper.
Menyimpan riwayat ke drafts/ss_posisi_mingguan.json dan catatan ke drafts/ss_posisi_mingguan.md.
Pakai: python3 ss_posisi_mingguan.py [--minggu 2026-W41]
"""
import json, sys, time, urllib.error, urllib.request
from datetime import datetime, timezone, timedelta

WS = "/home/mantapman/.hermes/profiles/atun/workspace"
DOM = "studiosoft.id"
KUNCI = json.load(open(f"{WS}/.serper_token.json"))["key"]
H = {"X-API-KEY": KUNCI, "Content-Type": "application/json", "User-Agent": "Mozilla/5.0"}
RIWAYAT = f"{WS}/drafts/ss_posisi_mingguan.json"
CATATAN = f"{WS}/drafts/ss_posisi_mingguan.md"

KATA_KUNCI = [
    "digital agency surabaya",
    "digital marketing agency surabaya",
    "jasa digital marketing surabaya",
    "branding agency surabaya",
    "jasa seo surabaya",
]
WIB = timezone(timedelta(hours=7))
sekarang = datetime.now(WIB)
minggu = None
if "--minggu" in sys.argv:
    minggu = sys.argv[sys.argv.index("--minggu") + 1]
minggu = minggu or f"{sekarang.isocalendar()[0]}-W{sekarang.isocalendar()[1]:02d}"


def cari(q, jumlah=20):
    body = json.dumps({"q": q, "gl": "id", "hl": "id", "num": jumlah}).encode()
    for _ in range(3):
        try:
            r = urllib.request.urlopen(urllib.request.Request(
                "https://google.serper.dev/search", data=body, headers=H), timeout=90)
            return json.loads(r.read())
        except urllib.error.HTTPError as e:
            return {"err": e.code, "msg": e.read().decode("utf-8", "replace")[:150]}
        except Exception as e:
            time.sleep(3)
            err = str(e)[:90]
    return {"err": err}


def posisi_sekali(q):
    """satu pemanggilan: kembalikan (posisi, url, tiga teratas, ai_overview)"""
    d = cari(q)
    if "err" in d:
        return None, None, [], None, d
    organic = d.get("organic") or []
    pos, url = None, None
    for i, h in enumerate(organic, 1):
        if DOM in str(h.get("link", "")):
            pos, url = i, h["link"]
            break
    atas = [str(h.get("link", "")).split("/")[2] if "//" in str(h.get("link", "")) else "?"
           for h in organic[:3]]
    return pos, url, atas, bool(d.get("aiOverview")), None


ULANG = 3          # SERP bergeser antar pemanggilan → ukur 3 kali, ambil nilai tengah


def median(angka):
    angka = sorted(angka)
    n = len(angka)
    return angka[n // 2] if n else None


hasil = []
print(f"=== posisi mingguan {minggu} · {sekarang.strftime('%d %b %Y %H:%M')} WIB · {ULANG}× pengukuran per kata kunci ===")
for kw in KATA_KUNCI:
    posisi, url, atas, ai, err = [], None, [], False, None
    for putaran in range(ULANG):
        p, u, a, ov, e = posisi_sekali(kw)
        if e:
            err = e
            break
        posisi.append(p)
        url, ai = u or url, ai or ov
        if a and not atas:
            atas = a
        time.sleep(0.7)
    if err:
        print(f"  ❌ «{kw}» {err.get('err')} {str(err.get('msg', ''))[:60]}")
        continue
    ada = [p for p in posisi if p]
    tengah = median(ada)
    sebaran = f"{min(ada)}-{max(ada)}" if ada else "-"
    hasil.append({"kata_kunci": kw, "posisi": tengah, "posisi_mentah": posisi,
                  "sebaran": sebaran, "url": url, "tiga_teratas": atas,
                  "ai_overview": ai, "diperiksa": sekarang.isoformat(timespec="minutes")})
    print(f"  «{kw}» → {'#' + str(tengah) if tengah else 'tidak masuk 20'} "
          f"(3 pengukuran: {posisi}, sebaran {sebaran}) | {url or '-'}")
    print(f"      3 teratas: {', '.join(atas)} | AI Overview: {'ada' if ai else 'tidak'}")


riwayat = json.load(open(RIWAYAT)) if __import__("os").path.exists(RIWAYAT) else {"minggu": {}}
riwayat["minggu"][minggu] = hasil
json.dump(riwayat, open(RIWAYAT, "w"), ensure_ascii=False, indent=1)

lama = sorted(riwayat["minggu"])[-2] if len(riwayat["minggu"]) > 1 else None
with open(CATATAN, "w") as f:
    f.write(f"# Posisi Mingguan StudioSoft — klaster «digital agency surabaya»\n\n"
            f"Sumber: Serper (Google, gl=id, hl=id). Minggu terakhir diperiksa: **{minggu}**.\n"
            f"Cara ukur: tiap kata kunci diperiksa {ULANG} kali pada hari yang sama, yang dicatat nilai tengahnya "
            f"(SERP bisa bergeser antar pemanggilan). Kolom sebaran menunjukkan nilai terendah-tertinggi.\n\n")
    f.write("| Minggu | " + " | ".join(k for k in KATA_KUNCI) + " |\n")
    f.write("|---|" + "---|" * len(KATA_KUNCI) + "\n")
    for m in sorted(riwayat["minggu"]):
        baris = {h["kata_kunci"]: h for h in riwayat["minggu"][m]}
        f.write(f"| {m} | " + " | ".join(
            ("#" + str(baris[k]["posisi"])) if k in baris and baris[k]["posisi"] else "—" for k in KATA_KUNCI) + " |\n")
    f.write("\n### Rincian minggu " + minggu + "\n\n")
    for h in hasil:
        f.write(f"- «{h['kata_kunci']}» → {'posisi #' + str(h['posisi']) + ' (' + str(h['url']) + ')' if h['posisi'] else 'di luar 20 besar'}"
                f" · pengukuran {h.get('posisi_mentah')} · sebaran {h.get('sebaran')}"
                f" · 3 teratas: {', '.join(h['tiga_teratas'])} · AI Overview: {'ada' if h['ai_overview'] else 'tidak'}\n")
    if lama:
        f.write(f"\nPembanding minggu sebelumnya ({lama}):\n\n")
        dulu = {h["kata_kunci"]: h["posisi"] for h in riwayat["minggu"][lama]}
        for h in hasil:
            p0, p1 = dulu.get(h["kata_kunci"]), h["posisi"]
            if p0 and p1:
                tanda = "naik" if p1 < p0 else ("turun" if p1 > p0 else "tetap")
                f.write(f"- «{h['kata_kunci']}» #{p0} → #{p1} ({tanda})\n")
print(f"\n→ {RIWAYAT}\n→ {CATATAN}")
