#!/usr/bin/env python3
"""Gelombang 5 klaster serbuk Yasma: pilar legalitas #3698 (gabung #3034) + pilar MOQ #3346.
GUARD: hanya post."""
import base64, html, importlib.util, json, os, re, sys, time, urllib.request, urllib.error

S = "https://yasmanatura.co.id"
AUTH = base64.b64encode(b"bambangbot:LFp4 LXBh kMYG 84qC 2DDc 5bLc").decode()
PILAR_LEG = 3698
PILAR_MOQ = 3346
BUANG = [3034]
GEL2 = "https://yasmanatura.co.id/maklon-minuman-serbuk-indonesia-yasma-natura-partner-maklon-nasional-untuk-produk-minuman-kesehatan/"
GEL3 = "https://yasmanatura.co.id/10-cara-buat-brand-minuman-serbuk-sendiri-lewat-jasa-maklon-yasma-natura/"

WA = """
<style>
.ss-cta-wa{display:inline-flex;align-items:center;gap:10px;background-color:#6878d6;color:#ffffff !important;
font-family:'Open Sans',sans-serif;font-weight:600;font-size:17px;padding:15px 30px;border-radius:8px;
text-decoration:none !important;line-height:1.2;box-shadow:0 2px 8px rgba(104,120,214,.35)}}
.ss-cta-wa:hover{background-color:#4d61d6;color:#ffffff !important}
</style>
<p style="text-align:center;margin:34px 0 6px">
<a class="ss-cta-wa" href="https://wa.me/6281939119209?text=Halo%20Yasma%20Natura%2C%20saya%20ingin%20konsultasi%20produksi%20minuman%20serbuk" target="_blank" rel="noopener" role="button">WhatsApp: Konsultasi Gratis</a>
</p>
<p style="text-align:center;font-size:14px;color:#5b5b6b;margin:0 0 26px">Ceritakan rencana produk Anda, tim kami bantu menaksir biaya dan waktu produksinya.</p>
"""

