#!/usr/bin/env python3
"""
toolbox — interaktiver Terminal-Tool-Launcher mit Kategorie-Navigation
Läuft auf macOS (iTerm2) und Linux (Xubuntu/xfce4-terminal, gnome-terminal, …)
"""

import subprocess
import shutil
import sys
import os
import platform
import shlex
from dataclasses import dataclass

IS_MAC   = platform.system() == "Darwin"
IS_LINUX = platform.system() == "Linux"

CURRENT_DIR = os.getcwd()


@dataclass
class Tool:
    category:    str
    name:        str
    description: str
    command:     str
    binary:      str
    mac:         bool = True
    linux:       bool = True


TOOLS = [
    # --- Git ---
    Tool("Git",      "lazygit",      "Git TUI: stagen, committen, pushen, rebasen",       "lazygit",                                           "lazygit"),
    Tool("Git",      "gitcheck",     "Status aller Repos prüfen",                          "~/git-check-all.sh",                                "git"),
    Tool("Git",      "gitsync",      "Alle Repos mit Gitea synchronisieren",               "~/git-projekte/dotfiles-rene/bin/git-sync-all.sh",  "git"),
    Tool("Git",      "git log",      "Commit-History (mit delta, side-by-side)",           "git log -p",                                        "git"),
    Tool("Git",      "git diff",     "Änderungen anzeigen (mit delta)",                    "git diff",                                          "git"),

    # --- Navigation & Dateien ---
    Tool("Dateien",  "yazi",         "Terminal-Dateimanager (q = quit)",                   "yazi",                                              "yazi"),
    Tool("Dateien",  "fzf",          "Fuzzy-Finder: Dateien und History durchsuchen",      "fzf",                                               "fzf"),
    Tool("Dateien",  "ncdu",         "Interaktive Festplattennutzung",                     "ncdu ~",                                            "ncdu"),
    Tool("Dateien",  "duf",          "Übersicht freier Speicherplatz",                     "duf",                                               "duf"),
    Tool("Dateien",  "fd",           "Schnelles find (Beispiel: fd .py)",                  "fd",                                                "fd"),
    Tool("Dateien",  "rg",           "Blitzschnelles grep (Beispiel: rg TODO)",            "rg",                                                "rg"),

    # --- Anzeige ---
    Tool("Anzeige",  "bat",          "cat mit Syntax-Highlighting",                        "bat",                                               "bat"),
    Tool("Anzeige",  "eza -la",      "Modernes ls mit Details, Farben, Git-Status",        "eza -la",                                           "eza"),
    Tool("Anzeige",  "eza -T",       "Verzeichnisbaum",                                    "eza -T",                                            "eza"),
    Tool("Anzeige",  "delta",        "Schöne Git-Diffs (wird automatisch verwendet)",      "git diff HEAD~1 | delta",                           "delta"),

    # --- System & Monitoring ---
    Tool("System",   "btop",         "Systemmonitor: CPU, RAM, Netz, Prozesse",            "btop",                                              "btop"),
    Tool("System",   "fastfetch",    "Systeminfo-Übersicht",                               "fastfetch",                                         "fastfetch"),
    Tool("System",   "temps",        "CPU/GPU-Temperatur + Akku (Mac)",                    "sudo powermetrics -s cpu_power,gpu_power,thermal,battery -i 1000 -n 1",
                                                                                                                                                "sudo",  linux=False),

    # --- Netzwerk ---
    Tool("Netzwerk", "nmap",         "Netzwerk-Scanner (Beispiel: nmap 10.47.11.0/24)",   "nmap -sn 10.47.11.0/24",                           "nmap"),

    # --- Berechnung ---
    Tool("Rechnen",  "units",        "Einheitenumrechnung (Beispiel: units 1kWh MJ)",      "units",                                             "units"),
    Tool("Rechnen",  "python3",      "Python REPL für schnelle Berechnungen",              "python3",                                           "python3"),

    # --- KI ---
    Tool("KI",       "ki-chat",      "Offline-KI interaktiver Chat",                       "ki interactive",                                    "ki"),
    Tool("KI",       "ki-agent",     "Offline-KI Agent-Modus: Datei- und Shell-Zugriff",  "ki interactive --agent-mode",                       "ki"),
    Tool("KI",       "ki-commit",    "Commit-Message mit KI generieren",                   "ki commit",                                         "ki"),
    Tool("KI",       "ki-diff",      "Git-Diff mit KI erklären lassen",                   "ki diff",                                           "ki"),

    # --- Screensaver / Spass ---
    Tool("Spass",    "cmatrix",      "Matrix-Regen (q = quit)",                            "cmatrix -sab",                                      "cmatrix"),
    Tool("Spass",    "asciiquarium", "Aquarium im Terminal (q = quit)",                    "asciiquarium",                                      "asciiquarium"),
    Tool("Spass",    "pipes.sh",     "Animierte Rohre (q = quit)",                         "pipes.sh -t 0 -p 4",                               "pipes.sh"),
    Tool("Spass",    "cbonsai",      "Wachsender Bonsai-Baum (q = quit)",                 "cbonsai -l",                                        "cbonsai"),
    Tool("Spass",    "nms",          "Sneakers-Entschlüsselungseffekt",                    "ls -la | nms",                                      "nms"),
]


LINUX_ALIASES = {
    "fd":  "fdfind",
    "bat": "batcat",
}

_FZF_BASE = [
    "fzf", "--ansi",
    "--height=80%", "--layout=reverse", "--border=rounded",
    "--color=header:italic:cyan,prompt:green,pointer:green,border:blue",
]


