#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
generateur_aides.py — Devoirati / Fahmi
========================================
Lit un fichier texte structuré contenant les aides rédigées par ChatGPT
(ou à la main), et génère un ZIP avec tous les .aide.js correspondants.

Usage :
    python generateur_aides.py aides.txt
    python generateur_aides.py aides.txt -o mon_dossier_sortie

Format du fichier texte source (aides.txt) :
─────────────────────────────────────────────
# quiz_associativite_hard_001
TITRE: التجميعية
FOCUS: استعمل التجميعية لحساب (8750+1250)+999
REGLE_TEXTE: في الجمع والضرب يمكن تغيير التجميع لتسهيل الحساب.
REGLE_MATH: (a+b)+c=a+(b+c)
HINT: اختر التجميع الأسهل.
EXEMPLE: استعمل التجميعية لحساب (1250+750)+333
ERREUR: (20-7)-3\\neq20-(7-3)
DEFI: 25+(17+75)

# quiz_associativite_hard_002
TITRE: التجميعية
...
─────────────────────────────────────────────
Règles :
  - Chaque bloc commence par une ligne # nom_du_fichier (sans .aide.js)
  - Les 8 champs sont obligatoires
  - Les maths sont en LaTeX brut, sans \\[...\\] — le script les ajoute
  - Les lignes vides entre blocs sont ignorées
  - Les commentaires commencent par //
