#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Regenerate guide articles for SNAPAT, SNAPTY, and URLIN."""

import json
import os
import re
from pathlib import Path

UPDATED = "2026-05-19"


def wc(text: str, arabic: bool = False) -> int:
    t = re.sub(r"<[^>]+>", " ", text)
    t = re.sub(r"\s+", " ", t).strip()
    if not t:
        return 0
    if arabic or re.search(r"[\u0600-\u06FF]", t):
        return len(t.split())
    return len(t.split())


def to_html(blocks):
    out = []
    for b in blocks:
        t = b.get("type")
        if t == "p":
            out.append(f"<p>{b['text']}</p>")
        elif t == "h2":
            out.append(f"<h2>{b['text']}</h2>")
        elif t == "ul":
            items = "".join(f"<li>{i}</li>" for i in b["items"])
            out.append(f"<ul>{items}</ul>")
        elif t == "ol":
            items = "".join(f"<li>{i}</li>" for i in b["items"])
            out.append(f"<ol>{items}</ol>")
    return "".join(out)


def php_export_str(s: str) -> str:
    return json.dumps(s, ensure_ascii=False)


def php_single_quoted(s: str) -> str:
    return "'" + s.replace("\\", "\\\\").replace("'", "\\'") + "'"


def write_snap(path: Path, meta: dict, body: str, strict: bool = True):
    header = "<?php\ndeclare(strict_types=1);\n\n" if strict else "<?php\n\n"
    if strict:
        ret = "return [\n"
        end = "];\n"
        body_expr = " <<<'HTML'\n" + body + "\nHTML,\n"
    else:
        ret = "return array(\n"
        end = ");\n"
        # PHP 5.6 (urlin): avoid heredoc — closing "HTML," can parse incorrectly
        body_expr = " " + php_single_quoted(body) + ",\n"
    content = (
        header
        + ret
        + f"    'slug' => {php_export_str(meta['slug'])},\n"
        + f"    'order' => {meta['order']},\n"
        + f"    'updated' => {UPDATED!r},\n"
        + f"    'title' => {php_export_str(meta['title'])},\n"
        + f"    'description' => {php_export_str(meta['description'])},\n"
        + "    'body' =>"
        + body_expr
        + end
    )
    path.write_text(content, encoding="utf-8")


# ─── SNAPAT / SNAPTY article definitions ───────────────────────────────────

SNAP_ARTICLES = {}

