"""
candy CLI — Commandes terminal
==============================

candy helper          → ouvre la fenêtre Helper
candy -- script.cdy   → exécute un fichier .cdy
"""

import sys
import os
import tkinter as tk
from tkinter import scrolledtext
import threading
import httpx

CANDY_JSON_URL = "https://client.hubworld.net/candy.json"

# Couleurs
BG     = "#0d0d1a"
BG2    = "#12122a"
BG3    = "#1a1a35"
ACCENT = "#b44fff"
CYAN   = "#00e5ff"
GREEN  = "#00ff99"
RED    = "#ff4444"
TEXT   = "#e8e8ff"
TEXT2  = "#9090bb"

HELPER_TEMPLATES = {
    "livre":      "Helper.run(\"livre\", sujet=\"{sujet}\", lang=\"FR\", chapitres=20)",
    "traduction": "Helper.run(\"traduction\", texte=\"{texte}\", langues=[\"ES\",\"DE\",\"JA\"])",
    "chatbot":    "Helper.run(\"chatbot\", lang=\"FR\", module=\"Full\")",
    "pipeline":   "Helper.run(\"pipeline\", tache=\"{tache}\", lang=\"FR\")",
    "batch":      "Helper.run(\"batch\", questions=[\"{q1}\",\"{q2}\"], module=\"Full\", lang=\"FR\")",
    "résumé":     "Helper.run(\"résumé\", lang=\"FR\")",
    "question":   "Helper.run(\"question\", module=\"Full\", lang=\"FR\")",
}


def get_api_base() -> str:
    resp = httpx.get(CANDY_JSON_URL, timeout=10)
    resp.raise_for_status()
    data = resp.json()
    if data.get("is_closed", True):
        raise Exception("API hors ligne")
    link = data.get("link", "").strip().rstrip("/")
    if not link:
        raise Exception("Pas de lien dans candy.json")
    return link


def ask_helper(task: str) -> str:
    """Demande à l'API de générer du code candy pour la tâche."""
    from .helper import TEMPLATES, _build_livre, _build_traduction  # noqa

    base = get_api_base()
    payload = {
        "prompt": (
            "[RÈGLE ABSOLUE : Retourne UNIQUEMENT du code Python candy-ai. "
            "Aucun texte. Aucune balise. Utilise from candy import ...]\n\n"
            f"Génère du code Python candy-ai v10 complet pour : {task}\n"
            "Langue : FR. Utilise les imports candy uniquement."
        ),
        "stream": False,
        "config": {
            "lang": "EN", "max_tokens": 2000, "temperature": 0.2,
            "style": "technical", "output_format": "text",
            "expertise": "expert", "safe_mode": True,
            "include_examples": False, "tone": "strict",
            "system_suffix": (
                "Tu es un expert candy-ai. Tu génères UNIQUEMENT du code Python "
                "qui utilise from candy import ... . Jamais pdfkit, googletrans, "
                "ou autres libs. Code complet, fonctionnel, avec print()."
            ),
        }
    }
    resp = httpx.post(f"{base}/ask/coding", json=payload, timeout=60)
    resp.raise_for_status()
    code = resp.json().get("response", "").strip()
    return code.replace("```python", "").replace("```", "").strip()


# ── Fenêtre Helper ────────────────────────────────────────────────────────────

