#!/usr/bin/env python3
"""TSC — artikel harian: «PMS Tanpa Gejala: Kenapa Pemeriksaan Tetap Perlu Dilakukan».

Topik dari tsc_topik_bank.json entri "Gejala PMS yang Perlu Diperiksa ke Dokter".
Judul aslinya BENTURAN 0,40 dengan #10356, jadi sudutnya digeser ke infeksi tanpa
gejala (hasil tsc_cek_topik.py: aman, skor tertinggi 0,12).

Alur: draf (REST) -> gambar unggulan (desain sendiri 1000x567 webp) -> meta Yoast
(XML-RPC, kirim ulang seluruh custom field) -> jadwalkan 2026-10-27 08:00 WIB
(zona situs UTC, jadi 01:00).

Pakai --apply untuk benar-benar mengerjakan.
"""
import json
import os
import re
import sys
import time

WS = "/home/mantapman/.hermes/profiles/atun/workspace"
sys.path.insert(0, WS)
from tsc_http import CFG, rest_json, xmlrpc_call  # noqa: E402

DOM = CFG["domain"]
USER, SANDI = CFG["user"], CFG["pass"]

JUDUL = "PMS Tanpa Gejala: Kenapa Pemeriksaan Tetap Perlu Dilakukan"
SLUG = "pms-tanpa-gejala-pemeriksaan-tetap-perlu"
FOKUS = "gejala pms"
META_JUDUL = "PMS Tanpa Gejala: Kenapa Pemeriksaan Tetap Perlu"
META_DESC = ("Tidak semua PMS menimbulkan gejala. Kenali kenapa infeksi tanpa gejala tetap "
             "perlu diperiksa, kapan waktu tes yang tepat, dan apa saja yang dicek di klinik.")
TANGGAL = "2026-10-27T01:00:00"   # 08:00 WIB (zona situs UTC)
GAMBAR = f"{WS}/tsc_feat_pms_tanpa_gejala.webp"
ALT_GAMBAR = "Ilustrasi artikel PMS tanpa gejala di The Skin Code Clinic Krian"

WA = ("https://wa.me/6285117444417?text=Saya%20ingin%20konsultasi%20masalah%20kulit%20di%20The%20Skin"
      "%20Code%20Clinic")
TOMBOL = ('<p style="text-align:center;margin:32px 0 8px"><a class="wp-block-button__link '
          'wp-element-button" href="' + WA + '" target="_blank" rel="noopener" '
          'style="display:inline-block;background-color:#0f2557;color:#ffffff;padding:15px 34px;'
          'font-size:18px;font-weight:bold;text-decoration:none;border-radius:6px;">'
          'KONSULTASI GRATIS</a></p>')