# 1 VIP
SNAP_ARTICLES["vip-100-members"] = {
    "order": 1,
    "ar": {
        "title": "VIP وشبكة الـ100 عضواً: دليل واقعي لظهور أقوى على سناب شات",
        "description": "ماذا يعني VIP في دليل SNAPAT، فكرة شبكة 100 عضو للتفاعل المنظم، وكيف تتجنب احتيال كلمات المرور والوعود الوهمية.",
        "blocks": [
            {"type": "p", "text": "عندما يبحث صانع محتوى عن «VIP» على سناب شات، قد يخلط بين ثلاثة معانٍ: اشتراك Snapchat+ داخل التطبيق، توثيق Snap Star للشخصيات العامة، أو إبراز الحساب في دليل خارجي مثل SNAPAT. هذا الدليل يوضح المعنى العملي لمسار VIP في الدليل، ويفصله عن الوعود المضللة التي تبيع «متابعين مضمونين» أو «نجوماً خلال 24 ساعة»."},
            {"type": "h2", "text": "الفرق بين Snapchat+ وSnap Star وVIP في الدليل"},
            {"type": "p", "text": "Snapchat+ اشتراك رسمي داخل التطبيق يوفّر مزايا مثل أيقونات تطبيق، أدوات حصرية، وأحياناً مضاعفاً لنقاط Snapscore عند التبادل مع مشتركين آخرين وفق شروط سناب. Snap Star شارة توثيق للشخصيات العامة والمبدعين المعروفين بعد مراجعة سناب شات، ولا تُباع لطرف ثالث. أما VIP في SNAPAT فهو ترتيب عرض داخل دليل حسابات سناب شات العربي لزيادة اكتشافك من زوار يبحثون عن حسابات في مجالك."},
            {"type": "h2", "text": "ماذا يقدّم VIP في SNAPAT؟"},
            {"type": "p", "text": "VIP هنا ليس زراً سرياً داخل تطبيق سناب شات. بعد مراجعة طلبك، يظهر حسابك في قسم مميز داخل الدليل مع عرض أوضح وروابط موثوقة لملفك الرسمي. الهدف إيصال زوار مهتمين بمجالك إلى صفحتك العامة، لا تغيير خوارزميات سناب من الخارج. من يزور الدليل غالباً يبحث عن حسابات في نيش محدد؛ لذلك يجب أن تكون سيرتك الذاتية والقصة الأولى جاهزتين خلال ثوانٍ."},
            {"type": "h2", "text": "فكرة شبكة 100 عضو — تنظيم لا اختصار"},
            {"type": "p", "text": "«شبكة 100» مصطلح مجتمعي يصف مجموعة محدودة من الحسابات النشطة تتفق على دعم قصص بعضها في نوافذ زمنية واضحة: إطلاق منتج، حملة موسمية، أو أسبوع تعريف بحساب جديد. العدد ليس ميزة مخفية في الإعدادات، بل إطار عمل: صغير بما يكفي ليبقى التفاعل بشرياً، كبير بما يكفي لرفع المشاهدات الأولية عندما يكون المحتوى جاهزاً."},
            {"type": "ul", "items": [
                "اتفقوا على قواعد: لا روابط مشبوهة، لا رسائل جماعية مزعجة، وتفاعل حقيقي لا بوتات.",
                "حدّدوا نافذتين للنشر يومياً بدل عشر قصص متتالية تُرهق المتابعين.",
                "استخدموا استطلاعاً أو سؤالاً واحداً في بداية السلسلة لرفع معدل الرد.",
                "راجعوا النتائج أسبوعياً: هل زادت الإضافات والردود، أم مجرد مشاهدات فارغة؟",
            ]},
            {"type": "h2", "text": "ما الذي يحرّك الظهور داخل سناب شات؟"},
            {"type": "p", "text": "وفق مساعدة سناب شات الرسمية، يعتمد التوزيع على نشاطك الحقيقي: إرسال واستقبال السنابات، نشر القصص، والتفاعل مع الأصدقاء. لا يوجد مسار رسمي لشراء Snap Score أو شارة Snap Star مقابل مال لطرف ثالث. Snapchat+ قد يوفّر مزايا اشتراك رسمية (مثل مضاعف نقاط لبعض المستخدمين)، وهي منفصلة عن أي دليل خارجي."},
            {"type": "h2", "text": "تحذيرات أمنية — خط أحمر"},
            {"type": "ul", "items": [
                "لا تشارك كلمة مرور سناب شات أو رمز التحقق لأي خدمة تدّعي تفعيل VIP.",
                "تجنّب من يعدك «نجمة سوداء مضمونة» أو «مستوى مرفوع بشكل مؤكد» مقابل تحويل بنكي.",
                "افتح التطبيق يدوياً للتحقق من الإشعارات؛ لا تضغط روابط تسجيل دخول في رسائل خاصة.",
                "SNAPAT يعرض معلومات علنية من الملف العام فقط ولا يطلب كلمة المرور.",
            ]},
            {"type": "h2", "text": "كيف تقيس نجاح VIP بشكل صحيح"},
            {"type": "p", "text": "لا تقارن نفسك بمبدع عالمي في يومك الأول. ركّز على مؤشرات يمكنك التأثير فيها: عدد الزيارات من الدليل إلى ملفك، معدل قبول طلبات الصداقة بعد القصة الترحيبية، ونسبة الرد على الرسائل. إن بقيت الأرقام ثابتة لأسبوعين رغم تحسين العنوان والصورة المصغّرة، جرّب نيشاً أضيق أو تعاوناً مع حسابين في نفس المجال بدل شراء «دعم وهمي»."},
            {"type": "ul", "items": [
                "سجّل يوم النشر ونوع المحتوى (تعليمي، ترفيهي، عرض منتج) بجانب مشاهدات القصة.",
                "قارن أداء القصص التي تبدأ بسؤال مباشر مقابل القصص التي تبدأ بإعلان فقط.",
                "تتبع من أين يأتي طلب الصداقة: بحث، رابط، أم مجموعة — لمعرفة قناة العمل.",
            ]},
            {"type": "h2", "text": "خطة عمل قبل طلب VIP"},
            {"type": "ol", "items": [
                "وحّد الهوية البصرية: صورة شخصية، اسم عرض، وسيرة تشرح قيمتك في سطرين.",
                "جهّز قصة ترحيبية قصيرة تربط زوار الدليل بما ستنشره هذا الأسبوع.",
                "انشر بانتظام 5–7 أيام قبل الطلب ليظهر حسابك حياً لمن يزوره.",
                "قدّم طلب VIP عبر النموذج الرسمي في الموقع مع وصف نيش واضح وأهداف واقعية.",
            ]},
            {"type": "h2", "text": "أسئلة شائعة"},
            {"type": "p", "text": "هل VIP يضمن 100 صديق يومياً؟ لا — يضمن مراجعة بشرية وعرضاً مميزاً عند القبول. هل أحتاج Snapchat+؟ ليس للإدراج في SNAPAT، بينما مزايا الاشتراك الرسمي تبقى داخل التطبيق. كم مدة المراجعة؟ تعتمد على الطابور؛ قدّم بيانات دقيقة لتسريع القرار."},
            {"type": "p", "text": "النمو المستدام = محتوى يستحق المتابعة + مجتمع صغير موثوق + قياس صادق. VIP في الدليل مكبّر لجهدك، لا بديلاً عنه. تصفّح قسم VIP للإلهام، ثم ابدأ من إضافة حسابك أو طلب المراجعة عندما تكون جاهزاً."},
        ],
    },
    "en": {
        "title": "VIP and the 100-Member Network: A Realistic Snapchat Visibility Guide",
        "description": "What VIP means on the SNAPTY directory, how a 100-member support circle works, and how to avoid password scams and fake star sellers.",
        "blocks": [
            {"type": "p", "text": "Creators often mix three different ideas when they search for “VIP” on Snapchat: Snapchat+ inside the app, Snap Star verification for public figures, or featured placement in an external directory like SNAPTY. This guide explains directory VIP in plain language and separates it from scams that sell “guaranteed followers” or “stars in 24 hours.”"},
            {"type": "h2", "text": "Snapchat+ vs Snap Star vs directory VIP"},
            {"type": "p", "text": "Snapchat+ is an in-app subscription with official perks such as badges, tools, and sometimes a Snapscore multiplier when snapping with other Plus members under Snapchat’s rules. Snap Star is verification for public figures and notable creators reviewed by Snapchat—not sold by third parties. SNAPTY VIP is featured placement in an English Snapchat directory so searchers in your niche can find your public profile faster."},
            {"type": "h2", "text": "What directory VIP actually provides"},
            {"type": "p", "text": "SNAPTY VIP is not a hidden Snapchat button. After manual review, your profile can appear in a featured section with clearer presentation and trusted links to your official Snapchat page. The goal is to send qualified visitors to your public profile—not to rewrite Snapchat’s ranking systems from the outside. Directory traffic only converts if your bio and first story deliver value within seconds."},
            {"type": "h2", "text": "The 100-member network idea"},
            {"type": "p", "text": "Community teams sometimes use “100 members” as a discipline frame: a capped group of active accounts that agree to support each other’s stories during launch windows. It is not a secret setting you can buy. The number stays small enough for human replies and large enough to create an early view spike when content is ready."},
            {"type": "ul", "items": [
                "Agree on rules: no spam links, no mass DM blasts, no bot engagement.",
                "Publish in two focused windows per day instead of ten rushed stories.",
                "Open with one poll or question to lift reply rate.",
                "Review weekly: friend adds, replies, and story completion—not vanity taps alone.",
            ]},
            {"type": "h2", "text": "What Snapchat itself rewards"},
            {"type": "p", "text": "Official Snapchat help states that Snapscore and distribution reflect real activity: snaps sent and received, stories posted, and genuine friend interaction. Third parties cannot sell official Snap Stars or guaranteed score jumps. Snapchat+ is a separate official subscription with its own documented perks."},
            {"type": "h2", "text": "Security red lines"},
            {"type": "ul", "items": [
                "Never share your Snapchat password or 2FA codes with a “VIP booster.”",
                "Reject anyone promising a black star, gold badge, or rank upgrade for cash off-platform.",
                "Open the app manually to verify alerts; do not use login links from random DMs.",
                "SNAPTY only displays public profile data and never asks for your password.",
            ]},
            {"type": "h2", "text": "Measuring VIP results honestly"},
            {"type": "p", "text": "Do not benchmark day one against a global creator. Track inputs you control: directory visits to your profile, friend-request acceptance after a welcome story, and reply rate in DMs. If numbers stay flat for two weeks despite better hooks and thumbnails, narrow your niche or collaborate with two peers instead of buying fake engagement."},
            {"type": "ul", "items": [
                "Log publish day and format (education, entertainment, offer) next to story views.",
                "Compare stories that open with a question versus stories that open with a hard sell.",
                "Note where friend requests originate—search, link, or group—to focus effort.",
            ]},
            {"type": "h2", "text": "Checklist before you apply"},
            {"type": "ol", "items": [
                "Unify branding: avatar, display name, and a two-line value proposition.",
                "Prepare a short welcome story that matches what directory visitors expect.",
                "Post consistently for 5–7 days so the profile looks active.",
                "Submit the VIP request form with a clear niche statement and realistic goals.",
            ]},
            {"type": "h2", "text": "FAQ"},
            {"type": "p", "text": "Does VIP guarantee 100 friends per day? No—it provides manual review and featured placement when accepted. Do you need Snapchat+? Not for a SNAPTY listing; official subscription perks remain inside Snapchat. How long is review? Queue-dependent—submit accurate details to avoid delays."},
            {"type": "p", "text": "Sustainable growth combines content quality, a small trusted circle, and honest metrics. Directory VIP amplifies work you already do—it does not replace it. Browse featured listings for ideas, then add your account or request review when you are ready."},
        ],
    },
}