class HelperWindow:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("✨ Candy Helper")
        self.root.geometry("720x600")
        self.root.configure(bg=BG)
        self.root.resizable(True, True)
        self._build()

    def _build(self):
        # Titre
        tk.Label(self.root, text="✨ Candy Helper",
                 bg=BG, fg=ACCENT, font=("Courier New", 16, "bold")).pack(pady=(14, 2))
        tk.Label(self.root, text="Décris ce que tu veux faire — le code candy sera généré",
                 bg=BG, fg=TEXT2, font=("Courier New", 10)).pack(pady=(0, 10))

        # Input
        input_frame = tk.Frame(self.root, bg=BG2)
        input_frame.pack(fill="x", padx=20)

        self._input = tk.Text(input_frame, bg=BG2, fg=TEXT,
                              insertbackground=ACCENT, font=("Courier New", 11),
                              relief="flat", height=3, wrap="word")
        self._input.pack(fill="x", padx=10, pady=10)
        self._input.focus()
        self._input.bind("<Control-Return>", lambda e: self._generate())

        # Templates rapides
        tmpl_outer = tk.Frame(self.root, bg=BG)
        tmpl_outer.pack(fill="x", padx=20, pady=(6, 0))
        tk.Label(tmpl_outer, text="Templates :", bg=BG, fg=TEXT2,
                 font=("Courier New", 9)).pack(side="left", padx=(0, 8))
        for name in HELPER_TEMPLATES:
            tk.Button(tmpl_outer, text=name, bg=BG3, fg=CYAN,
                      font=("Courier New", 9), relief="flat", cursor="hand2",
                      padx=8, pady=2, activebackground=ACCENT,
                      command=lambda n=name: self._use_template(n)
                      ).pack(side="left", padx=2)

        # Boutons action
        btn_frame = tk.Frame(self.root, bg=BG)
        btn_frame.pack(pady=10)

        tk.Button(btn_frame, text="✨ Générer le code",
                  bg=ACCENT, fg="white",
                  font=("Courier New", 11, "bold"),
                  relief="flat", cursor="hand2",
                  command=self._generate,
                  activebackground="#9933ff",
                  padx=18, pady=7).pack(side="left", padx=6)

        tk.Button(btn_frame, text="▶ Exécuter",
                  bg=GREEN, fg=BG,
                  font=("Courier New", 11, "bold"),
                  relief="flat", cursor="hand2",
                  command=self._run,
                  activebackground=CYAN,
                  padx=18, pady=7).pack(side="left", padx=6)

        tk.Button(btn_frame, text="💾 Enregistrer .cdy",
                  bg=BG3, fg=CYAN,
                  font=("Courier New", 10),
                  relief="flat", cursor="hand2",
                  command=self._save_cdy,
                  padx=14, pady=7).pack(side="left", padx=6)

        tk.Button(btn_frame, text="🗑 Effacer",
                  bg=BG3, fg=TEXT2,
                  font=("Courier New", 10),
                  relief="flat", cursor="hand2",
                  command=self._clear,
                  padx=10, pady=7).pack(side="left", padx=6)

        # Zone de code généré
        tk.Label(self.root, text="  Code généré :",
                 bg=BG2, fg=TEXT2, font=("Courier New", 9),
                 anchor="w").pack(fill="x", padx=20, pady=(4, 0))

        self._output = scrolledtext.ScrolledText(
            self.root, bg=BG2, fg=GREEN,
            font=("Courier New", 10), relief="flat",
            wrap="none", insertbackground=ACCENT
        )
        self._output.pack(fill="both", expand=True, padx=20, pady=(0, 4))

        # Status
        self._status = tk.Label(self.root, text="Prêt — Ctrl+Entrée pour générer",
                                bg=BG, fg=TEXT2, font=("Courier New", 9))
        self._status.pack(pady=(0, 8))

    def _use_template(self, name: str):
        self._input.delete("1.0", "end")
        self._input.insert("1.0", f"template:{name}")

    def _set_status(self, msg: str, color: str = TEXT2):
        self._status.config(text=msg, fg=color)

    def _generate(self):
        task = self._input.get("1.0", "end").strip()
        if not task:
            return
        self._set_status("⏳ Génération en cours...", CYAN)
        self._output.delete("1.0", "end")
        self._output.insert("end", "# Génération en cours...\n")

        def do():
            try:
                # Template direct
                if task.startswith("template:"):
                    name = task.replace("template:", "").strip()
                    tmpl = HELPER_TEMPLATES.get(name, "")
                    code = (
                        f"from candy import cfg, Helper\n\n"
                        f"cfg.default.lang = \"FR\"\n\n"
                        f"{tmpl}\n"
                    )
                else:
                    code = ask_helper(task)

                self.root.after(0, lambda c=code: self._show_code(c))
                self.root.after(0, lambda: self._set_status("✅ Code généré !", GREEN))
            except Exception as e:
                self.root.after(0, lambda: self._show_code(f"# Erreur : {e}"))
                self.root.after(0, lambda: self._set_status(f"❌ {e}", RED))

        threading.Thread(target=do, daemon=True).start()

    def _show_code(self, code: str):
        self._output.delete("1.0", "end")
        self._output.insert("end", code)

    def _run(self):
        code = self._output.get("1.0", "end").strip()
        if not code or code.startswith("# Génération") or code.startswith("# Erreur"):
            self._set_status("❌ Génère du code d'abord", RED)
            return
        self._set_status("▶ Exécution...", CYAN)

        def do():
            import io
            from contextlib import redirect_stdout, redirect_stderr
            out_buf = io.StringIO()
            err_buf = io.StringIO()
            try:
                with redirect_stdout(out_buf), redirect_stderr(err_buf):
                    exec(code, {"__name__": "__main__"})
                out = out_buf.getvalue()
                err = err_buf.getvalue()
                result = out + err if out or err else "✅ Exécuté (pas de sortie)"
                self.root.after(0, lambda r=result: (
                    self._show_code(f"{code}\n\n# ── Sortie ──────────────\n{r}"),
                    self._set_status("✅ Exécuté", GREEN)
                ))
            except Exception as ex:
                import traceback
                tb = traceback.format_exc()
                self.root.after(0, lambda t=tb: (
                    self._show_code(f"{code}\n\n# ── Erreur ──────────────\n{t}"),
                    self._set_status("❌ Erreur à l'exécution", RED)
                ))

        threading.Thread(target=do, daemon=True).start()

    def _save_cdy(self):
        from tkinter import filedialog
        code = self._output.get("1.0", "end").strip()
        if not code:
            self._set_status("❌ Rien à sauvegarder", RED)
            return
        path = filedialog.asksaveasfilename(
            defaultextension=".cdy",
            filetypes=[("Candy script", "*.cdy"), ("Python", "*.py"), ("Tous", "*.*")]
        )
        if path:
            with open(path, "w", encoding="utf-8") as f:
                f.write(code)
            self._set_status(f"💾 Sauvegardé → {path}", GREEN)

    def _clear(self):
        self._input.delete("1.0", "end")
        self._output.delete("1.0", "end")
        self._set_status("Prêt", TEXT2)

    def run(self):
        self.root.mainloop()


# ── Exécuteur de fichiers .cdy ────────────────────────────────────────────────

def run_cdy_file(path: str):
    """Exécute un fichier .cdy (code Python candy)."""
    if not os.path.exists(path):
        print(f"❌ Fichier introuvable : {path}")
        sys.exit(1)
    with open(path, "r", encoding="utf-8") as f:
        code = f.read()
    print(f"🍬 Exécution de {path}\n{'─' * 40}")
    exec(code, {"__name__": "__main__"})


# ── Point d'entrée CLI ────────────────────────────────────────────────────────

def main():
    args = sys.argv[1:]

    # candy helper
    if args and args[0] == "helper":
        win = HelperWindow()
        win.run()
        return

    # candy -- script.cdy
    if len(args) >= 2 and args[0] == "--":
        run_cdy_file(args[1])
        return

    # candy (sans args) → aide
    print("""
🍬 Candy CLI v10
─────────────────────────────
  candy helper        → ouvre la fenêtre Helper
  candy -- script.cdy → exécute un fichier .cdy

Exemples :
  candy helper
  candy -- mon_script.cdy
─────────────────────────────
""")