ISI = """
<p>Anda datang ke klinik dengan satu pertanyaan sederhana: apakah saya terinfeksi? Tidak ada luka,
tidak ada nyeri, tidak ada keluhan yang bisa Anda tunjuk. Justru karena itu, pertanyaannya terasa
berlebihan. Sebagian orang memilih pulang dan menunggu gejala muncul. Padahal pada banyak kasus,
gejala itu tidak pernah muncul.</p>

<p>PMS, atau penyakit menular seksual, tidak selalu datang dengan tanda yang kelihatan. Infeksi bisa
berjalan berbulan-bulan tanpa keluhan, sementara tubuh tetap bisa menularkan ke pasangan. Ada juga
orang yang merasakan gejala ringan, menganggapnya sariawan biasa atau iritasi karena
sabun, lalu melupakannya. Dua kelompok ini sama-sama berakhir di ruang periksa dengan pertanyaan
yang sama: apa yang sebenarnya terjadi.</p>

<h2>Kenapa infeksi menular seksual bisa berjalan tanpa gejala</h2>
<p>Gejala muncul ketika tubuh bereaksi terhadap kuman. Reaksi itu tidak selalu berupa rasa sakit.
Pada banyak infeksi, peradangan berjalan pelan di permukaan lendir yang tidak punya banyak ujung
saraf, sehingga tidak ada yang bisa dirasakan.</p>

<p>Klamidia dan gonore termasuk contoh yang paling sering. Pada perempuan, keduanya kerap hanya
menimbulkan keputihan yang tidak khas, dan sering tidak menimbulkan keluhan sama sekali. Pada
laki-laki, keluhan biasanya lebih terasa, tetapi tidak jarang juga ringan. Sifilis punya pola lain:
luka awal muncul sebentar, tidak nyeri, lalu hilang sendiri, sementara kumannya tetap ada di dalam
tubuh. Fasenya bisa berlanjut tanpa tanda yang jelas selama bertahun-tahun.</p>

<p>HIV juga bisa tanpa gejala selama bertahun-tahun sebelum sistem imun melemah. HPV sering hanya
terdeteksi lewat pemeriksaan, karena kutil bisa sangat kecil atau berada di area yang tidak terlihat.
Herpes bisa menular saat tidak ada luka yang tampak, meski risikonya lebih rendah dibanding saat luka
terbuka.</p>

<p>Tidak adanya keluhan bukan bukti tidak adanya infeksi.</p>

<h2>Gejala ringan yang sering diabaikan</h2>
<p>Selain kasus tanpa gejala sama sekali, ada kelompok keluhan yang sebenarnya terasa tetapi
dianggap biasa. Berikut yang paling sering muncul di ruang periksa:</p>

<ul>
<li>Keputihan yang berubah warna, bau, atau jumlahnya, terutama bila disertai gatal.</li>
<li>Nyeri atau panas saat berkemih yang hilang timbul.</li>
<li>Luka kecil di area kelamin atau mulut yang sembuh sendiri dalam beberapa hari.</li>
<li>Bercak, kutil, atau tonjolan kecil yang tidak nyeri.</li>
<li>Nyeri panggul atau perdarahan di luar siklus haid.</li>
<li>Gatal atau kemerahan yang datang lagi setelah diobati sendiri.</li>
</ul>

<p>Daftar itu bukan alat diagnosis. Anggap saja sebagai pengingat untuk memeriksakan hal yang selama
ini Anda tunda. Artikel
<a href="https://www.theskincodeclinic.com/tanda-awal-pms-yang-perlu-diwaspadai-3/">tanda awal PMS
yang perlu diwaspadai</a> membahas tiap gejala dengan lebih rinci.</p>

<h2>Jendela waktu pemeriksaan yang perlu Anda tahu</h2>
<p>Ini bagian yang paling sering membuat hasil tes menyesatkan. Tubuh butuh waktu untuk menghasilkan
penanda yang bisa dideteksi, dan lama waktunya berbeda untuk setiap infeksi. Kalau Anda memeriksa
terlalu cepat setelah hubungan berisiko, hasilnya bisa negatif padahal infeksinya ada.</p>

<p>Sebagai gambaran, pemeriksaan klamidia dan gonore umumnya memberi hasil yang bisa dipercaya
sekitar dua minggu setelah kontak. Sifilis biasanya diperiksa lewat darah dengan masa tunggu sekitar
empat sampai enam minggu. HIV dengan tes antibodi generasi terbaru umumnya akurat pada dua sampai
enam minggu, sedangkan tes generasi lama membutuhkan waktu sampai tiga bulan untuk kepastian. Karena
itu, dokter akan menanyakan kapan kontak terakhir terjadi sebelum menentukan waktu pemeriksaan. Pola
sifilis yang bertahap dijelaskan di halaman
<a href="https://www.theskincodeclinic.com/tahapan-sifilis-awal-hingga-lanjutan-3/">tahapan sifilis
dari awal hingga lanjutan</a>.</p>

<p>Kalau hasil pertama negatif tetapi keluhan atau riwayat Anda tetap mengarah ke infeksi, tes ulang
setelah selang waktu biasanya disarankan. Itu bukan tanda tesnya tidak bisa dipercaya, melainkan
bagian dari cara kerja pemeriksaan itu sendiri.</p>

<h2>Apa yang diperiksa saat Anda datang</h2>
<p>Pemeriksaan dimulai dari percakapan. Dokter akan menanyakan keluhan, kapan mulai, riwayat kontak,
penggunaan kondom, dan riwayat infeksi sebelumnya. Pertanyaan ini terasa pribadi karena memang harus
pribadi. Tanpa jawaban yang jujur, pilihan pemeriksaan bisa meleset.</p>

<p>Setelah itu dokter memeriksa kulit dan selaput lendir di area yang relevan, termasuk mulut dan
tenggorokan bila riwayatnya mengarah ke sana. Pemeriksaan penunjang menyesuaikan temuan, bukan paket
seragam untuk semua orang. Yang umum dipakai adalah swab atau sampel urin untuk klamidia dan gonore,
tes darah untuk sifilis dan HIV, serta pemeriksaan apusan bila ada keluhan keputihan atau luka.</p>

<p>Hasil sebagian tes keluar di hari yang sama, sebagian butuh beberapa hari. Dokter akan menjelaskan
arti hasil tersebut, termasuk kemungkinan hasil negatif palsu seperti yang sudah dibahas di atas,
sebelum menyusun rencana penanganan. Kalau Anda ingin tahu dulu layanan yang tersedia, halaman
<a href="https://www.theskincodeclinic.com/dokter-kulit-dan-kelamin-krian-untuk-jerawat-gatal-pms/">dokter
kulit dan kelamin Krian</a> merangkum cakupannya.</p>

<h2>Rasa malu yang menunda pemeriksaan</h2>
<p>Alasan paling sering bukan biaya dan bukan jarak. Banyak orang menunda karena takut dihakimi. Ini
wajar, dan tidak perlu Anda lawan sendirian di ruang tunggu. Yang bisa Anda lakukan adalah memastikan
tempat yang Anda pilih memang menangani kasus seperti ini setiap hari, sehingga percakapannya berjalan
biasa saja tanpa komentar yang membuat tidak nyaman.</p>

<p>Kerahasiaan juga layak ditanyakan di awal. Klinik yang baik akan menjelaskan siapa yang bisa
mengakses rekam medis Anda dan bagaimana hasil pemeriksaan disampaikan. Untuk infeksi menular
seksual, hasil hanya dibicarakan dengan Anda, kecuali Anda memberi izin lain.</p>

<p>Hal praktis lain yang membantu: datang tanpa mengoles krim atau obat di area yang dikeluhkan,
jangan berkemih satu sampai dua jam sebelum pengambilan sampel urin, dan catat kapan keluhan pertama
muncul. Kalau Anda masih memakai obat dari kunjungan sebelumnya, bawa daftarnya. Alur pendaftaran dan
hal yang perlu dibawa diuraikan di halaman
<a href="https://www.theskincodeclinic.com/dokter-kulit-sidoarjo-panduan-berobat/">panduan berobat
dokter kulit Sidoarjo</a>.</p>

""" + TOMBOL + """

<h2>Pertanyaan yang sering diajukan</h2>

<h3>Apakah saya perlu tes kalau tidak ada keluhan?</h3>
<p>Kalau Anda pernah melakukan hubungan berisiko tanpa pengaman, pemeriksaan tetap layak
dipertimbangkan meski tanpa keluhan. Keputusannya diambil setelah dokter mendengar riwayat Anda,
karena jenis tes dan waktunya bergantung pada hal itu.</p>

<h3>Apakah hasil tes negatif berarti pasti tidak terinfeksi?</h3>
<p>Tidak selalu, terutama kalau tes dilakukan terlalu cepat. Tes ulang setelah jendela waktu yang
sesuai memberi gambaran lebih akurat. Beberapa infeksi juga butuh jenis pemeriksaan berbeda, sehingga
satu tes tidak menyingkirkan semuanya.</p>

<h3>Apakah pasangan juga harus diperiksa?</h3>
<p>Pada banyak kasus, ya. Kalau hanya satu pihak yang ditangani, infeksi bisa kembali lagi setelah
pengobatan selesai. Dokter biasanya membahas cara memberi tahu pasangan dengan cara yang Anda rasa
paling nyaman.</p>

<h3>Apakah PMS bisa disembuhkan?</h3>
<p>Bergantung jenisnya. Infeksi bakteri seperti klamidia, gonore, dan sifilis ditangani dengan
antibiotik sesuai indikasi dokter. Infeksi virus seperti herpes dan HIV tidak bisa dihilangkan
sepenuhnya, tetapi gejalanya bisa dikendalikan lewat pengobatan berkelanjutan. Yang perlu Anda ingat,
penanganan mengikuti hasil pemeriksaan, bukan dugaan.</p>

<p>Memeriksa diri saat tidak ada keluhan memang terasa berlebihan, sampai Anda ingat bahwa sebagian
infeksi tidak memberi tanda apa pun. Pencegahan tetap jadi langkah pertama, dan langkah itu bisa Anda
mulai sekarang lewat halaman
<a href="https://www.theskincodeclinic.com/cara-mencegah-penularan-pms-3/">cara mencegah penularan
PMS</a>.</p>

<p>Di The Skin Code Clinic Krian, pemeriksaan dimulai dari percakapan tentang riwayat Anda, lalu
dilanjutkan pemeriksaan kulit dan pemeriksaan penunjang yang sesuai. Kalau Anda masih ragu apakah
keluhan atau riwayat Anda perlu diperiksa, tanyakan dulu lewat tombol di atas.</p>
"""


