#!/usr/bin/env python3
"""TSLaw #3177 konsultasi-hukum-kapan-dan-mengapa: 501 -> 1.200+ kata isi berguna.

Cara kerja: blok lama diekstrak utuh per H2 (teks tidak diubah), lalu disusun ulang
dengan urutan yang runtut dan disisipi 6 bagian baru + 2 FAQ (skema diselaraskan).
Blok lama diverifikasi utuh satu per satu sebelum menulis.

Default dry run. --apply untuk menulis lewat REST API JSON.
"""
import base64, json, re, sys, urllib.request, urllib.error

WS = "/home/mantapman/.hermes/profiles/atun/workspace"
DIR = f"{WS}/tslaw_pemulihan/perbaikan_20261018"
PID = 3177
AUTH = base64.b64encode(b"bambangbot:EFKm EYGx VQCP Y9go ncPr uM2Y").decode()
UA = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124 Safari/537.36"}


def rest(path, method="GET", data=None):
    h = {"Authorization": f"Basic {AUTH}", **UA}
    body = None
    if data is not None:
        body = json.dumps(data).encode()
        h["Content-Type"] = "application/json"
    r = urllib.request.Request(f"https://tslaw.id{path}", data=body, headers=h, method=method)
    try:
        with urllib.request.urlopen(r, timeout=180) as x:
            return x.status, json.loads(x.read())
    except urllib.error.HTTPError as e:
        return e.code, e.read().decode()[:400]


def kata(html):
    t = re.sub(r"<(script|style)[^>]*>.*?</\1>", " ", html, flags=re.S | re.I)
    t = re.sub(r"<[^>]+>", " ", t)
    t = re.sub(r"&[a-z]+;", " ", t)
    return len(re.findall(r"[A-Za-z0-9][A-Za-z0-9'\-]*", t))


def rapikan_p_ganda(t):
    """<p>A<p>B</p></p> -> <p>A</p><p>B</p>, teks tidak hilang."""
    pola = re.compile(r"<p>([^<]*?)<p>([^<]*?)</p>\s*</p>", re.S)
    return pola.subn(lambda m: f"<p>{m.group(1).strip()}</p>\n<p>{m.group(2).strip()}</p>", t)


# ----------------------------------------------------------------- bagian baru
SEC_PREVENTIF = """<h2 class="wp-block-heading">Konsultasi Preventif dan Konsultasi Kuratif: Apa Bedanya</h2>
<p>Konsultasi hukum punya dua fungsi yang tidak sama, dan keduanya dipakai di titik yang berbeda. Konsultasi preventif berjalan saat belum ada sengketa, misalnya ketika Anda memeriksa rancangan perjanjian kerja sama, menilai kepatuhan izin usaha, atau menyiapkan perjanjian kerja sebelum merekrut karyawan. Tujuannya menutup celah yang nanti bisa dipersoalkan pihak lain.</p>
<p>Konsultasi kuratif berjalan setelah masalah muncul, misalnya saat Anda menerima somasi, ada wanprestasi dari mitra, atau karyawan mempersoalkan pemutusan hubungan kerja. Di tahap ini pertanyaannya bukan lagi bagaimana mencegah, tetapi langkah apa yang harus diambil, bukti apa yang masih kurang, dan jalur mana yang paling masuk akal, apakah perundingan, mediasi, atau gugatan.</p>
"""

SEC_RAHASIA = """<h2 class="wp-block-heading">Kerahasiaan yang Dilindungi Undang-Undang</h2>
<p>Kekhawatiran paling sering muncul sebelum orang membuka masalahnya ke pengacara: apakah rahasia usaha dan persoalan pribadinya akan bocor. Bagi advokat, kewajiban itu bukan sekadar etika. Pasal 19 ayat (1) Undang-Undang Nomor 18 Tahun 2003 tentang Advokat mewajibkan advokat merahasiakan segala sesuatu yang diketahui atau diperoleh dari kliennya karena hubungan profesinya, kecuali ditentukan lain oleh undang undang.</p>
<p>Ayat (2) pasal yang sama memberi advokat hak atas kerahasiaan hubungan dengan klien, termasuk perlindungan atas berkas dan dokumennya terhadap penyitaan atau pemeriksaan, serta perlindungan terhadap penyadapan atas komunikasi elektronik advokat. Pasal 18 menambahkan bahwa advokat tidak dapat diidentikkan dengan kliennya dalam membela perkara. Artinya Anda bisa menjelaskan duduk perkara secara utuh tanpa membuat dokumen pribadi Anda ikut terbuka karena Anda sedang berkonsultasi.</p>
"""

