#!/usr/bin/env python3
"""Perbaikan harian tslaw.id 2026-10-11 - post 3228
/cara-mengurus-sertifikat-tanah.htm

Dasar pemilihan (audit drafts/tslaw_audit_selaras.json, snapshot 8 Okt 2026):
- Prioritas 1 sudah habis: 7 artikel yang punya tayangan GSC > 0 / posisi 11-30
  (3065, 3057, 3233, 3208, 3230, 2940, 2823) semuanya sudah digarap 2-8 Okt 2026.
  GSC/GA4 live tetap tidak bisa ditarik: token OAuth atun dicabut (invalid_grant),
  sudah diuji ulang hari ini.
- Prioritas 2 = artikel 600-900 kata. Yang belum digarap dan permintaannya paling
  kuat: #3228 (619 kata tanpa skema, 774 kata metrik audit, 2 sesi GA4 90 hari).
  #3232 (18 sesi) dan #3234 (10 sesi) sudah dikerjakan 9 dan 10 Okt 2026.

Perbaikan HARI INI = panjangkan artikel ke 1.000+ kata dengan isi baru yang
berguna: konversi girik/letter C/petok D, balik nama karena waris, cara mengecek
status berkas, dan pajak yang muncul saat balik nama. Judul, slug, meta, fokus
keyword, tombol WhatsApp, dan skema FAQPage TIDAK diubah karena sudah benar.
Tautan pilar /law-firm-surabaya/ sengaja TIDAK ditambahkan (perbaikan prioritas 5
untuk hari lain, tepat 1 perbaikan per hari).

Satu perbaikan integritas ikut di dalam suntingan yang sama: tautan internal
"Baca juga" menunjuk alamat tanpa .htm yang sekarang 404 (permaiik peralihan
permalink 10 Okt 2026), dibetulkan ke alamat .htm yang benar (sudah dicek 200).

Fakta di isi baru diverifikasi lewat pencarian (tslaw_cek_fakta_20261011.py):
- Tarif pengukuran BPN: luas/500 x HSBku + Rp100.000 untuk luas <= 10 ha.
- BPHTB 5% x (NPOP - NPOPTKP); NPOPTKP ditetapkan daerah (DKI: Rp80 juta
  perolehan pertama, Rp300 juta waris/hibah wasiat).
- PPh final pengalihan hak 2,5% (PP 34/2016).
- Balik nama waris: akta kematian, surat keterangan waris, identitas ahli waris.
- Sentuh Tanahku + Bhumi ATR/BPN untuk cek berkas dan bidang tanah.
- Sertipikat elektronik: Permen ATR/BPN No. 1 Tahun 2021.
- Biaya persiapan PTSL Rp150.000-Rp450.000 per wilayah (atrbpn.go.id).

Jalankan tanpa argumen = dry run. Tambah --apply untuk menulis via REST (JSON).
"""
import base64, html as htmlmod, json, os, re, sys
import urllib.request, urllib.error

WS = "/home/mantapman/.hermes/profiles/atun/workspace"
sys.path.insert(0, WS)
from cfg_tslaw import CFG

AUTH = base64.b64encode(f"{CFG['user']}:{CFG['pass']}".encode()).decode()
BASE = "https://tslaw.id/wp-json/wp/v2"
HDR = {"Authorization": f"Basic {AUTH}", "User-Agent": "Mozilla/5.0"}

PID = 3228
OUT = f"{WS}/tslaw_pemulihan/perbaikan_20261011"
os.makedirs(OUT, exist_ok=True)
APPLY = "--apply" in sys.argv


def rest_get(path, timeout=180):
    req = urllib.request.Request(BASE + path, headers=HDR)
    with urllib.request.urlopen(req, timeout=timeout) as r:
        return json.load(r)


def rest_post(path, payload, timeout=180):
    req = urllib.request.Request(
        BASE + path, data=json.dumps(payload).encode(),
        headers={**HDR, "Content-Type": "application/json"}, method="POST")
    try:
        with urllib.request.urlopen(req, timeout=timeout) as r:
            return r.status, json.load(r)
    except urllib.error.HTTPError as e:
        return e.code, e.read().decode()[:800]