LEG = {
    "judul": "Legalitas Produk Minuman Serbuk: Izin Edar, BPOM, dan Sertifikasi Halal",
    "fk": "legalitas produk minuman serbuk",
    "meta": ("Legalitas produk minuman serbuk: alur izin edar BPOM, sertifikasi Halal, informasi wajib di kemasan, "
             "dan dokumen yang perlu disiapkan brand sebelum produksi."),
    "isi": """
<p>Legalitas produk minuman serbuk menentukan apakah produk Anda boleh dijual resmi atau tidak. Untuk kategori minuman kesehatan, ada dua hal utama yang harus diurus: izin edar dari BPOM dan sertifikasi Halal. Keduanya sebaiknya dimulai bersamaan dengan penyusunan formula, bukan setelah produk selesai diproduksi, karena bisa memengaruhi desain kemasan dan komposisi bahan.</p>

<h2>Kenapa legalitas tidak bisa ditunda</h2>
<p>Produk tanpa izin edar tidak bisa masuk ke ritel modern, tidak bisa ikut program promosi platform besar, dan berisiko ditarik dari peredaran. Selain itu, mengurus izin setelah produk diproduksi sering memaksa perubahan kemasan — artinya biaya cetak terbuang dua kali. Menempatkan legalitas di awal justru menghemat waktu dan uang.</p>

<h2>Izin edar BPOM: apa dan untuk apa</h2>
<p>Izin edar adalah persetujuan pemerintah bahwa produk memenuhi syarat keamanan dan mutu pangan olahan. Untuk produk yang diproduksi pihak lain, izin diterbitkan atas nama brand dengan mencantumkan produsen atau penyedia maklon yang bersangkutan. Karena itu, pastikan penyedia maklon Anda memang memiliki fasilitas dan perizinan yang sesuai — ini pertanyaan pertama yang layak diajukan sebelum menandatangani kerja sama.</p>

<h2>Sertifikasi Halal</h2>
<p>Sertifikasi Halal memastikan bahan, proses produksi, dan fasilitasnya memenuhi ketentuan. Untuk produk pangan olahan di Indonesia, sertifikasi ini menjadi kebutuhan pasar yang nyata, bukan sekadar nilai tambah: banyak pembeli menyaring produk berdasarkan label Halal sebelum melihat hal lain. Prosesnya menuntut kejelasan asal bahan dan keterpisahan jalur produksi.</p>

<h2>Informasi wajib pada kemasan</h2>
<p>Kemasan harus memuat nama produk, komposisi, berat bersih, nama dan alamat produsen, kode produksi, serta tanggal kedaluwarsa. Untuk produk tertentu ditambahkan keterangan cara penyajian dan peringatan bagi kelompok yang perlu berhati-hati. Semua keterangan ini sebaiknya sudah masuk desain kemasan sejak awal supaya tidak ada pencetakan ulang.</p>

<h2>Dokumen yang perlu disiapkan brand</h2>
<p>Empat kelompok dokumen yang biasanya diminta: identitas badan usaha atau brand, rancangan kemasan lengkap dengan keterangannya, rincian komposisi beserta asal bahan, dan data fasilitas produksi. Kelengkapan dokumen inilah yang paling menentukan cepat atau lambatnya proses, karena pemeriksaan berhenti ketika ada bagian yang kurang.</p>

<h2>Peran penyedia maklon dalam pengurusan izin</h2>
<p>Penyedia maklon menyiapkan data produksi dan fasilitas, membantu penyusunan komposisi, serta mendampingi komunikasi teknis selama pemeriksaan. Brand tetap bertanggung jawab atas nama produk dan pemasarannya. Pembagian peran ini penting disepakati di awal supaya tidak ada bagian yang saling menunggu.</p>

<h2>Batas klaim manfaat</h2>
<p>Produk pangan olahan tidak boleh diklaim menyembuhkan penyakit. Kalimat yang aman menyebut fungsi bahan secara wajar, misalnya membantu memelihara kesehatan pencernaan atau melengkapi asupan serat harian. Klaim berlebihan bukan hanya berisiko saat pengurusan izin, tapi juga merusak kepercayaan pembeli ketika hasilnya tidak sesuai harapan.</p>

<h2>Kesalahan yang membuat proses tertunda</h2>
<p>Mendesain kemasan sebelum komposisi final. Mengubah komposisi di tengah proses pengurusan. Memilih pemasok bahan tanpa dokumen pendukung. Dan menganggap legalitas bisa diurus setelah produk dijual — cara ini hampir selalu berakhir dengan produk ditarik dari penjualan.</p>

<h2>Urutan yang realistis</h2>
<p>Tetapkan komposisi dan formula lebih dulu, siapkan dokumen brand, finalkan desain kemasan, lalu jalankan proses izin edar dan sertifikasi bersamaan. Setelah keduanya terbit, produksi jumlah penuh baru dijalankan. Urutan ini memastikan tidak ada pekerjaan yang diulang.</p>

<h2>Pertanyaan yang sering muncul</h2>
<h3>Siapa yang mengurus izin edar, brand atau penyedia maklon?</h3><p>Keduanya bekerja bersama. Penyedia menyiapkan data produksi dan fasilitas, sementara brand menyiapkan identitas produk dan bertanggung jawab atas pemasaran.</p>
<h3>Apakah produk harus punya izin edar sebelum dijual?</h3><p>Ya, untuk produk pangan olahan yang dijual resmi, termasuk agar bisa masuk ke ritel dan platform penjualan besar.</p>
<h3>Berapa lama proses legalitas sampai terbit?</h3><p>Bergantung kelengkapan dokumen dan jadwal pemeriksaan. Karena itu dokumen disiapkan sejak awal, bukan setelah produksi selesai.</p>
<h3>Apakah boleh mengubah komposisi setelah izin terbit?</h3><p>Perubahan komposisi umumnya memerlukan penyesuaian perizinan. Karena itu formula sebaiknya dimatangkan sebelum proses pengurusan dimulai.</p>
<h3>Apakah label Halal wajib?</h3><p>Untuk produk pangan olahan di Indonesia, sertifikasi Halal menjadi kebutuhan pasar yang kuat. Banyak pembeli menyaring produk berdasarkan label ini sebelum mempertimbangkan hal lain.</p>
""",
}

