"""
candy.cli — Interface ligne de commande v16
============================================

Commandes disponibles :
  candy helper                          → fenêtre Helper graphique
  candy -- script.cdy                   → exécute un fichier .cdy
  candy --score "mon prompt"            → score qualité du prompt
  candy --score prompt.txt              → score depuis un fichier
  candy --fix "mon prompt"              → optimise un prompt
  candy --fix prompt.txt                → optimise depuis un fichier
  candy --dry-run "prompt"              → simule pipeline sans API
  candy --ask "prompt"                  → one-liner depuis terminal
  candy --ask "prompt" --lang EN        → avec langue spécifiée
  candy --status                        → statut de l'API
  candy --version                       → version installée
"""

import sys
import os
import json
from pathlib import Path


def _print_score(score_data: dict):
    """Affiche le score d'un prompt en ASCII coloré."""
    s      = score_data["score"]
    grade  = score_data["grade"]
    quality= score_data["quality"]

    # Couleur selon grade
    if grade == "A":    col = "\033[92m"   # vert
    elif grade == "B":  col = "\033[96m"   # cyan
    elif grade == "C":  col = "\033[93m"   # jaune
    elif grade == "D":  col = "\033[33m"   # orange
    else:               col = "\033[91m"   # rouge
    reset = "\033[0m"
    gray  = "\033[90m"

    bar_len  = 30
    filled   = int(bar_len * s / 100)
    bar      = "█" * filled + "░" * (bar_len - filled)

    print(f"\n  {gray}Candy Prompt Score{reset}")
    print(f"  {col}{bar}{reset}  {col}{s}/100 · Grade {grade}{reset}")
    print(f"  Qualité : {col}{quality}{reset}  |  Mots : {score_data['words']}  |  Chars : {score_data['chars']}")
    print(f"  Personnalité détectée : \033[96m{score_data['detected_personality']}\033[0m")

    if score_data["issues"]:
        print(f"\n  {col}⚠ Problèmes :{reset}")
        for issue in score_data["issues"]:
            print(f"    • {issue}")

    if score_data["suggestions"]:
        print(f"\n  \033[96m💡 Suggestions :{reset}")
        for sug in score_data["suggestions"]:
            print(f"    → {sug}")
    print()


def _print_pipeline_viz(result: dict):
    """Affiche une visualisation ASCII du pipeline multi-agents."""
    steps = result.get("steps", {})
    total = result.get("total_steps", len(steps))

    print("\n  \033[90m╔══ Pipeline Multi-agents ══╗\033[0m")
    for i, (key, value) in enumerate(steps.items()):
        name    = key.split("_", 2)[-1] if "_" in key else key
        is_last = i == len(steps) - 1
        arrow   = "└──" if is_last else "├──"
        words   = len(str(value).split())
        print(f"  \033[90m{arrow}\033[0m \033[96m{name}\033[0m  \033[90m({words} mots)\033[0m")
        if not is_last:
            print(f"  \033[90m│     ↓\033[0m")

    print(f"\n  \033[92m✓ Final : {len(str(result.get('final','')).split())} mots\033[0m")
    print()


