#!/bin/bash
# setup-jupyter.sh - Automatiza la configuración de Jupyter + MCP para Claude
# Uso: ./setup-jupyter.sh [ruta-proyecto]
# Generado para el skill /init-jupyter

set -e

# Colores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# ═══════════════════════════════════════════════════════════════
# FUNCIONES AUXILIARES
# ═══════════════════════════════════════════════════════════════

log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_ok() { echo -e "${GREEN}[OK]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }

find_free_port() {
    for port in 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899; do
        if ! lsof -i:$port >/dev/null 2>&1; then
            echo $port
            return
        fi
    done
    echo 8888
}

# ═══════════════════════════════════════════════════════════════
# PASO 0: CAMBIAR AL DIRECTORIO DEL PROYECTO
# ═══════════════════════════════════════════════════════════════

RUTA="${1:-.}"
cd "$RUTA" || { log_error "No se pudo acceder a: $RUTA"; exit 1; }
PROJECT_PATH=$(pwd)

echo ""
echo "═══════════════════════════════════════════════════════════════"
echo "  SETUP JUPYTER + MCP para Claude"
echo "  Proyecto: $PROJECT_PATH"
echo "═══════════════════════════════════════════════════════════════"
echo ""

# ═══════════════════════════════════════════════════════════════
# PASO 1: VERIFICACIONES DE ESTADO
# ═══════════════════════════════════════════════════════════════

log_info "Verificando estado actual..."

# Variables de estado
MCP_LOCAL=false
REPO_CONFIG=false
JUPYTER_RUNNING=false
RULES_OK=false
GLOBAL_MCP=false
CURRENT_PORT=""

# 1. MCP instalado localmente
if [ -f .venv/bin/jupyter-mcp-server ]; then
    MCP_LOCAL=true
    log_ok "MCP instalado en .venv/bin/"
else
    log_warn "MCP no instalado localmente"
fi

# 2. Repo configurado (.mcp.json con jupyter)
if [ -f .mcp.json ] && grep -q "jupyter" .mcp.json 2>/dev/null; then
    REPO_CONFIG=true
    log_ok "Repo configurado (.mcp.json tiene jupyter)"
else
    log_warn "Repo no configurado para Jupyter"
fi

# 3. Jupyter corriendo en este repo
if pgrep -af "jupyter" 2>/dev/null | grep -q "$PROJECT_PATH"; then
    JUPYTER_RUNNING=true
    CURRENT_PORT=$(pgrep -af "jupyter" | grep "$PROJECT_PATH" | grep -oP 'port[= ]\K\d+' | head -1)
    [ -z "$CURRENT_PORT" ] && CURRENT_PORT=$(cat .jupyter-port 2>/dev/null || echo "desconocido")
    log_ok "Jupyter corriendo en puerto $CURRENT_PORT"
else
    log_warn "Jupyter no está corriendo"
fi

# 4. Reglas en CLAUDE.md
if [ -f .claude/CLAUDE.md ] && grep -q "JUPYTER HABILITADO" .claude/CLAUDE.md 2>/dev/null; then
    RULES_OK=true
    log_ok "Reglas Jupyter en CLAUDE.md"
else
    log_warn "Reglas Jupyter no configuradas"
fi

# 5. Instalación global (problemática)
if [ -f ~/.local/bin/jupyter-mcp-server ]; then
    GLOBAL_MCP=true
    log_warn "Existe instalación GLOBAL de jupyter-mcp-server (se eliminará)"
fi

echo ""

# ═══════════════════════════════════════════════════════════════
# DECISIÓN: ¿Ya está todo configurado?
# ═══════════════════════════════════════════════════════════════

if $MCP_LOCAL && $REPO_CONFIG && $RULES_OK; then
    if $JUPYTER_RUNNING; then
        echo "═══════════════════════════════════════════════════════════════"
        log_ok "TODO LISTO - Jupyter configurado y corriendo en puerto $CURRENT_PORT"
        echo "═══════════════════════════════════════════════════════════════"
        echo ""
        echo "STATUS: READY"
        echo "PORT: $CURRENT_PORT"
        exit 0
    else
        echo "═══════════════════════════════════════════════════════════════"
        log_ok "CONFIGURADO - Solo falta iniciar Jupyter"
        echo "═══════════════════════════════════════════════════════════════"
        echo ""
        echo "Ejecuta en otra terminal:"
        echo "  cd $PROJECT_PATH && ./run-jupyter-lab.sh"
        echo ""
        echo "STATUS: CONFIGURED_NOT_RUNNING"
        exit 0
    fi
fi

# ═══════════════════════════════════════════════════════════════
# PASO 2: ELIMINAR INSTALACIÓN GLOBAL SI EXISTE
# ═══════════════════════════════════════════════════════════════

if $GLOBAL_MCP; then
    log_info "Eliminando instalación global de jupyter-mcp-server..."
    uv tool uninstall jupyter-mcp-server 2>/dev/null || true
    pip uninstall -y jupyter-mcp-server 2>/dev/null || true
    rm -f ~/.local/bin/jupyter-mcp-server

    if [ -f ~/.local/bin/jupyter-mcp-server ]; then
        log_error "No se pudo eliminar instalación global"
    else
        log_ok "Instalación global eliminada"
    fi
fi

# ═══════════════════════════════════════════════════════════════
# PASO 3: DETECTAR PUERTO LIBRE
# ═══════════════════════════════════════════════════════════════

PUERTO=$(find_free_port)
log_info "Puerto asignado: $PUERTO"

# ═══════════════════════════════════════════════════════════════
# PASO 4: CREAR ESTRUCTURA DE CARPETAS
# ═══════════════════════════════════════════════════════════════

log_info "Creando estructura de carpetas..."
mkdir -p .claude notebooks
log_ok "Carpetas .claude/ y notebooks/ creadas"

# ═══════════════════════════════════════════════════════════════
# PASO 5: CREAR run-jupyter-lab.sh
# ═══════════════════════════════════════════════════════════════

log_info "Creando run-jupyter-lab.sh..."

cat > run-jupyter-lab.sh << 'SCRIPT'
#!/bin/bash
# Jupyter Lab para colaboración Claude + Usuario
# Generado por /init-jupyter
# REQUIERE: jupyter-collaboration instalado para que funcione el MCP

# Autodetectar puerto libre
find_free_port() {
    for port in 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899; do
        if ! lsof -i:$port >/dev/null 2>&1; then
            echo $port
            return
        fi
    done
    echo 8888
}

PORT=${1:-$(find_free_port)}

# Guardar puerto para que Claude lo lea
echo $PORT > .jupyter-port

# Activar entorno si existe
source .venv/bin/activate 2>/dev/null || true

# Verificar que jupyter-collaboration está instalado
if ! python -c "import jupyter_collaboration" 2>/dev/null; then
    echo "ERROR: jupyter-collaboration no está instalado"
    echo "Instala con: uv add jupyter-collaboration"
    exit 1
fi

echo "══════════════════════════════════════════════════════"
echo "  Jupyter Lab + Colaboración iniciando en puerto $PORT"
echo "══════════════════════════════════════════════════════"
echo ""
echo "  Abre: http://localhost:$PORT"
echo ""
echo "  Claude se conectará al kernel cuando abras un notebook"
echo "  Colaboración en tiempo real ACTIVADA"
echo "  Usa Ctrl+C para detener"
echo ""
echo "══════════════════════════════════════════════════════"

jupyter lab \
    --port=$PORT \
    --no-browser \
    --ServerApp.token='' \
    --ServerApp.password='' \
    --ServerApp.disable_check_xsrf=True \
    --ServerApp.allow_origin='*' \
    --ServerApp.root_dir="$(pwd)" \
    --YDocExtension.ystore_class='ypy_websocket.ystore.TempFileYStore' \
    --collaborative
SCRIPT

chmod +x run-jupyter-lab.sh
log_ok "run-jupyter-lab.sh creado"

# ═══════════════════════════════════════════════════════════════
# PASO 6: CREAR/ACTUALIZAR .mcp.json
# ═══════════════════════════════════════════════════════════════

log_info "Configurando .mcp.json..."

# Crear config temporal
cat > /tmp/jupyter-mcp.json << EOF
{
  "mcpServers": {
    "jupyter": {
      "command": "${PROJECT_PATH}/.venv/bin/jupyter-mcp-server",
      "args": [
        "--runtime-url", "http://localhost:${PUERTO}",
        "--start-new-runtime", "false"
      ]
    }
  }
}
EOF

# Merge o crear
if [ -f .mcp.json ]; then
    if command -v jq >/dev/null 2>&1; then
        jq -s '.[0] * .[1] | .mcpServers = (.[0].mcpServers // {}) * (.[1].mcpServers // {})' \
            .mcp.json /tmp/jupyter-mcp.json > .mcp.json.tmp
        mv .mcp.json.tmp .mcp.json
        log_ok ".mcp.json actualizado (merge)"
    else
        log_warn "jq no disponible, sobrescribiendo .mcp.json"
        mv /tmp/jupyter-mcp.json .mcp.json
    fi
else
    mv /tmp/jupyter-mcp.json .mcp.json
    log_ok ".mcp.json creado"
fi

rm -f /tmp/jupyter-mcp.json

# ═══════════════════════════════════════════════════════════════
# PASO 7: ACTUALIZAR .claude/CLAUDE.md
# ═══════════════════════════════════════════════════════════════

log_info "Configurando reglas en .claude/CLAUDE.md..."

JUPYTER_RULES='# JUPYTER HABILITADO EN ESTE REPO

Este repositorio está configurado para exploración de datos con Jupyter + Claude.

## Estado del entorno
- **Lanzador**: `./run-jupyter-lab.sh`
- **Puerto config**: ver `.jupyter-port` o `.mcp.json`
- **MCP**: jupyter-mcp-server configurado

## Reglas OBLIGATORIAS para Claude

### 1. CÓDIGO INMUTABLE - NUNCA MODIFICAR CELDAS EXISTENTES
- **PROHIBIDO** usar NotebookEdit para reemplazar celdas existentes
- **PROHIBIDO** modificar o sobrescribir notebooks completos
- **SIEMPRE** añadir celdas NUEVAS al final del notebook
- Si hay un error en una celda → crear celda nueva con la corrección, NO editar la original
- El historial de trabajo debe quedar intacto para trazabilidad

### 2. PROGRAMACIÓN FUNCIONAL OBLIGATORIA
- **Funciones puras**: sin efectos secundarios, mismo input → mismo output
- **Inmutabilidad**: nunca mutar datos, crear copias transformadas
- **Composición**: funciones pequeñas que se combinan
- **Sin estado global**: evitar variables globales mutables
- Preferir: `map`, `filter`, `reduce`, list comprehensions
- Evitar: loops con mutación, `global`, modificar argumentos in-place

Ejemplo CORRECTO:
```python
# Función pura, sin efectos secundarios
def limpiar_columna(df, col):
    return df.assign(**{col: df[col].str.strip().str.lower()})

# Composición de transformaciones
df_limpio = (df
    .pipe(limpiar_columna, "nombre")
    .pipe(limpiar_columna, "email"))
```

Ejemplo INCORRECTO:
```python
# Mutación directa - PROHIBIDO
df["nombre"] = df["nombre"].str.strip()
```

### 3. SIEMPRE usar MCP jupyter para ejecutar código Python
- Las ejecuciones se ven en tiempo real en Jupyter Lab del usuario
- Compartimos variables y estado del kernel
- **NUNCA usar bash para ejecutar Python en este repo**

### 4. Verificar Jupyter activo ANTES de ejecutar
```bash
pgrep -af "jupyter" | grep "$(pwd)" || cat .jupyter-port 2>/dev/null
```
- Si no está activo → pedir al usuario: "Ejecuta `./run-jupyter-lab.sh` en otra terminal"

### 5. Gestión de notebooks
- **TODOS los notebooks van a la carpeta `notebooks/`** o subcarpetas dentro de ella
- Si un notebook tiene >50 celdas → crear uno nuevo
- Nombrar descriptivamente: `notebooks/01_exploracion.ipynb`, `notebooks/02_limpieza.ipynb`
- Mantener notebooks enfocados en una tarea

### 6. Gestión de Python
- **SIEMPRE usar `uv` para gestionar Python** (entornos, dependencias, etc.)
- Añadir paquetes con `uv add nombre_paquete`
- Nunca usar pip directamente si uv está disponible

### 7. Antes de código pesado
- Avisar al usuario
- Usar `%%time` o `tqdm` para progreso

---

'

if [ -f .claude/CLAUDE.md ]; then
    if ! grep -q "JUPYTER HABILITADO" .claude/CLAUDE.md; then
        # Prepend
        echo "$JUPYTER_RULES" > .claude/CLAUDE.md.tmp
        cat .claude/CLAUDE.md >> .claude/CLAUDE.md.tmp
        mv .claude/CLAUDE.md.tmp .claude/CLAUDE.md
        log_ok "Reglas añadidas al principio de CLAUDE.md"
    else
        log_ok "Reglas ya existían en CLAUDE.md"
    fi
else
    echo "$JUPYTER_RULES" > .claude/CLAUDE.md
    log_ok "CLAUDE.md creado con reglas"
fi

# ═══════════════════════════════════════════════════════════════
# PASO 8: INICIALIZAR ENTORNO PYTHON E INSTALAR DEPENDENCIAS
# ═══════════════════════════════════════════════════════════════

log_info "Configurando entorno Python..."

# Crear venv si no existe
if [ ! -d .venv ]; then
    log_info "Creando venv..."
    uv venv 2>/dev/null || python -m venv .venv
fi

# Activar venv
source .venv/bin/activate 2>/dev/null || true

# Instalar dependencias
log_info "Instalando dependencias (jupyter, mcp, colaboración)..."
if command -v uv >/dev/null 2>&1; then
    # Inicializar pyproject.toml si no existe
    [ ! -f pyproject.toml ] && uv init 2>/dev/null || true
    uv add jupyter jupyterlab jupyter-collaboration jupyter-mcp-server pandas numpy matplotlib 2>/dev/null || \
    pip install jupyter jupyterlab jupyter-collaboration jupyter-mcp-server pandas numpy matplotlib
else
    pip install jupyter jupyterlab jupyter-collaboration jupyter-mcp-server pandas numpy matplotlib
fi

# Verificar instalación
echo ""
if [ -f .venv/bin/jupyter-mcp-server ]; then
    log_ok "jupyter-mcp-server instalado en venv local"
else
    log_error "jupyter-mcp-server NO instalado"
fi

if python -c "import jupyter_collaboration" 2>/dev/null; then
    log_ok "jupyter-collaboration instalado"
else
    log_warn "jupyter-collaboration no instalado"
fi

# ═══════════════════════════════════════════════════════════════
# RESUMEN FINAL
# ═══════════════════════════════════════════════════════════════

echo ""
echo "═══════════════════════════════════════════════════════════════"
echo "  CONFIGURACIÓN COMPLETADA"
echo "═══════════════════════════════════════════════════════════════"
echo ""
echo "  Proyecto: $PROJECT_PATH"
echo "  Puerto: $PUERTO"
echo ""
echo "  Archivos creados/actualizados:"
echo "  ✓ run-jupyter-lab.sh"
echo "  ✓ .mcp.json"
echo "  ✓ .claude/CLAUDE.md"
echo "  ✓ .venv/bin/jupyter-mcp-server"
echo ""
echo "  ┌─────────────────────────────────────────────────────────┐"
echo "  │  PASOS SIGUIENTES:                                      │"
echo "  │                                                         │"
echo "  │  1. SALIR de Claude Code: /exit o Ctrl+C                │"
echo "  │     (necesario para cargar el nuevo MCP)                │"
echo "  │                                                         │"
echo "  │  2. En OTRA terminal:                                   │"
echo "  │     cd $PROJECT_PATH && ./run-jupyter-lab.sh            │"
echo "  │                                                         │"
echo "  │  3. Volver a entrar a Claude:                           │"
echo "  │     cd $PROJECT_PATH && claude                          │"
echo "  │                                                         │"
echo "  │  4. Abrir en navegador: http://localhost:$PUERTO        │"
echo "  └─────────────────────────────────────────────────────────┘"
echo ""
echo "STATUS: CONFIGURED"
echo "PORT: $PUERTO"