SEC_IMUNITAS = """<h2 class="wp-block-heading">Batas Imunitas Advokat</h2>
<p>Pasal 16 Undang-Undang Advokat menyebut advokat tidak dapat dituntut baik secara perdata maupun pidana dalam menjalankan tugas profesinya dengan iktikad baik untuk kepentingan pembelaan klien dalam sidang pengadilan. Ketentuan ini melindungi advokat agar leluasa membela klien, bukan membebaskan siapa pun dari hukum.</p>
<p>Ada dua batas yang perlu dicatat. Pertama, iktikad baik, sehingga advokat yang menyusun keterangan palsu tetap bisa dipersoalkan. Kedua, konteksnya adalah pembelaan di sidang pengadilan. Karena itu, saat memilih pendamping, tanyakan bagaimana ia memandang peluang dan risiko perkara Anda, bukan hanya janji untuk menang.</p>
"""

SEC_DIGITAL = """<h2 class="wp-block-heading">Konsultasi Online dan Kekuatan Bukti Digital</h2>
<p>Konsultasi jarak jauh kini lazim, dan pertanyaan yang sering muncul adalah soal keabsahan dokumen yang dikirim lewat surel atau aplikasi pesan. Pasal 5 ayat (1) Undang-Undang Nomor 11 Tahun 2008 tentang Informasi dan Transaksi Elektronik menyatakan informasi elektronik dan/atau dokumen elektronik dan/atau hasil cetaknya merupakan alat bukti hukum yang sah. Ayat (2) menempatkannya sebagai perluasan alat bukti yang sah menurut hukum acara yang berlaku.</p>
<p>Namun ayat (3) memberi syarat: informasi elektronik dinyatakan sah apabila menggunakan sistem elektronik sesuai ketentuan undang undang. Dalam praktik, simpan pesan dan surel apa adanya, jangan mengedit tangkapan layar, dan usahakan jejak waktunya konsisten. Kalau percakapan penting hanya tersimpan di satu ponsel, ekspor atau cadangkan sebelum perangkat berganti.</p>
"""

SEC_TANYA = """<h2 class="wp-block-heading">Pertanyaan yang Layak Diajukan di Sesi Pertama</h2>
<ul class="wp-block-list">
<li>Apa dasar hukum yang paling kuat untuk posisi saya?</li>
<li>Apa risiko terburuk jika perkara berlanjut, dan berapa lama kira-kira prosesnya?</li>
<li>Bukti apa yang masih kurang dan bagaimana cara memperolehnya?</li>
<li>Apakah ada jalur damai sebelum berperkara, dan apa syaratnya?</li>
<li>Apa langkah yang bisa saya lakukan sendiri tanpa biaya advokat?</li>
<li>Apa yang sebaiknya tidak saya lakukan atau kirimkan mulai hari ini?</li>
</ul>
<p>Jawaban atas enam pertanyaan itu memberi gambaran apakah persoalan Anda cukup diselesaikan lewat perundingan atau perlu pendampingan penuh.</p>
"""

SEC_CUKUP = """<h2 class="wp-block-heading">Kapan Konsultasi Saja Tidak Cukup</h2>
<p>Konsultasi cukup untuk membaca risiko, memilih langkah, dan menyusun dokumen. Ada situasi yang menuntut pendampingan penuh: ketika Anda menerima somasi dengan tenggat, saat gugatan sudah didaftarkan di pengadilan, ketika penyidik memanggil Anda sebagai saksi atau tersangka, dan saat negosiasi berjalan dengan pihak yang sudah didampingi kuasa hukum lain. Di titik itu, surat menyurat harus dijawab dengan format dan tenggat yang benar.</p>
<p>Untuk kasus seperti ini, <a href="https://www.tslaw.id/law-firm-surabaya/">law firm Surabaya</a> yang menangani litigasi dan non litigasi bisa menjadi pilihan, karena satu tim mengikuti perkara sejak penanganan awal sampai putusan. Anda tetap bisa memulai dari konsultasi, lalu memutuskan sendiri apakah perlu naik ke pendampingan.</p>
"""