def is_available(tool: Tool) -> bool:
    if IS_MAC and not tool.mac:
        return False
    if IS_LINUX and not tool.linux:
        return False
    binary = LINUX_ALIASES.get(tool.binary, tool.binary) if IS_LINUX else tool.binary
    return shutil.which(binary) is not None


def resolve_command(cmd: str) -> str:
    if IS_LINUX:
        for mac_bin, linux_bin in LINUX_ALIASES.items():
            if cmd == mac_bin or cmd.startswith(mac_bin + " "):
                return linux_bin + cmd[len(mac_bin):]
    return cmd


def open_new_window(command: str) -> None:
    """Öffnet den Befehl in einem neuen Fenster im aktuellen Verzeichnis."""
    full_cmd = f"cd {shlex.quote(CURRENT_DIR)} && {command}"

    if IS_MAC:
        escaped = full_cmd.replace("\\", "\\\\").replace('"', '\\"')
        script = (
            'tell application "iTerm2"\n'
            '    activate\n'
            '    set w to (create window with current profile)\n'
            '    tell current session of w\n'
            f'        write text "{escaped}"\n'
            '    end tell\n'
            'end tell\n'
        )
        subprocess.run(["osascript", "-e", script], capture_output=True)
        return

    # Linux: Terminal-Emulator nach Verfügbarkeit
    bash_cmd = f"{command}; exec bash"
    candidates = [
        ("xfce4-terminal", ["xfce4-terminal",
                             f"--working-directory={CURRENT_DIR}",
                             "-e", f"bash -c {shlex.quote(bash_cmd)}"]),
        ("gnome-terminal", ["gnome-terminal",
                             f"--working-directory={CURRENT_DIR}",
                             "--", "bash", "-c", bash_cmd]),
        ("kitty",          ["kitty", "--directory", CURRENT_DIR,
                             "bash", "-c", bash_cmd]),
        ("alacritty",      ["alacritty", "--working-directory", CURRENT_DIR,
                             "-e", "bash", "-c", bash_cmd]),
        ("xterm",          ["xterm", "-e",
                             f"bash -c {shlex.quote(full_cmd + '; exec bash')}"]),
    ]
    for binary, args in candidates:
        if shutil.which(binary):
            subprocess.Popen(args)
            return

    os.system(full_cmd)  # Fallback: inline


def fzf_run(items: list[str], extra_args: list[str]) -> str | None:
    result = subprocess.run(
        _FZF_BASE + extra_args,
        input="\n".join(items),
        text=True,
        capture_output=True,
    )
    return result.stdout.strip() if result.returncode == 0 and result.stdout.strip() else None


def main() -> None:
    if not shutil.which("fzf"):
        print("fzf nicht gefunden – bitte installieren:")
        print("  macOS:  brew install fzf")
        print("  Linux:  sudo apt install fzf")
        sys.exit(1)

    available  = [t for t in TOOLS if is_available(t)]
    categories = list(dict.fromkeys(t.category for t in available))
    ALL        = "★  Alle Tools"

    # Kategorie-Vorschau: Anzahl verfügbarer Tools pro Kategorie
    cat_counts = {c: sum(1 for t in available if t.category == c) for c in categories}
    cat_items  = [f"{ALL}  ({len(available)})"] + [
        f"{c}  ({cat_counts[c]})" for c in categories
    ]

    # Preview für Kategorien: Tools der markierten Kategorie anzeigen
    # {1} = Kategoriename (erstes Wort), fzf-Feldreferenz
    cat_preview = (
        "cat << 'CATEOF'\n"  # Dummy — wir nutzen awk auf die Eingabeliste
    )
    # Einfacherer Ansatz: kein Preview auf Kategorie-Ebene, nur auf Tool-Ebene

    while True:
        # ── Schritt 1: Kategorie wählen ──────────────────────────────────────
        cat_choice = fzf_run(
            cat_items,
            [
                "--prompt=  Kategorie > ",
                "--header= toolbox  ·  Kategorie wählen  (Esc = beenden)",
                "--no-preview",
            ],
        )
        if not cat_choice:
            sys.exit(0)

        if cat_choice.startswith(ALL[:3]):          # "★  Alle …"
            filtered, cat_label = available, "Alle Tools"
        else:
            cat_label = cat_choice.split("  (")[0]  # Name ohne "(N)"
            filtered  = [t for t in available if t.category == cat_label]

        # ── Schritt 2: Tool wählen ───────────────────────────────────────────
        # Felder TAB-getrennt: name \t description \t command
        tool_lines = [f"{t.name}\t{t.description}\t{t.command}" for t in filtered]

        # Preview zeigt Beschreibung + Befehl für das markierte Tool.
        # {2} und {3} sind fzf-Feldreferenzen (TAB-Delimiter), werden von fzf
        # korrekt gequotet, bevor sie in den Shell-Befehl eingefügt werden.
        preview = r"printf '\n  \033[1m%s\033[0m\n\n  \033[33m$\033[0m %s\n' {2} {3}"

        chosen = fzf_run(
            tool_lines,
            [
                f"--prompt=  {cat_label} > ",
                f"--header= ‹ {cat_label}   (Esc = zurück zur Kategorie)",
                "--delimiter=\t",
                "--with-nth=1,2",
                f"--preview={preview}",
                "--preview-window=bottom:5:wrap",
            ],
        )

        if not chosen:
            continue  # Esc → zurück zur Kategorie-Auswahl

        parts = chosen.split("\t")
        if len(parts) < 3:
            continue

        tool_name, _, tool_cmd = parts[0], parts[1], parts[2]
        command = resolve_command(tool_cmd)
        print(f"\n▶  {tool_name}  —  {command}\n")
        open_new_window(command)
        sys.exit(0)


if __name__ == "__main__":
    main()