def _read_prompt_arg(arg: str) -> str:
    """Lit le prompt depuis une string ou un fichier .txt/.cdy."""
    if arg.endswith((".txt", ".cdy", ".md")) and Path(arg).exists():
        return Path(arg).read_text(encoding="utf-8").strip()
    return arg


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

    if not args:
        _print_help()
        return

    # ── candy --version ──────────────────────────────────────────────────────
    if args[0] in ("--version", "-v"):
        from candy.banner import VERSION
        print(f"candy-ai v{VERSION}")
        return

    # ── candy --status ───────────────────────────────────────────────────────
    if args[0] == "--status":
        try:
            from candy.modules.coding import Coding
            online = Coding.is_online()
            if online:
                ms = Coding.ping()
                print(f"\033[92m● API en ligne\033[0m  ({ms:.0f} ms)")
            else:
                print("\033[91m● API hors ligne\033[0m")
        except Exception as e:
            print(f"\033[91m● Erreur : {e}\033[0m")
        return

    # ── candy --score ────────────────────────────────────────────────────────
    if args[0] == "--score":
        if len(args) < 2:
            print("Usage : candy --score \"mon prompt\" ou candy --score prompt.txt")
            return
        from candy.core import Candy
        prompt = _read_prompt_arg(args[1])
        score  = Candy.score(prompt)
        _print_score(score)
        return

    # ── candy --fix ──────────────────────────────────────────────────────────
    if args[0] == "--fix":
        if len(args) < 2:
            print("Usage : candy --fix \"mon prompt\" ou candy --fix prompt.txt")
            return
        from candy.core import Candy
        prompt  = _read_prompt_arg(args[1])
        lang    = "FR"
        if "--lang" in args:
            idx  = args.index("--lang")
            lang = args[idx + 1] if idx + 1 < len(args) else "FR"

        print(f"\n  \033[90mPrompt original :\033[0m {prompt}")
        score_before = Candy.score(prompt)
        print(f"  \033[90mScore avant :\033[0m {score_before['score']}/100 (Grade {score_before['grade']})")

        print("\n  \033[96m⚡ Optimisation...\033[0m")
        fixed = Candy.fix(prompt, lang=lang)
        score_after = Candy.score(fixed)

        print(f"\n  \033[92m✓ Prompt optimisé :\033[0m")
        print(f"  {fixed}")
        print(f"\n  \033[90mScore après :\033[0m {score_after['score']}/100 (Grade {score_after['grade']})")

        gain = score_after["score"] - score_before["score"]
        if gain > 0:
            print(f"  \033[92m+{gain} points ↑\033[0m\n")
        return

    # ── candy --dry-run ───────────────────────────────────────────────────────
    if args[0] == "--dry-run":
        if len(args) < 2:
            print("Usage : candy --dry-run \"mon prompt\"")
            return
        from candy.core import Candy
        prompt = _read_prompt_arg(args[1])
        result = Candy.dry_run(prompt)

        print(f"\n  \033[90m╔══ Dry Run — Simulation ══╗\033[0m")
        print(f"  Prompt        : {prompt[:60]}{'...' if len(prompt)>60 else ''}")
        print(f"  Personnalité  : \033[96m{result['would_use_personality']}\033[0m")
        print(f"  Score prompt  : \033[{'92' if result['prompt_score']>=70 else '91'}m{result['prompt_score']}/100 (Grade {result['prompt_grade']})\033[0m")
        if result["issues"]:
            print(f"  Problèmes     : {', '.join(result['issues'])}")
        print(f"  API           : \033[93m{result['api_call']}\033[0m")
        print()
        return

    # ── candy --ask ───────────────────────────────────────────────────────────
    if args[0] == "--ask":
        if len(args) < 2:
            print("Usage : candy --ask \"mon prompt\" [--lang FR] [--stream]")
            return
        from candy.core import Candy
        prompt  = _read_prompt_arg(args[1])
        lang    = "FR"
        stream  = "--stream" in args
        if "--lang" in args:
            idx  = args.index("--lang")
            lang = args[idx + 1] if idx + 1 < len(args) else "FR"

        if stream:
            for token in Candy.stream(prompt, lang=lang):
                print(token, end="", flush=True)
            print()
        else:
            print(Candy.ask(prompt, lang=lang))
        return

    # ── candy --doctor (v20) ────────────────────────────────────────────────────
    if args[0] == "--doctor":
        _run_doctor()
        return

    # ── candy --update (v20) ─────────────────────────────────────────────────
    if args[0] == "--update":
        _run_update()
        return

    # ── candy helper ─────────────────────────────────────────────────────────
    if args[0] == "helper":
        _launch_helper_window()
        return

    # ── candy -- script.cdy ───────────────────────────────────────────────────
    if args[0] == "--" and len(args) >= 2:
        script_path = args[1]
        if not Path(script_path).exists():
            print(f"\033[91mErreur : fichier '{script_path}' introuvable.\033[0m")
            sys.exit(1)
        code = Path(script_path).read_text(encoding="utf-8")
        exec(compile(code, script_path, "exec"), {"__name__": "__main__"})
        return

    _print_help()