def wc_tanpa_skema(s):
    t = htmlmod.unescape(re.sub(r"<(script|style).*?</\1>", " ", s, flags=re.S))
    return len(re.sub(r"<[^>]+>", " ", t).split())


def wc_audit(s):
    t = htmlmod.unescape(s)
    return len(re.sub(r"<[^>]+>", " ", t).split())


# ---------------------------------------------------------------- tarik sebelum
p = rest_get(f"/posts/{PID}?context=edit")
raw = p["content"]["raw"]
open(f"{OUT}/post_{PID}_SEBELUM.html", "w").write(raw)
json.dump(p, open(f"{OUT}/post_{PID}_SEBELUM.json", "w"), ensure_ascii=False, indent=1)
KATA_SEBELUM = wc_tanpa_skema(raw)
KATA_AUDIT_SEBELUM = wc_audit(raw)
meta0 = p.get("meta") or {}
print(f"[sebelum] kata (tanpa skema) = {KATA_SEBELUM} | kata metrik audit = {KATA_AUDIT_SEBELUM}")
print(f"[sebelum] judul : {p['title']['raw']!r}")
print(f"[sebelum] link  : {p['link']}")
print(f"[sebelum] fokus : {meta0.get('_yoast_wpseo_focuskw')!r} | slug {p['slug']!r} (tidak diubah)")

# ------------------------------------------------------------------ isi tambahan
GIRIK = """<!-- wp:heading -->
<h2 class="wp-block-heading">Tanah Girik, Letter C, dan Petok D: Cara Mengurusnya Menjadi Sertifikat</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Banyak bidang tanah di Jawa masih tercatat dengan girik, letter C, atau petok D. Dokumen semacam itu adalah bukti penguasaan dan pembayaran pajak lama, bukan bukti hak. Karena belum terdaftar di kantor pertanahan, tanahnya lebih mudah diklaim pihak lain, sulit dijadikan agunan, dan bernilai di bawah tanah bersertifikat. Jalan keluarnya adalah pendaftaran tanah pertama kali untuk mengubah status tanah lama itu menjadi Sertifikat Hak Milik.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Tahapannya sebagai berikut:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul class="wp-block-list"><!-- wp:list-item -->
<li>Urus riwayat tanah dan surat keterangan tidak sengketa di kelurahan atau desa setempat.</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Serahkan girik, letter C, atau petok D asli beserta bukti penguasaan lain seperti SPPT PBB tahun terakhir dan akta jual beli lama.</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Ajukan permohonan pendaftaran tanah pertama kali ke kantor pertanahan. Petugas akan mengukur dan memetakan bidang tanah Anda.</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Ikuti pengumuman data yuridis di kelurahan. Pada masa itu pihak lain diberi kesempatan mengajukan sanggahan, dan keberatan harus diselesaikan sebelum sertifikat diterbitkan.</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Setelah masa pengumuman berakhir tanpa sanggahan, sertifikat diterbitkan atas nama pemohon.</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Kalau di wilayah Anda sedang berjalan program Pendaftaran Tanah Sistematis Lengkap (PTSL), ikutkan tanah itu lewat program tersebut. Biaya persiapannya diatur per wilayah, umumnya Rp150.000 sampai Rp450.000, jauh lebih murah daripada pengurusan mandiri, meskipun BPHTB tetap menjadi kewajiban pemohon.</p>
<!-- /wp:paragraph -->"""

WARIS = """<!-- wp:heading -->
<h2 class="wp-block-heading">Mengurus Sertifikat Tanah Warisan</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Tanah warisan sering masih tercatat atas nama pewaris yang sudah meninggal. Selama sertifikat belum dibalik nama, ahli waris tidak bisa menjual atau menjaminkan tanah itu, dan pembagiannya rawan berselisih. Berkas peralihan karena waris lebih sederhana daripada jual beli karena tidak melibatkan transaksi.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Dokumen yang perlu disiapkan:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul class="wp-block-list"><!-- wp:list-item -->
<li>Sertifikat tanah asli atas nama pewaris.</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Akta kematian pewaris yang sudah dilegalisasi.</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>Surat keterangan waris, dapat berupa akta keterangan hak mewaris dari notaris, surat pernyataan ahli waris yang disahkan lurah atau kepala desa, wasiat, atau penetapan pengadilan.</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>KTP dan kartu keluarga seluruh ahli waris.</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>SPPT PBB tahun terakhir sebagai bukti objek pajaknya aktif.</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Persetujuan antar ahli waris menentukan lancar atau tidaknya proses ini. Kalau ada yang menolak pembagian atau keberatan atas porsi warisnya, kantor pertanahan tidak akan memaksakan peralihan hak. Sengketa seperti itu harus diselesaikan lebih dulu lewat musyawarah keluarga, mediasi, atau gugatan ke pengadilan agama bagi yang beragama Islam dan pengadilan negeri untuk lainnya. Kesepakatan atau putusan itulah yang menjadi dasar pendaftaran peralihan haknya.</p>
<!-- /wp:paragraph -->"""