FAQ = [
    ("Kapan waktu terbaik konsultasi hukum?", "Sebelum mengambil keputusan penting. Konsultasi preventif jauh lebih hemat daripada berperkara."),
    ("Dokumen apa yang perlu dibawa?", "Perjanjian terkait, bukti transaksi, surat menyurat, dan tangkapan layar komunikasi yang relevan."),
    ("Berapa biaya konsultasi?", "Bervariasi tergantung kompleksitas perkara dan pengalaman advokat. Sebagian kantor menawarkan sesi awal gratis."),
    ("Apakah hasil konsultasi mengikat?", "Tidak. Konsultasi memberi rekomendasi langkah, keputusan tetap di tangan Anda."),
    ("Apakah bisa konsultasi online?", "Bisa, banyak kantor hukum melayani konsultasi jarak jauh lewat panggilan video."),
    ("Apakah kerahasiaan konsultasi dijamin undang undang?", "Untuk advokat, ya. Pasal 19 Undang-Undang Nomor 18 Tahun 2003 mewajibkan advokat merahasiakan informasi dari klien, dan memberi perlindungan atas berkas serta dokumen klien terhadap penyitaan atau pemeriksaan."),
    ("Bisakah konsultasi dilakukan lewat chat?", "Bisa untuk pertanyaan awal dan hal yang sifatnya umum. Untuk perkara yang butuh penilaian dokumen, sesi tatap muka atau panggilan video dengan dokumen lengkap memberi hasil yang lebih akurat."),
]


def blok_teks(html):
    """Teks paragraf & butir daftar (tanpa judul) untuk uji keutuhan."""
    out = []
    for m in re.finditer(r"<(p|li)\b[^>]*>(.*?)</\1>", html, re.S | re.I):
        x = re.sub(r"<[^>]+>", " ", m.group(2))
        x = re.sub(r"&nbsp;?", " ", x).replace("&amp;", "&")
        x = re.sub(r"\s+", " ", x).strip()
        if len(x) > 25:
            out.append(x)
    return out


def muat():
    st, d = rest(f"/wp-json/wp/v2/posts/{PID}?context=edit")
    assert st == 200 and isinstance(d, dict), f"gagal muat: {st} {d}"
    return d


def bangun(lama):
    t, nfix = rapikan_p_ganda(lama)
    print(f"  paragraf <p><p> dirapikan: {nfix}")

    # pisah per H2; blok pertama = paragraf pembuka
    potong = re.split(r"(?=<h2)", t)
    pembuka = potong[0]
    blok = {}
    for b in potong[1:]:
        jud = re.search(r"<h2[^>]*>(.*?)</h2>", b, re.S)
        assert jud, b[:80]
        kunci = re.sub(r"<[^>]+>", "", jud.group(1)).strip()
        assert kunci not in blok, f"judul ganda: {kunci}"
        blok[kunci] = b
    print(f"  blok lama: {len(blok)} -> {list(blok)}")

    # blok FAQ lama diganti versi 7 pertanyaan; skema lama di dalamnya dibuang
    faq_lama = blok.pop("Pertanyaan yang Sering Diajukan")
    assert faq_lama.count("<h3>") == 5, faq_lama.count("<h3>")

    # H2 duplikatif diganti nama (judul saja, isi tetap)
    lama_judul = "<h2>Apa yang Membuat Konsultasi Hukum Perlu</h2>"
    assert blok["Apa yang Membuat Konsultasi Hukum Perlu"].count(lama_judul) == 1
    blok["Momen yang Paling Sering Membuat Konsultasi Dibutuhkan"] = blok.pop(
        "Apa yang Membuat Konsultasi Hukum Perlu").replace(
        lama_judul, '<h2 class="wp-block-heading">Momen yang Paling Sering Membuat Konsultasi Dibutuhkan</h2>')

    # dua H2 soal persiapan digabung: daftar dokumen masuk ke bagian persiapan
    blok_siap = blok.pop("Apa yang Perlu Disiapkan?")
    ul_siap = re.search(r"<ul[^>]*>.*?</ul>", blok_siap, re.S).group(0)
    penyiapan = blok.pop("Menyiapkan Diri Sebelum Konsultasi")
    p1 = re.search(r"<p>.*?</p>", penyiapan, re.S).group(0)
    assert penyiapan.count(p1) == 1
    penyiapan = penyiapan.replace(p1, p1 + "\n" + ul_siap, 1)
    blok["Menyiapkan Diri Sebelum Konsultasi"] = penyiapan

    faq_baru = '<h2 class="wp-block-heading">Pertanyaan yang Sering Diajukan</h2>\n'
    for q, a in FAQ:
        faq_baru += f"<h3>{q}</h3>\n<p>{a}</p>\n"
    skema = {"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [
        {"@type": "Question", "name": q, "acceptedAnswer": {"@type": "Answer", "text": a}} for q, a in FAQ]}
    faq_baru += '<script type="application/ld+json">' + json.dumps(skema, ensure_ascii=False) + "</script>\n"

    urutan = [
        "Kapan Anda Perlu Konsultasi Hukum?",
        "Manfaat Konsultasi Hukum",
        "Konsultasi Hukum Itu Mahal? Mitos!",
        SEC_PREVENTIF,
        "Momen yang Paling Sering Membuat Konsultasi Dibutuhkan",
        "Menyiapkan Diri Sebelum Konsultasi",
        "Apa yang Bisa Diharapkan dari Sesi Konsultasi",
        SEC_RAHASIA,
        SEC_IMUNITAS,
        SEC_DIGITAL,
        SEC_TANYA,
        SEC_CUKUP,
        faq_baru,
        "Kesimpulan",
        "Baca juga",
    ]
    bagian = [pembuka.strip() + "\n"]
    for u in urutan:
        isi = u if u.startswith("<h2") else blok.pop(u)
        bagian.append(isi.strip() + "\n")
    assert not blok, f"blok belum terpakai: {list(blok)}"
    baru = "\n".join(bagian).strip() + "\n"

    # ---- uji wajib (blok pembanding diambil dari teks lama yang sudah dirapikan tag-nya)
    acuan = rapikan_p_ganda(lama)[0]
    hilang = [b for b in blok_teks(acuan) if b not in re.sub(r"\s+", " ", re.sub(r"<[^>]+>", " ", baru))]
    print(f"  teks lama: {len(blok_teks(acuan))} blok, hilang: {len(hilang)}")
    assert not hilang, hilang[:2]
    for q, _ in FAQ:
        assert baru.count(q) >= 2, f"pertanyaan skema tidak tampil di isi: {q}"
    for pola in ("<p><p>", "</p></p>", "\u2014", "\u201c", "\u201d"):
        assert pola not in baru, f"sisa pola terlarang: {pola}"
    assert baru.count("wa.me/6281909222026") == 1, "tombol WA berubah"
    assert baru.count("law-firm-surabaya") == 1, "tautan pilar harus tepat satu"
    return baru