def _print_help():
    gray  = "\033[90m"
    cyan  = "\033[96m"
    green = "\033[92m"
    reset = "\033[0m"
    print(f"""
  {cyan}🍬 candy-ai CLI v20 BETA — Cedric8-Thinking{reset}

  {gray}── Prompts ──────────────────────────────────{reset}
  {green}candy --ask{reset} {gray}"prompt"{reset}            Appel one-liner
  {green}candy --ask{reset} {gray}"prompt" --stream{reset}   Streaming token par token
  {green}candy --ask{reset} {gray}"prompt" --lang EN{reset}  Langue spécifiée

  {gray}── Qualité des prompts ──────────────────────{reset}
  {green}candy --score{reset} {gray}"prompt"{reset}          Score 0-100 + grade A→F
  {green}candy --score{reset} {gray}prompt.txt{reset}        Score depuis fichier
  {green}candy --fix{reset} {gray}"prompt"{reset}            Auto-optimise un prompt
  {green}candy --dry-run{reset} {gray}"prompt"{reset}        Simule sans appeler l'API

  {gray}── Outils ───────────────────────────────────{reset}
  {green}candy helper{reset}                  Fenêtre Helper graphique
  {green}candy -- script.cdy{reset}           Exécute un fichier .cdy
  {green}candy --status{reset}                Statut de l'API
  {green}candy --doctor{reset}                Diagnostic complet (connexion, quota, cache)
  {green}candy --update{reset}                Met à jour candy-ai
  {green}candy --version{reset}               Version installée
""")


def _launch_helper_window():
    """Lance la fenêtre Helper tkinter."""
    try:
        import tkinter as tk
        from tkinter import scrolledtext, ttk
        import threading

        root = tk.Tk()
        root.title("🍬 Candy Helper v16")
        root.geometry("700x540")
        root.configure(bg="#ffffff")
        root.resizable(True, True)

        # Header
        header = tk.Frame(root, bg="#f5f5f7", pady=12)
        header.pack(fill="x")
        tk.Label(header, text="🍬 Candy Helper", font=("Inter", 14, "bold"),
                 bg="#f5f5f7", fg="#1d1d1f").pack(side="left", padx=20)
        tk.Label(header, text="v16", font=("Inter", 10),
                 bg="#f5f5f7", fg="#6e6e73").pack(side="left")

        # Input
        input_frame = tk.Frame(root, bg="#ffffff", padx=20, pady=12)
        input_frame.pack(fill="x")
        tk.Label(input_frame, text="Décris ce que tu veux faire :",
                 font=("Inter", 11), bg="#ffffff", fg="#1d1d1f").pack(anchor="w")
        task_input = tk.Text(input_frame, height=4, font=("Courier New", 11),
                             bg="#f5f5f7", fg="#1d1d1f", relief="flat",
                             padx=10, pady=8, wrap="word")
        task_input.pack(fill="x", pady=(6, 0))

        # Buttons
        btn_frame = tk.Frame(root, bg="#ffffff", padx=20, pady=8)
        btn_frame.pack(fill="x")

        status_lbl = tk.Label(btn_frame, text="", font=("Inter", 10),
                              bg="#ffffff", fg="#6e6e73")
        status_lbl.pack(side="left")

        def generate():
            task = task_input.get("1.0", "end").strip()
            if not task:
                return
            status_lbl.config(text="⚡ Génération...")
            output.config(state="normal")
            output.delete("1.0", "end")

            def run():
                try:
                    from candy import Helper
                    code = Helper.write("chatbot", lang="FR", module="Full") if task == "chatbot" else Helper.write(task)
                    root.after(0, lambda: _show_output(code))
                except Exception as e:
                    root.after(0, lambda: _show_output(f"# Erreur : {e}"))

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

        def _show_output(code):
            output.config(state="normal")
            output.delete("1.0", "end")
            output.insert("1.0", code)
            output.config(state="normal")
            status_lbl.config(text="✅ Prêt")

        def copy_output():
            code = output.get("1.0", "end").strip()
            root.clipboard_clear()
            root.clipboard_append(code)
            status_lbl.config(text="✅ Copié !")

        tk.Button(btn_frame, text="Générer", font=("Inter", 11, "bold"),
                  bg="#0071e3", fg="white", relief="flat", padx=16, pady=6,
                  cursor="hand2", command=generate).pack(side="right", padx=(8, 0))
        tk.Button(btn_frame, text="Copier", font=("Inter", 11),
                  bg="#f5f5f7", fg="#1d1d1f", relief="flat", padx=16, pady=6,
                  cursor="hand2", command=copy_output).pack(side="right")

        # Output
        out_frame = tk.Frame(root, bg="#ffffff", padx=20, pady=(0, 20))
        out_frame.pack(fill="both", expand=True)
        output = scrolledtext.ScrolledText(
            out_frame, font=("Courier New", 11), bg="#1d1d1f", fg="#e8e8ed",
            relief="flat", state="normal", padx=12, pady=10, wrap="word"
        )
        output.pack(fill="both", expand=True)

        root.mainloop()

    except ImportError:
        print("\033[91mtkinter non disponible. Installe-le ou utilise candy --ask\033[0m")