def baca(p, method="GET", data=None):
    return rest_json(method, p, data=data)


teks = re.sub(r"<[^>]+>", " ", ISI)
kata = len(teks.split())
print(f"=== {JUDUL}")
print(f"   kata: {kata} (target 1.000-1.300)")
print(f"   meta judul: {len(META_JUDUL)} char (maks 60) · meta desc: {len(META_DESC)} char (140-158)")
print(f"   tombol WA: {'ada' if 'wa.me' in ISI else 'TIDAK ADA'}")
print(f"   tautan internal: {len(re.findall('theskincodeclinic.com', ISI))}")
print(f"   sub-judul H2: {ISI.count('<h2')} · H3: {ISI.count('<h3')}")
print(f"   tanggal jadwal: {TANGGAL} (08:00 WIB)")

if kata < 1000 or kata > 1300:
    sys.exit("   PANJANG TIDAK SESUAI BAKU - perbaiki dulu")
if len(META_JUDUL) > 60 or not (140 <= len(META_DESC) <= 158):
    sys.exit("   META TIDAK SESUAI BAKU - perbaiki dulu")

if "--apply" not in sys.argv:
    print("\n(dry run - pakai --apply)")
    sys.exit(0)

# ---------- 1. buat draf ----------
st, d = baca("/wp-json/wp/v2/posts", "POST", {"title": JUDUL, "slug": SLUG, "content": ISI,
                                              "status": "draft", "comment_status": "closed"})