def main():
    d = muat()
    lama = d["content"]["raw"]
    judul_lama, slug_lama = d["title"]["raw"], d["slug"]
    m = d.get("meta") or {}
    fokus, meta_desc = m.get("_yoast_wpseo_focuskw"), m.get("_yoast_wpseo_metadesc")
    baru = bangun(lama)

    sk = re.search(r'ld\+json">(.*?)</script>', baru, re.S)
    print(f"\njudul : {judul_lama}\nslug  : {slug_lama}\nfokus : {fokus}")
    print(f"kata  : {kata(lama)} -> {kata(baru)} | H2: {len(re.findall(r'<h2', lama))} -> "
          f"{len(re.findall(r'<h2', baru))} | H3: {len(re.findall(r'<h3', lama))} -> {len(re.findall(r'<h3', baru))}"
          f" | skema FAQ: {len(json.loads(sk.group(1))['mainEntity'])} item")
    open(f"{DIR}/post_3177_SESUDAH_dryrun.html", "w").write(baru)

    if "--apply" not in sys.argv:
        print("\n[dry run] tidak ada yang ditulis.")
        return

    st, resp = rest(f"/wp-json/wp/v2/posts/{PID}", "POST", {"content": baru})
    print(f"\nPOST status {st}")
    assert st == 200, resp
    json.dump(resp, open(f"{DIR}/post_3177_POSTRESP.json", "w"), ensure_ascii=False, indent=1)

    st2, d2 = rest(f"/wp-json/wp/v2/posts/{PID}?context=edit")
    assert st2 == 200, d2
    raw = d2["content"]["raw"]
    json.dump(d2, open(f"{DIR}/post_3177_VERIFIKASI.json", "w"), ensure_ascii=False, indent=1)
    print(f"baca ulang: raw == dikirim -> {raw == baru} | kata={kata(raw)}")
    print(f"judul tetap={d2['title']['raw'] == judul_lama} slug tetap={d2['slug'] == slug_lama} "
          f"fokus tetap={(d2.get('meta') or {}).get('_yoast_wpseo_focuskw') == fokus} "
          f"metadesc tetap={(d2.get('meta') or {}).get('_yoast_wpseo_metadesc') == meta_desc}")
    assert raw == baru, "isi di server tidak sama dengan yang dikirim"


if __name__ == "__main__":
    main()