if __name__ == "__main__":
    main()


# ── candy --doctor (v20) ──────────────────────────────────────────────────────

def _run_doctor():
    """Vérifie la connexion, le quota et la version — candy --doctor"""
    green  = "\033[92m"
    red    = "\033[91m"
    yellow = "\033[93m"
    gray   = "\033[90m"
    cyan   = "\033[96m"
    reset  = "\033[0m"

    from candy.banner import VERSION, ENGINE
    print(f"\n  {cyan}🍬 candy doctor — v{VERSION}{reset}\n")

    # 1. Version installée
    print(f"  {gray}[1/4] Version{reset}")
    print(f"       candy-ai     {green}v{VERSION}{reset}")
    print(f"       Engine       {green}{ENGINE}{reset}")

    # 2. Connexion API
    print(f"\n  {gray}[2/4] Connexion API{reset}")
    try:
        from candy.modules.coding import Coding
        online = Coding.is_online()
        if online:
            ms = Coding.ping()
            print(f"       API          {green}● en ligne{reset}  ({ms:.0f} ms)")
        else:
            print(f"       API          {red}● hors ligne{reset}")
    except Exception as e:
        print(f"       API          {red}● erreur : {e}{reset}")

    # 3. Quota
    print(f"\n  {gray}[3/4] Quota{reset}")
    try:
        from candy.modules.coding import Coding
        q = Coding.quota()
        used      = q.get("quota_used_today", "?")
        limit     = q.get("quota_limit", "?")
        remaining = q.get("quota_remaining", "?")
        pct       = int(used / limit * 100) if isinstance(used, int) and isinstance(limit, int) and limit > 0 else 0
        col       = green if pct < 70 else (yellow if pct < 90 else red)
        bar_len   = 20
        filled    = int(bar_len * pct / 100)
        bar       = "█" * filled + "░" * (bar_len - filled)
        print(f"       Utilisé      {col}{bar}{reset}  {used}/{limit}  ({remaining} restants)")
    except Exception as e:
        print(f"       Quota        {yellow}⚠ impossible à récupérer : {e}{reset}")

    # 4. Cache offline
    print(f"\n  {gray}[4/4] Cache offline{reset}")
    try:
        from pathlib import Path
        cache_dir = Path.home() / ".candy" / "cache"
        if cache_dir.exists():
            files = list(cache_dir.glob("*.json"))
            size  = sum(f.stat().st_size for f in files)
            print(f"       Entrées      {green}{len(files)} fichiers{reset}  ({size // 1024} Ko)")
        else:
            print(f"       Cache        {gray}vide (pas encore utilisé){reset}")
    except Exception as e:
        print(f"       Cache        {yellow}⚠ {e}{reset}")

    print()


# ── candy --update (v20) ──────────────────────────────────────────────────────

def _run_update():
    """Met à jour candy-ai via pip — candy --update"""
    import subprocess
    cyan  = "\033[96m"
    green = "\033[92m"
    gray  = "\033[90m"
    reset = "\033[0m"

    print(f"\n  {cyan}🍬 candy update{reset}")
    print(f"  {gray}Mise à jour de candy-ai via pip...{reset}\n")
    try:
        result = subprocess.run(
            [sys.executable, "-m", "pip", "install", "--upgrade", "candy-ai"],
            capture_output=False,
            text=True
        )
        if result.returncode == 0:
            print(f"\n  {green}✓ candy-ai mis à jour avec succès.{reset}\n")
        else:
            print(f"\n  \033[91m✗ Échec de la mise à jour (code {result.returncode}).\033[0m\n")
    except Exception as e:
        print(f"\n  \033[91m✗ Erreur : {e}\033[0m\n")