if not isinstance(d, dict) or "id" not in d:
    sys.exit(f"   GAGAL buat draf: {st} {str(d)[:200]}")
PID = d["id"]
print(f"\n[1] draf #{PID} -> {d.get('link')} · status={d.get('status')}")

# ---------- 2. gambar unggulan ----------
try:
    from PIL import Image, ImageDraw, ImageFont
    FONTS = os.path.expanduser("~/.fonts")
    NAVY, BIRU, ABU, PUTIH, BIRU_MUDA = (11, 31, 58), (30, 64, 175), (100, 116, 139), (255, 255, 255), (219, 234, 254)
    W, H, PAD = 1000, 567, 62
    fon = lambda n, s: ImageFont.truetype(os.path.join(FONTS, n), s)

    def bungkus(t, font, maks):
        baris, kini = [], ""
        for k in t.split():
            c = (kini + " " + k).strip()
            if font.getlength(c) <= maks:
                kini = c
            else:
                if kini:
                    baris.append(kini)
                kini = k
        if kini:
            baris.append(kini)
        return baris

    img = Image.new("RGB", (W, H), PUTIH)
    dr = ImageDraw.Draw(img)
    panel = int(W * 0.34)
    dr.rectangle([W - panel, 0, W, H], fill=BIRU)
    cx, cy = W - panel // 2, H // 2
    # motif: papan periksa (lembar dengan centang)
    dr.rounded_rectangle([cx - 78, cy - 96, cx + 78, cy + 96], radius=14, outline=PUTIH, width=4)
    for i in range(3):
        y = cy - 52 + i * 48
        dr.ellipse([cx - 54, y - 11, cx - 32, y + 11], outline=PUTIH, width=3)
        dr.line([cx - 18, y, cx + 46, y], fill=PUTIH, width=4)
    dr.rectangle([0, 0, 10, H], fill=BIRU)
    dr.text((PAD, PAD - 6), "THE SKIN CODE CLINIC", font=fon("Poppins-SemiBold.ttf", 24), fill=BIRU)
    dr.text((PAD, PAD + 26), "Krian, Sidoarjo", font=fon("Poppins-Regular.ttf", 20), fill=ABU)
    maks = W - panel - PAD - 46
    y = 148
    for b in bungkus("PMS Tanpa Gejala", fon("Poppins-Bold.ttf", 54), maks):
        dr.text((PAD, y), b, font=fon("Poppins-Bold.ttf", 54), fill=NAVY)
        y += 66
    y += 6
    for b in bungkus("Kenapa pemeriksaan tetap perlu", fon("Poppins-Regular.ttf", 26), maks):
        dr.text((PAD, y), b, font=fon("Poppins-Regular.ttf", 26), fill=ABU)
        y += 36
    dr.rectangle([PAD, H - 96, PAD + 74, H - 92], fill=BIRU)
    dr.text((PAD, H - 78), "theskincodeclinic.com", font=fon("Poppins-SemiBold.ttf", 23), fill=NAVY)
    dr.text((PAD, H - 46), "Konsultasi lewat WhatsApp · 0851-1744-4417",
            font=fon("Poppins-Regular.ttf", 20), fill=ABU)
    img.save(GAMBAR, "WEBP", quality=92, method=6)
    print(f"[2] gambar: {GAMBAR} {img.size} {os.path.getsize(GAMBAR)//1024} KB")

    data = open(GAMBAR, "rb").read()
    nama = os.path.basename(GAMBAR)
    stm, med = rest_json("POST", "/wp-json/wp/v2/media", binary=data, content_type="image/webp",
                         extra_headers={"Content-Disposition": f'attachment; filename="{nama}"'})
    if not isinstance(med, dict) or "id" not in med:
        raise RuntimeError(f"unggah media gagal: {stm} {str(med)[:200]}")
    print(f"    unggah media #{med['id']} -> {med.get('source_url')}")
    baca(f"/wp-json/wp/v2/media/{med['id']}", "POST",
         {"alt_text": ALT_GAMBAR, "title": f"Gambar unggulan: {JUDUL}"})
    baca(f"/wp-json/wp/v2/posts/{PID}", "POST", {"featured_media": med["id"]})
    time.sleep(2)
    _, cekp = baca(f"/wp-json/wp/v2/posts/{PID}?context=edit&_fields=featured_media")
    print(f"    featured_media tersimpan: {cekp.get('featured_media') if isinstance(cekp, dict) else cekp}")
    _, cekm = baca(f"/wp-json/wp/v2/media/{med['id']}?context=edit&_fields=alt_text")
    print(f"    alt_text tersimpan: {str(cekm)[:160]}")