# Due to script size, remaining articles are loaded from companion JSON
COMPANION = Path(__file__).with_name("guides_content.json")

PATHS = {
    "snapat_ar": Path("/home/snapat/public_html/includes/guides/articles"),
    "snapty_en": Path("/home/snapty/public_html/includes/guides/articles"),
    "urlin_en": Path("/home/urlin/public_html/inc/guides/articles"),
}


def load_all_articles() -> dict:
    articles = dict(SNAP_ARTICLES)
    if COMPANION.is_file():
        extra = json.loads(COMPANION.read_text(encoding="utf-8"))
        articles.update(extra)
    return articles


def emit_article(slug: str, data: dict, lang: str, dest: Path, strict: bool = True) -> int:
    pack = data.get(lang)
    if not pack:
        return 0
    body = to_html(pack["blocks"])
    meta = {
        "slug": slug,
        "order": data["order"],
        "title": pack["title"],
        "description": pack["description"],
    }
    write_snap(dest / f"{slug}.php", meta, body, strict=strict)
    return wc(body, arabic=(lang == "ar"))


def main() -> None:
    articles = load_all_articles()
    report = []

    for slug, data in sorted(articles.items(), key=lambda x: x[1]["order"]):
        if "ar" in data:
            w = emit_article(slug, data, "ar", PATHS["snapat_ar"], strict=True)
            report.append(f"SNAPAT {slug}: {w} words (ar)")
        if "en" in data and "ar" in data:
            w = emit_article(slug, data, "en", PATHS["snapty_en"], strict=True)
            report.append(f"SNAPTY {slug}: {w} words (en)")
        elif "en" in data:
            w = emit_article(slug, data, "en", PATHS["urlin_en"], strict=False)
            report.append(f"URLIN {slug}: {w} words (en)")

    print("\n".join(report))
    print(f"\nTotal slugs in source: {len(articles)}")


if __name__ == "__main__":
    main()