CEK = """<!-- wp:heading -->
<h2 class="wp-block-heading">Cara Mengecek Status Pengurusan dan Kondisi Bidang Tanah</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Setelah berkas diterima, Anda tidak perlu bolak-balik ke kantor pertanahan untuk mengetahui progresnya. Melalui aplikasi Sentuh Tanahku yang disediakan Kementerian ATR/BPN, pemohon bisa memantau tahapan pengurusan berkas dan memeriksa status sertipikat, termasuk memastikan berkasnya benar-benar sudah masuk dan sedang diproses. Untuk melihat apakah suatu bidang tanah sudah terdaftar, layanan peta daring Bhumi ATR/BPN menampilkan batas dan status bidang beserta informasi dasarnya.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Sejak 2021 kantor pertanahan juga menerbitkan sertipikat elektronik berdasarkan Permen ATR/BPN No. 1 Tahun 2021. Dokumen itu ditandatangani secara elektronik dan data yuridisnya tersimpan dalam basis data pertanahan, sehingga data yang tercatat menjadi rujukan utama. Karena itu, sebelum bertransaksi, bandingkan data di sertifikat dengan data di kantor pertanahan. Ketidaksesuaian luas, batas, atau nama pemegang hak jauh lebih mudah dibetulkan sebelum uang berpindah tangan.</p>
<!-- /wp:paragraph -->"""

PAJAK = """<!-- wp:heading -->
<h2 class="wp-block-heading">Pajak yang Muncul saat Balik Nama Tanah</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Di luar biaya pendaftaran, pengukuran, dan jasa PPAT, peralihan hak atas tanah menimbulkan dua pajak. Pembeli menanggung Bea Perolehan Hak atas Tanah dan Bangunan (BPHTB) sebesar 5 persen dari nilai perolehan setelah dikurangi Nilai Perolehan Objek Pajak Tidak Kena Pajak (NPOPTKP). Besaran NPOPTKP ditetapkan masing-masing daerah; di DKI Jakarta, contohnya, Rp80 juta untuk perolehan hak pertama dan Rp300 juta untuk waris atau hibah wasiat.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Pihak penjual menanggung Pajak Penghasilan yang bersifat final sebesar 2,5 persen dari nilai pengalihan sesuai PP No. 34 Tahun 2016. Ada pengecualian, antara lain pengalihan karena waris dan pengalihan dengan nilai sampai Rp60 juta. Bukti setor kedua pajak itu wajib dilampirkan ketika mendaftarkan peralihan hak, sehingga balik nama sering berhenti di tahap verifikasi karena salah satunya belum dibayar.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Biaya pengukuran bidang tanah sampai 10 hektar dihitung dengan rumus luas tanah dibagi 500 dikali Harga Satuan Biaya Khusus pengukuran (HSBKu), lalu ditambah Rp100.000. HSBKu ditetapkan per provinsi, jadi biaya pengukuran tanah 100 m2 di Surabaya berbeda dari daerah lain meskipun rumusnya sama. Karena itu, perkiraan biaya di atas kertas sering meleset untuk tanah yang luasnya belum pernah diukur.</p>
<!-- /wp:paragraph -->"""

KONTEN = raw

# 1) girik/letter C, setelah daftar jenis sertifikat
JANGKAR_A = ('<li><strong>Sertifikat Hak Pakai</strong> \u2014 hak menggunakan tanah untuk keperluan tertentu</li>\n'
             '<!-- /wp:list-item --></ul>\n<!-- /wp:list -->')