except Exception as e:
    print(f"[2] gambar unggulan GAGAL: {str(e)[:200]} - lanjut tanpa gambar")

# ---------- 3. meta Yoast via XML-RPC (kirim ulang seluruh custom field) ----------
try:
    p = xmlrpc_call("wp.getPost", [0, USER, SANDI, PID])
    cf = p.get("custom_fields", [])
    print(f"[3] custom field lama: {len(cf)} -> {[x.get('key') for x in cf]}")
    baru = {x["key"]: x["value"] for x in cf}
    baru["_yoast_wpseo_title"] = META_JUDUL
    baru["_yoast_wpseo_metadesc"] = META_DESC
    baru["_yoast_wpseo_focuskw"] = FOKUS
    kirim = [{"key": k, "value": v} for k, v in baru.items()]
    xmlrpc_call("wp.editPost", [0, USER, SANDI, PID, {"custom_fields": kirim}])
    time.sleep(2)
    p2 = xmlrpc_call("wp.getPost", [0, USER, SANDI, PID])
    v = {x["key"]: x["value"] for x in p2.get("custom_fields", [])}
    print(f"    tersimpan: title={v.get('_yoast_wpseo_title')!r}")
    print(f"               desc={v.get('_yoast_wpseo_metadesc')!r}")
    print(f"               focuskw={v.get('_yoast_wpseo_focuskw')!r}")
    print(f"    jumlah field setelah tulis: {len(v)}")
except Exception as e:
    print(f"[3] meta Yoast GAGAL: {str(e)[:200]}")

# ---------- 4. jadwalkan ----------
sts, ds = baca(f"/wp-json/wp/v2/posts/{PID}", "POST", {"status": "future", "date": TANGGAL})
print(f"[4] jadwalkan: HTTP {sts}")
time.sleep(3)
_, akhir = baca(f"/wp-json/wp/v2/posts/{PID}?context=edit"
                f"&_fields=id,status,date,date_gmt,slug,link,featured_media,title")
if isinstance(akhir, dict):
    print(f"    status={akhir.get('status')} · date={akhir.get('date')} · slug={akhir.get('slug')}")
    print(f"    featured_media={akhir.get('featured_media')}")
    _, isi = baca(f"/wp-json/wp/v2/posts/{PID}?context=edit&_fields=content")
    html = ((isi or {}).get("content") or {}).get("raw", "") if isinstance(isi, dict) else ""
    print(f"    isi: {len(html)} char · tombol WA: "
          f"{'ada' if 'wa.me/6285117444417' in html else 'TIDAK ADA'} · sub-judul h2: {html.count('<h2')}")
else:
    print(f"    baca balik gagal: {akhir}")
print(f"\npost #{PID} · {akhir.get('link') if isinstance(akhir, dict) else ''}")
print("JSON:", json.dumps({"id": PID, "slug": (akhir or {}).get("slug") if isinstance(akhir, dict) else None,
                           "date": (akhir or {}).get("date") if isinstance(akhir, dict) else None,
                           "status": (akhir or {}).get("status") if isinstance(akhir, dict) else None}))