MOQ = {
    "judul": "MOQ Maklon Minuman Serbuk: Cara Menentukan Jumlah Produksi Pertama",
    "fk": "moq maklon minuman serbuk",
    "meta": ("MOQ maklon minuman serbuk dan cara menentukan jumlah produksi pertama: faktor yang mempengaruhinya, "
             "hitungan modal, dan pilihan bila anggaran terbatas."),
    "isi": """
<p>MOQ, atau minimum order quantity, adalah jumlah produksi paling kecil yang bisa diterima penyedia maklon. Angka ini berbeda-beda tergantung jenis produk, ukuran kemasan, dan cara produksinya. Bagi pemilik brand baru, memahami MOQ penting karena menentukan berapa modal awal yang harus disiapkan dan berapa lama stok akan bertahan.</p>

<h2>Kenapa MOQ ada</h2>
<p>Setiap kali produksi dijalankan, ada biaya penyiapan yang tidak tergantung jumlah: mencuci dan menyetel mesin, menimbang bahan, menguji hasil, dan membersihkan jalur produksi. Biaya ini dibagi ke jumlah unit yang diproduksi. Kalau produksinya sangat sedikit, biaya per unit menjadi mahal. Itulah alasan penyedia menetapkan batas minimum.</p>

<h2>Faktor yang menentukan besar MOQ</h2>
<p><strong>Jenis produk.</strong> Formula dengan banyak bahan dan tahap pencampuran biasanya ber-MOQ lebih besar. <strong>Ukuran kemasan.</strong> Kemasan sachet kecil memungkinkan MOQ unit lebih banyak dengan berat bahan yang sama. <strong>Bahan baku.</strong> Bahan yang hanya dijual dalam kemasan besar memaksa pembelian minimum tertentu. <strong>Mesin dan antrean produksi.</strong> Jadwal produksi yang padat membuat penyedia menetapkan minimum agar slotnya efisien.</p>

<h2>MOQ besar: lebih murah, tapi berisiko</h2>
<p>Harga per unit biasanya turun pada jumlah besar, dan itu menggoda. Namun ada dua risiko yang sering diabaikan: modal terikat pada stok yang belum tentu terjual, dan produk yang sudah diproduksi tetap harus disimpan dengan benar agar tidak rusak. Untuk brand baru yang belum tahu kecepatan penjualannya, mengunci modal di jumlah besar adalah pilihan yang berbahaya.</p>

<h2>Cara menentukan jumlah produksi pertama</h2>
<p>Mulai dari perkiraan penjualan harian yang realistis, bukan dari harapan. Kalikan dengan masa uji yang Anda inginkan — biasanya dua sampai tiga bulan — lalu sesuaikan dengan MOQ yang tersedia. Kalau angka Anda lebih kecil dari MOQ, jangan naikkan jumlahnya otomatis; pertimbangkan dulu pilihan di bagian berikutnya.</p>

<h2>Hitungan modal dan perputaran stok</h2>
<p>Hitung tiga hal sebelum memutuskan: total biaya produksi batch pertama, biaya kemasan termasuk minimum cetak, dan biaya pengenalan produk seperti foto dan materi promosi. Setelah itu perkirakan berapa lama stok akan habis pada kecepatan penjualan saat ini. Kalau perkiraan itu lebih dari enam bulan, jumlah produksinya kemungkinan terlalu besar untuk tahap awal.</p>

<h2>Kalau MOQ terasa terlalu besar</h2>
<p>Ada empat penyesuaian yang biasanya bisa dibicarakan. <strong>Satu</strong>, memilih ukuran kemasan lebih kecil agar jumlah unit lebih banyak dengan berat bahan sama. <strong>Dua</strong>, mengurangi jumlah varian pada produksi pertama. <strong>Tiga</strong>, memilih kombinasi bahan yang lebih sederhana. <strong>Empat</strong>, memulai dari satu jenis kemasan saja. Sampaikan kendala anggaran Anda secara terbuka — penyedia yang berpengalaman biasanya punya pengalaman menyesuaikan rencana produksi.</p>

<h2>Kesalahan umum soal MOQ</h2>
<p>Menyamakan harga per unit termurah dengan keputusan terbaik. Mengabaikan biaya penyimpanan. Memesan beberapa varian sekaligus padahal permintaan belum terbukti. Dan tidak menanyakan apa saja yang termasuk dalam hitungan MOQ — terkadang bahan dan kemasan dihitung terpisah.</p>

<h2>Kapan menambah jumlah produksi</h2>
<p>Empat tanda yang bisa dipakai sebagai patokan: stok habis sebelum jadwal produksi berikutnya, ada pembelian ulang dari pembeli yang sama, ada permintaan restok dari reseller, dan biaya produksi per unit masih sesuai rencana. Kalau tiga dari empat tanda ini muncul, menambah jumlah produksi biasanya aman.</p>

<h2>Pertanyaan yang sering muncul</h2>
<h3>Berapa MOQ maklon minuman serbuk pada umumnya?</h3><p>Berbeda untuk setiap penyedia dan jenis produk. Karena itu, sebutkan rencana produk Anda dan minta angka minimumnya secara tertulis sejak awal.</p>
<h3>Apakah MOQ bisa dinegosiasikan?</h3><p>Bisa, terutama pada produksi pertama. Cara yang biasanya berhasil adalah menyesuaikan ukuran kemasan atau mengurangi jumlah varian, bukan meminta potongan harga.</p>
<h3>Apa saja yang dihitung dalam MOQ?</h3><p>Tergantung kebijakan penyedia. Ada yang menghitung jumlah unit sachet, ada yang menghitung berat bahan, dan ada yang menghitung keduanya. Pastikan ini jelas sebelum memesan.</p>
<h3>Apakah jumlah besar selalu lebih untung?</h3><p>Tidak selalu. Harga per unit memang lebih rendah, tetapi modal terikat dan risiko stok menumpuk. Untuk brand baru, kecepatan uji pasar biasanya lebih berharga.</p>
<h3>Bagaimana kalau saya ingin punya banyak varian?</h3><p>Mulai dari dua sampai tiga varian, lalu tambah setelah salah satunya terbukti. Menambah varian pada produksi pertama menaikkan biaya kemasan minimal secara tidak proporsional.</p>
""",
}