assert KONTEN.count(JANGKAR_A) == 1, "jangkar A tidak unik"
KONTEN = KONTEN.replace(JANGKAR_A, JANGKAR_A + "\n\n" + GIRIK, 1)

# 2) waris + cek status, tepat sebelum bagian biaya
JANGKAR_B = '<!-- wp:heading -->\n<h2 class="wp-block-heading">Biaya Mengurus Sertifikat Tanah</h2>'
assert KONTEN.count(JANGKAR_B) == 1, "jangkar B tidak unik"
KONTEN = KONTEN.replace(JANGKAR_B, WARIS + "\n\n" + CEK + "\n\n" + JANGKAR_B, 1)

# 3) pajak, sesudah bagian biaya (sebelum tips)
JANGKAR_C = '<!-- wp:heading -->\n<h2 class="wp-block-heading">Tips agar Proses Pengurusan Lancar</h2>'
assert KONTEN.count(JANGKAR_C) == 1, "jangkar C tidak unik"
KONTEN = KONTEN.replace(JANGKAR_C, PAJAK + "\n\n" + JANGKAR_C, 1)

# 4) perbaikan integritas: tautan internal "Baca juga" masih memakai alamat lama (404)
LAMA = 'https://www.tslaw.id/cara-mengurus-sengketa-tanah-secara-hukum/'
BARU_LINK = 'https://www.tslaw.id/cara-mengurus-sengketa-tanah-secara-hukum.htm'
assert KONTEN.count(LAMA) == 1, "tautan lama tidak unik"
KONTEN = KONTEN.replace(LAMA, BARU_LINK, 1)

KATA_SESUDAH = wc_tanpa_skema(KONTEN)
KATA_AUDIT_SESUDAH = wc_audit(KONTEN)
print(f"\n[kata] tanpa skema {KATA_SEBELUM} -> {KATA_SESUDAH} (+{KATA_SESUDAH - KATA_SEBELUM})")
print(f"[kata] metrik audit {KATA_AUDIT_SEBELUM} -> {KATA_AUDIT_SESUDAH}")
assert KATA_SESUDAH >= 1000, f"target 1.000+ kata belum tercapai ({KATA_SESUDAH})"
assert KATA_SESUDAH <= 1400, f"artikel jadi terlalu panjang ({KATA_SESUDAH})"
assert KATA_SESUDAH > KATA_SEBELUM + 350, "tambahan isi terlalu tipis"

# ------------------------------------------------------------- pemeriksa teks baru
BARU = GIRIK + WARIS + CEK + PAJAK
cekal = {
    "em dash": BARU.count("\u2014"),
    "kutip melengkung": len(re.findall(r"[\u2018\u2019\u201c\u201d]", BARU)),
    "CJK": len(re.findall(r"[\u3000-\u9fff]", BARU)),
    "placeholder": len(re.findall(r"\{[A-Za-z_\[0-9]+\}", BARU)),
    "frasa AI": len(re.findall(r"(Di era digital|Dalam dunia yang|Selain itu|Tak dapat dipungkiri|Pada era|Mari kita|perlu diketahui bahwa)", BARU, re.I)),
    "klaim angka tak berdasar": len(re.findall(r"(\d{2,3}\s?%|pasti menang|100%|dijamin|terbaik di)", BARU, re.I)),
    "emoji": len(re.findall(r"[\U0001F300-\U0001FAFF\u2600-\u27BF]", BARU)),
}
print("[periksa teks baru]", cekal)
assert sum(cekal.values()) == 0, "teks baru tidak lolos pemeriksa"

# fakta kunci harus ada apa adanya (sudah dicek lewat pencarian)
assert "luas tanah dibagi 500 dikali" in PAJAK
assert "PP No. 34 Tahun 2016" in PAJAK
assert "Permen ATR/BPN No. 1 Tahun 2021" in CEK
assert "Rp150.000 sampai Rp450.000" in GIRIK

