#!/bin/bash

# Git Prepare-commit-msg Hook para generar mensajes automáticos con Claude
# Archivo: .git/hooks/prepare-commit-msg

set -e

# Configuración
CLAUDE_CLI="claude"
TEMP_DIR="/tmp/commit-msg-$$"
MAX_FILE_SIZE=100000
AUTO_COMMIT_ENABLED=true

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

# Función para logging
log() {
    printf "${GREEN}[PREPARE-MSG]${NC} %s\n" "$1" >&2
}

warning() {
    printf "${YELLOW}[WARNING]${NC} %s\n" "$1" >&2
}

# Función para limpiar archivos temporales
cleanup() {
    rm -rf "$TEMP_DIR"
}
trap cleanup EXIT

# Argumentos del hook
COMMIT_MSG_FILE="$1"
COMMIT_SOURCE="$2"

# Solo procesar si es un commit normal
if [ "$COMMIT_SOURCE" != "" ] && [ "$COMMIT_SOURCE" != "message" ]; then
    exit 0
fi

# Leer el mensaje actual
CURRENT_MSG=$(head -n 1 "$COMMIT_MSG_FILE" 2>/dev/null || echo "")

# Verificar si necesitamos generar mensaje
if [ "$CURRENT_MSG" = "auto" ]; then
    log "Intentando generar mensaje..."
else
    exit 0
fi

# Verificar si Claude CLI está instalado
if ! command -v "$CLAUDE_CLI" &> /dev/null; then
    warning "Claude CLI no está instalado"
    warning "Commit cancelado. Ejecuta nuevamente sin 'auto' para escribir mensaje manual"
    exit 1
fi

mkdir -p "$TEMP_DIR"
PROMPT_FILE="$TEMP_DIR/commit_msg_prompt.txt"

cat > "$PROMPT_FILE" << 'EOF'
Analiza los siguientes cambios y genera un mensaje de commit siguiendo el formato Conventional Commits.

Responde SOLO con un JSON válido:

{
  "type": "feat|fix|docs|style|refactor|test|chore|ci|perf",
  "scope": "alcance opcional (ej: api, frontend, db)",
  "title": "descripción corta en presente (max 50 chars)",
  "body": "descripción detallada opcional"
}

CAMBIOS A ANALIZAR:
EOF

# Obtener archivos staged
ALL_STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null || echo "")

if [ -z "$ALL_STAGED_FILES" ]; then
    warning "No hay archivos staged"
    warning "Commit cancelado. Ejecuta nuevamente sin 'auto' para escribir mensaje manual"
    exit 1
fi

printf "\nArchivos modificados:\n" >> "$PROMPT_FILE"
echo "$ALL_STAGED_FILES" >> "$PROMPT_FILE"

printf "\nResumen de cambios:\n" >> "$PROMPT_FILE"
git diff --cached --stat >> "$PROMPT_FILE" 2>/dev/null || echo "No se pudo obtener estadísticas"

# Mostrar diffs de archivos pequeños
for FILE in $ALL_STAGED_FILES; do
    if [ -f "$FILE" ]; then
        FILE_SIZE=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE" 2>/dev/null || echo "0")
        
        if [ "$FILE_SIZE" -lt "$MAX_FILE_SIZE" ]; then
            printf "\n--- Diff de %s ---\n" "$FILE" >> "$PROMPT_FILE"
            git diff --cached "$FILE" >> "$PROMPT_FILE" 2>/dev/null || echo "No se pudo obtener diff"
        fi
    fi
done

RESPONSE_FILE="$TEMP_DIR/commit_msg_response.txt"
log "Generando mensaje de commit con Claude..."

if $CLAUDE_CLI < "$PROMPT_FILE" > "$RESPONSE_FILE" 2>&1; then
    JSON_MSG=$(sed -n '/^{/,/^}/p' "$RESPONSE_FILE" | head -n 1000)
    
    if [ -n "$JSON_MSG" ]; then
        MSG_TYPE=$(echo "$JSON_MSG" | jq -r '.type // "feat"' 2>/dev/null || echo "feat")
        MSG_SCOPE=$(echo "$JSON_MSG" | jq -r '.scope // ""' 2>/dev/null || echo "")
        MSG_TITLE=$(echo "$JSON_MSG" | jq -r '.title // ""' 2>/dev/null || echo "")
        MSG_BODY=$(echo "$JSON_MSG" | jq -r '.body // ""' 2>/dev/null || echo "")
        
        if [ -n "$MSG_TITLE" ]; then
            FULL_MESSAGE="$MSG_TYPE"
            if [ -n "$MSG_SCOPE" ] && [ "$MSG_SCOPE" != "null" ]; then
                FULL_MESSAGE="${FULL_MESSAGE}(${MSG_SCOPE})"
            fi
            FULL_MESSAGE="${FULL_MESSAGE}: ${MSG_TITLE}"
            
            if [ -n "$MSG_BODY" ] && [ "$MSG_BODY" != "null" ]; then
                FULL_MESSAGE="${FULL_MESSAGE}\n\n${MSG_BODY}"
            fi
            
            printf "%s\n" "$FULL_MESSAGE" > "$COMMIT_MSG_FILE"
            log "📝 Mensaje generado: $(echo "$FULL_MESSAGE" | head -n 1)"
            exit 0
        fi
    fi
fi

warning "No se pudo generar el mensaje automáticamente con Claude"
warning "Commit cancelado. Ejecuta nuevamente sin 'auto' para escribir mensaje manual"
exit 1