# tambahan isi pilar (dari ys_serbuk_tambahan5.py)
_spec = importlib.util.spec_from_file_location("_ysb5", os.path.join(os.path.dirname(os.path.abspath(__file__)), "ys_serbuk_tambahan5.py"))
_modb5 = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_modb5)
LEG["isi"] = LEG["isi"].replace('<h2>Pertanyaan yang sering muncul</h2>', _modb5.LEG + "\n<h2>Pertanyaan yang sering muncul</h2>")
MOQ["isi"] = MOQ["isi"].replace('<h2>Pertanyaan yang sering muncul</h2>', _modb5.MOQ + "\n<h2>Pertanyaan yang sering muncul</h2>")

def api(path, data=None, method=None):
    method = method or ("POST" if data is not None else "GET")
    h = {"Authorization": f"Basic {AUTH}", "User-Agent": "Mozilla/5.0"}
    body = None
    if data is not None:
        body = json.dumps(data).encode(); h["Content-Type"] = "application/json"
    err = None
    r = urllib.request.Request(S + path, data=body, headers=h, method=method)
    for _ in range(3):
        try:
            with urllib.request.urlopen(r, timeout=220) as x:
                return x.status, json.loads(x.read())
        except urllib.error.HTTPError as e:
            if e.code in (404, 410, 500, 502, 503, 504):
                time.sleep(4); continue
            return e.code, e.read().decode()[:200]
        except Exception as e:
            err = e; time.sleep(4)
    return 0, str(err)[:150] if err else "gagal"