"""

from __future__ import annotations
import argparse, sys, zipfile, re
from pathlib import Path
from dataclasses import dataclass, field
from typing import List, Tuple

# ─── CSS (unique, identique pour tous les fichiers) ───────────────────────────
CSS = """\
      .fahmi-local-help-overlay{position:fixed;inset:0;background:rgba(15,23,42,.35);z-index:9997;display:none;}
      .fahmi-local-help-overlay.show{display:block;}
      .fahmi-local-help-panel{
        position:fixed;top:85px;left:22px;width:440px;max-width:calc(100vw - 44px);
        max-height:75vh;background:#fff;border-radius:18px;box-shadow:0 18px 45px rgba(0,0,0,.28);
        z-index:9998;overflow:hidden;opacity:0;visibility:hidden;transform:translateY(-12px);
        transition:.25s ease;font-family:'Tajawal','Cairo','Segoe UI',sans-serif;border:2px solid #e0e7ff;
      }
      .fahmi-local-help-panel.show{opacity:1;visibility:visible;transform:translateY(0);}
      .fahmi-local-help-header{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;padding:13px 16px;font-weight:800;display:flex;justify-content:space-between;align-items:center;}
      .fahmi-local-help-close{width:30px;height:30px;border:none;border-radius:50%;background:rgba(255,255,255,.22);color:white;font-size:22px;cursor:pointer;}
      .fahmi-local-help-content{padding:16px;overflow-y:auto;max-height:calc(75vh - 58px);line-height:1.9;}
      .fahmi-local-help-box{padding:13px 14px;border-radius:13px;margin-bottom:12px;border-right:5px solid;}
      .fahmi-local-help-box h4{margin:0 0 8px;}
      .fahmi-local-help-box.hint{background:#ecfeff;border-color:#06b6d4;}
      .fahmi-local-help-box.method{background:#eef2ff;border-color:#6366f1;}
      .fahmi-local-help-box.rule{background:#f5f3ff;border-color:#8b5cf6;}
      .fahmi-local-help-box.visual{background:#ecfdf5;border-color:#10b981;}
      .fahmi-local-help-box.apply{background:#eff6ff;border-color:#3b82f6;}
      .fahmi-local-help-box.warning{background:#fff7ed;border-color:#f97316;}
      .fahmi-local-help-box.final{background:#f0fdf4;border-color:#22c55e;}
      .math-line{direction:ltr;text-align:center;font-weight:700;background:rgba(255,255,255,.75);border-radius:8px;padding:6px;margin:10px 0;overflow-x:auto;}
      @media(max-width:600px){.fahmi-local-help-panel{left:12px;right:12px;top:75px;width:auto;}}"""


# ─── Dataclass pour une aide ──────────────────────────────────────────────────
@dataclass
class Aide:
    fichier: str        # nom sans extension, ex: quiz_associativite_hard_001
    titre: str          # عنوان الفقرة
    focus: str          # السؤال المحوري  → math-line dans boîte hint
    regle_texte: str    # نص القاعدة     → <p> dans boîte method
    regle_math: str     # صيغة LaTeX     → math-line dans boîte method
    hint: str           # تلميح محدد     → <p> dans boîte visual
    exemple: str        # مثال مشابه     → math-line dans boîte apply
    erreur: str         # خطأ شائع LaTeX → math-line dans boîte warning
    defi: str           # تحدي LaTeX     → math-line dans boîte final


# ─── Parseur du fichier texte ─────────────────────────────────────────────────
CHAMPS = {"TITRE", "FOCUS", "REGLE_TEXTE", "REGLE_MATH", "HINT", "EXEMPLE", "ERREUR", "DEFI"}

def parse(path: Path) -> Tuple[List[Aide], List[str]]:
    """Retourne (liste d'Aide, liste d'erreurs)."""
    aides, erreurs = [], []
    current_fichier = None
    current_data: dict = {}
    line_no = 0

    def finalise(fichier, data, lno):
        manquants = CHAMPS - set(data.keys())
        if manquants:
            erreurs.append(f"Ligne ~{lno} — [{fichier}] champs manquants : {', '.join(sorted(manquants))}")
            return None
        return Aide(
            fichier=fichier,
            titre=data["TITRE"],
            focus=data["FOCUS"],
            regle_texte=data["REGLE_TEXTE"],
            regle_math=data["REGLE_MATH"],
            hint=data["HINT"],
            exemple=data["EXEMPLE"],
            erreur=data["ERREUR"],
            defi=data["DEFI"],
        )

    for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines():
        line_no += 1
        line = raw.strip()

        if not line or line.startswith("//"):
            continue

        if line.startswith("#"):
            # Sauvegarder le bloc précédent
            if current_fichier:
                a = finalise(current_fichier, current_data, line_no)
                if a:
                    aides.append(a)
            current_fichier = line[1:].strip()
            current_data = {}
            continue

        # Chercher CHAMP: valeur
        m = re.match(r"^([A-Z_]+)\s*:\s*(.+)$", line)
        if m:
            key, val = m.group(1), m.group(2).strip()
            if key in CHAMPS:
                current_data[key] = val
            else:
                erreurs.append(f"Ligne {line_no} — champ inconnu '{key}' (ignoré)")
        else:
            erreurs.append(f"Ligne {line_no} — ligne non reconnue : {line[:60]}")

    # Dernier bloc
    if current_fichier:
        a = finalise(current_fichier, current_data, line_no)
        if a:
            aides.append(a)

    return aides, erreurs


# ─── Générateur JS ────────────────────────────────────────────────────────────
def generer_js(a: Aide) -> str:
    return f"""/* aide.js — {a.titre}
   Généré par generateur_aides.py — Devoirati
   Fichier cible : {a.fichier}.aide.js
*/

(function () {{
  "use strict";

  if (window.FAHMI_LOCAL_AIDE_READY) return;
  window.FAHMI_LOCAL_AIDE_READY = true;

  window.openFahmiLocalHelp = function () {{
    injectLocalHelpCSS();
    createLocalHelpPanel();
    const overlay = document.getElementById("fahmiLocalHelpOverlay");
    const panel   = document.getElementById("fahmiLocalHelpPanel");
    overlay.classList.add("show");
    panel.classList.add("show");
    if (window.MathJax && MathJax.typesetPromise) {{
      MathJax.typesetPromise([panel]);
    }}
  }};

  function closeFahmiLocalHelp() {{
    document.getElementById("fahmiLocalHelpOverlay")?.classList.remove("show");
    document.getElementById("fahmiLocalHelpPanel")?.classList.remove("show");
  }}

  function createLocalHelpPanel() {{
    if (document.getElementById("fahmiLocalHelpPanel")) return;

    const overlay = document.createElement("div");
    overlay.id        = "fahmiLocalHelpOverlay";
    overlay.className = "fahmi-local-help-overlay";

    const panel = document.createElement("div");
    panel.id        = "fahmiLocalHelpPanel";
    panel.className = "fahmi-local-help-panel";
    panel.setAttribute("dir", "rtl");

    panel.innerHTML = `
      <div class="fahmi-local-help-header">
        <span>🤖 فهمي يساعدك — {a.titre}</span>
        <button id="fahmiLocalHelpClose" class="fahmi-local-help-close">×</button>
      </div>

      <div class="fahmi-local-help-content">

        <div class="fahmi-local-help-box hint">
          <h4>💡 ماذا نلاحظ؟</h4>
          <p>هذه المساعدة مخصّصة لهذه الفقرة: <b>{a.titre}</b>.</p>
          <p>نقرأ السؤال ونبحث عن الفكرة الخاصة به قبل الحساب.</p>
          <p class="math-line">
            \\\\[
            {a.focus}
            \\\\]
          </p>
        </div>

        <div class="fahmi-local-help-box method">
          <h4>📝 القاعدة المهمة</h4>
          <p>{a.regle_texte}</p>
          <p class="math-line">
            \\\\[
            {a.regle_math}
            \\\\]
          </p>
        </div>

        <div class="fahmi-local-help-box rule">
          <h4>📘 طريقة العمل</h4>
          <p>1️⃣ حدّد الخاصية أو القاعدة المطلوبة.</p>
          <p>2️⃣ طبّقها على العملية دون تغيير المعنى.</p>
          <p>3️⃣ احسب أو قارن ثم تحقّق من النتيجة.</p>
        </div>

        <div class="fahmi-local-help-box visual">
          <h4>🔍 تلميح من نفس الصفحة</h4>
          <p>{a.hint}</p>
          <p>استعمل التلميح لتحديد الطريق، لا لتعويض التفكير.</p>
        </div>

        <div class="fahmi-local-help-box apply">
          <h4>🧩 مثال مشابه من نفس النوع</h4>
          <p class="math-line">
            \\\\[
            {a.exemple}
            \\\\]
          </p>
          <p>لاحظ أن المثال من نفس الفكرة، لذلك طريقة التفكير هي نفسها.</p>
        </div>

        <div class="fahmi-local-help-box warning">
          <h4>⚠️ خطأ شائع</h4>
          <p>الخطأ الشائع هو استعمال قاعدة أخرى لا تناسب هذه الفقرة.</p>
          <p class="math-line">
            \\\\[
            {a.erreur}
            \\\\]
          </p>
        </div>

        <div class="fahmi-local-help-box final">
          <h4>🔥 جرّب قبل التصحيح</h4>
          <p>طبّق نفس الفكرة على هذا المثال:</p>
          <p class="math-line">
            \\\\[
            {a.defi}
            \\\\]
          </p>
          <p>ثم عد إلى تمرين الصفحة واكتب المراحل بوضوح.</p>
        </div>

      </div>
    `;

    document.body.appendChild(overlay);
    document.body.appendChild(panel);

    document.getElementById("fahmiLocalHelpClose").addEventListener("click", closeFahmiLocalHelp);
    overlay.addEventListener("click", closeFahmiLocalHelp);
    document.addEventListener("keydown", function (e) {{
      if (e.key === "Escape") closeFahmiLocalHelp();
    }});
  }}

  function injectLocalHelpCSS() {{
    if (document.getElementById("fahmiLocalHelpCSS")) return;
    const style = document.createElement("style");
    style.id = "fahmiLocalHelpCSS";
    style.textContent = `
{CSS}
    `;
    document.head.appendChild(style);
  }}
}})();
"""


# ─── Rapport ─────────────────────────────────────────────────────────────────
def generer_rapport(aides: List[Aide], erreurs: List[str], source: str) -> str:
    lignes = [
        "RAPPORT generateur_aides.py — Devoirati",
        "=" * 44,
        f"Source : {source}",
        f"Aides générées : {len(aides)}",
        f"Erreurs/avertissements : {len(erreurs)}",
        "",
    ]
    if erreurs:
        lignes.append("── Erreurs ──────────────────────────────────")
        lignes.extend(erreurs)
        lignes.append("")
    lignes.append("── Fichiers générés ─────────────────────────")
    for a in aides:
        lignes.append(f"  [OK] {a.fichier}.aide.js  ({a.titre})")
    return "\n".join(lignes)


# ─── Point d'entrée ───────────────────────────────────────────────────────────
def main() -> int:
    ap = argparse.ArgumentParser(
        description="Génère les .aide.js Fahmi à partir d'un fichier texte structuré."
    )
    ap.add_argument("source", nargs="?", help="Fichier texte source (aides.txt)")
    ap.add_argument("-o", "--output-dir", default=None, help="Dossier de sortie")
    args = ap.parse_args()

    if not args.source:
        args.source = input("Glisse ici ton fichier texte : ").strip().strip('"')

    source_path = Path(args.source).expanduser().resolve()
    if not source_path.exists():
        print(f"ERREUR : fichier introuvable : {source_path}", file=sys.stderr)
        return 1

    output_dir = Path(args.output_dir).expanduser().resolve() if args.output_dir else source_path.parent

    print(f"Lecture de {source_path.name} …")
    aides, erreurs = parse(source_path)

    if not aides:
        print("ERREUR : aucune aide valide trouvée dans le fichier source.", file=sys.stderr)
        for e in erreurs:
            print(" ", e, file=sys.stderr)
        return 1

    # Créer le ZIP
    zip_path    = output_dir / f"{source_path.stem}_aides.zip"
    rapport_path = output_dir / f"rapport_{source_path.stem}.txt"

    with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf:
        for a in aides:
            js = generer_js(a)
            zf.writestr(f"{a.fichier}.aide.js", js.encode("utf-8"))

    # Rapport texte
    rapport = generer_rapport(aides, erreurs, source_path.name)
    rapport_path.write_text(rapport, encoding="utf-8")

    print(f"✅  {len(aides)} fichiers générés")
    print(f"📦  ZIP   : {zip_path}")
    print(f"📝  Rapport : {rapport_path}")
    if erreurs:
        print(f"⚠️   {len(erreurs)} avertissement(s) — voir le rapport")

    return 0


if __name__ == "__main__":
    raise SystemExit(main())