# ------------------------------------------------------------------ keutuhan lain
for_cek = {
    "tombol WA": KONTEN.count("wa.me/6281909222026"),
    "skema FAQPage": KONTEN.count('"@type": "FAQPage"'),
    "faq blok rank math": KONTEN.count("rank-math-faq-question"),
    "h2": len(re.findall(r"<h2", KONTEN)),
    "h3": len(re.findall(r"<h3", KONTEN)),
    "tautan pilar": KONTEN.count("law-firm-surabaya"),
    "tautan .htm diperbaiki": KONTEN.count(BARU_LINK),
}
print("[utuh]", for_cek)
assert for_cek["tombol WA"] == 1, "tombol WA berubah"
assert for_cek["skema FAQPage"] == 1, "skema FAQPage berubah"
assert for_cek["faq blok rank math"] == 5, "blok FAQ berubah"
assert for_cek["tautan pilar"] == 0, "tautan pilar tidak boleh disentuh hari ini"
assert for_cek["tautan .htm diperbaiki"] == 1, "tautan .htm tidak masuk"

# bukti tidak ada bagian lain tersentuh: balikkan 3 sisipan + 1 tautan -> harus identik
BALIK = (KONTEN.replace("\n\n" + GIRIK, "", 1)
         .replace(WARIS + "\n\n" + CEK + "\n\n", "", 1)
         .replace(PAJAK + "\n\n", "", 1)
         .replace(BARU_LINK, LAMA, 1))
assert BALIK == raw, "ada perubahan di luar sisipan yang direncanakan"
print("[integritas] sisa artikel identik dengan versi sebelum (3 sisipan + 1 tautan)")

if not APPLY:
    open(f"{OUT}/post_{PID}_SESUDAH_dryrun.html", "w").write(KONTEN)
    print("\n[DRY RUN] tidak ada yang dikirim. Jalankan dengan --apply bila sudah benar.")
    sys.exit(0)

payload = {"content": KONTEN}  # judul/meta/slug sengaja tidak dikirim
kode, resp = rest_post(f"/posts/{PID}", payload)
print(f"\n[POST] status {kode}")
json.dump(resp, open(f"{OUT}/post_{PID}_POSTRESP.json", "w"), ensure_ascii=False, indent=1)
if kode != 200:
    print("GAGAL:", resp)
    sys.exit(1)

# ------------------------------------------------------------- baca ulang dari API
q = rest_get(f"/posts/{PID}?context=edit")
raw2 = q["content"]["raw"]
open(f"{OUT}/post_{PID}_SESUDAH.html", "w").write(raw2)
verif = {
    "id": PID, "slug": q["slug"], "status": q["status"], "link": q["link"],
    "modified": q["modified"], "judul": q["title"]["raw"],
    "kata_tanpa_skema_sebelum": KATA_SEBELUM, "kata_tanpa_skema_sesudah": wc_tanpa_skema(raw2),
    "kata_metrik_audit_sebelum": KATA_AUDIT_SEBELUM, "kata_metrik_audit_sesudah": wc_audit(raw2),
    "sisipan_girik": "Tanah Girik, Letter C, dan Petok D" in raw2,
    "sisipan_waris": "Mengurus Sertifikat Tanah Warisan" in raw2,
    "sisipan_cek_online": "Cara Mengecek Status Pengurusan dan Kondisi Bidang Tanah" in raw2,
    "sisipan_pajak": "Pajak yang Muncul saat Balik Nama Tanah" in raw2,
    "tautan_internal_htm": raw2.count(BARU_LINK),
    "tautan_internal_404_sisa": raw2.count(LAMA),
    "faq_utuh": raw2.count('"@type": "FAQPage"') == 1 and raw2.count("rank-math-faq-question") == 5,
    "tombol_wa": raw2.count("wa.me/6281909222026"),
    "h2": len(re.findall(r"<h2", raw2)), "h3": len(re.findall(r"<h3", raw2)),
    "judul_tidak_berubah": q["title"]["raw"] == p["title"]["raw"],
    "slug_tidak_berubah": q["slug"] == p["slug"],
    "identik_di_luar_sisipan": (raw2.replace("\n\n" + GIRIK, "", 1)
                                .replace(WARIS + "\n\n" + CEK + "\n\n", "", 1)
                                .replace(PAJAK + "\n\n", "", 1)
                                .replace(BARU_LINK, LAMA, 1)) == raw,
}
json.dump(verif, open(f"{OUT}/post_{PID}_VERIFIKASI.json", "w"), ensure_ascii=False, indent=1)
print("[verifikasi REST]", json.dumps(verif, ensure_ascii=False, indent=1))