def bangun(konf, tautan_blok):
    pasangan = [(re.sub(r"<[^>]+>", " ", m.group(1)).strip(), re.sub(r"\s+", " ", re.sub(r"<[^>]+>", " ", m.group(2))).strip())
                for m in re.finditer(r"<h3[^>]*>(.*?)</h3>\s*<p>(.*?)</p>", konf["isi"], re.S)]
    schema = ('<script type="application/ld+json">' + json.dumps({
        "@context": "https://schema.org", "@type": "FAQPage",
        "mainEntity": [{"@type": "Question", "name": q, "acceptedAnswer": {"@type": "Answer", "text": a}} for q, a in pasangan]},
        ensure_ascii=False) + "</script>")
    return konf["isi"] + "\n" + tautan_blok + "\n" + schema + "\n" + WA


print("=== GUARD tipe post ===")
for pid in (PILAR_LEG, PILAR_MOQ) + tuple(BUANG):
    st, d = api(f"/wp-json/wp/v2/posts/{pid}?context=edit&_fields=type,status")
    t = d.get("type") if isinstance(d, dict) else f"gagal({st})"
    if t != "post":
        print(f"  #{pid} tipe={t} ⛔ bukan post — dibatalkan"); sys.exit(1)
print("  semua sasaran = post ✅")
for nama, k in (("legalitas", LEG), ("MOQ", MOQ)):
    print(f"  pilar {nama}: {len(html.unescape(re.sub(r'<[^>]+>', ' ', k['isi'])).split())} kata | meta {len(k['meta'])} | fk di awal: {k['meta'].lower().startswith(k['fk'].lower())}")

if "--apply" not in sys.argv:
    print(f"\n  dipensiunkan: {BUANG} (#3034 legalitas BPOM — isinya masuk pilar legalitas)")
    sys.exit(0)

blok_leg = (f'<h2>Baca juga</h2>\n<p>Alur produksinya ada di <a href="{GEL2}">maklon minuman serbuk</a>, '
            f'dan langkah memulai brand dibahas di <a href="{GEL3}">cara memulai bisnis minuman serbuk</a>.</p>')
blok_moq = (f'<h2>Baca juga</h2>\n<p>Untuk sisi perizinannya, baca <a href="https://yasmanatura.co.id/panduan-lengkap-legalitas-produk-minuman-serbuk/">legalitas produk minuman serbuk</a>, '
            f'dan proses produksinya di <a href="{GEL2}">maklon minuman serbuk</a>.</p>')

for pid, konf, blok in ((PILAR_LEG, LEG, blok_leg), (PILAR_MOQ, MOQ, blok_moq)):
    st, _ = api(f"/wp-json/wp/v2/posts/{pid}", {
        "title": konf["judul"], "content": bangun(konf, blok),
        "meta": {"_yoast_wpseo_focuskw": konf["fk"], "_yoast_wpseo_title": konf["judul"], "_yoast_wpseo_metadesc": konf["meta"]}})
    _, chk = api(f"/wp-json/wp/v2/posts/{pid}?context=edit&_fields=content,meta,link")
    raw = chk["content"]["raw"]
    print(f"\nPILAR #{pid} POST {st} | {len(html.unescape(re.sub(r'<[^>]+>', ' ', raw)).split())} kata | FAQ {raw.count('<h3>')} Q | meta {len(chk['meta'].get('_yoast_wpseo_metadesc',''))}")
    print(f"  URL kanonik: {chk.get('link')}")

print("\nmemindahkan ke trash:")
for pid in BUANG:
    st4, _ = api(f"/wp-json/wp/v2/posts/{pid}", method="DELETE")
    _, c2 = api(f"/wp-json/wp/v2/posts/{pid}?context=edit&_fields=status")
    print(f"  #{pid} DELETE {st4} | status: {c2.get('status') if isinstance(c2, dict) else c2}")
