#!/usr/bin/env bash
# git_push_all_remotes
# --------------------
# Hace commit de todos los cambios pendientes (si los hay) y pushea
# a todos los remotes configurados en el repositorio.
#
# USO:
#   source git_push_all_remotes.sh
#   git_push_all_remotes [--message "mensaje"]
#
# ARGUMENTOS:
#   --message "msg"  Mensaje de commit (si hay cambios). Si se omite y hay
#                    cambios, sale con error.

git_push_all_remotes() {
    local commit_msg=""

    # Parsear argumentos
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --message|-m)
                commit_msg="$2"
                shift 2
                ;;
            *)
                shift
                ;;
        esac
    done

    # Validar repo
    if ! git rev-parse --is-inside-work-tree &>/dev/null; then
        echo "git_push_all_remotes: el directorio actual no es un repositorio Git" >&2
        return 1
    fi

    local branch
    branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null)"

    local remotes
    remotes="$(git remote 2>/dev/null || true)"

    if [[ -z "$remotes" ]]; then
        echo "git_push_all_remotes: no hay remotes configurados en este repositorio" >&2
        return 1
    fi

    echo "Rama actual:  ${branch}"
    echo "Remotes:"
    echo "$remotes" | while IFS= read -r r; do
        local url
        url="$(git remote get-url "$r" 2>/dev/null || echo "?")"
        echo "  ${r} → ${url}"
    done
    echo ""

    # Gestión del commit si hay cambios
    local has_changes=false
    if [[ -n "$(git status --porcelain 2>/dev/null)" ]]; then
        has_changes=true
    fi

    if [[ "$has_changes" == true ]]; then
        if [[ -z "$commit_msg" ]]; then
            echo "git_push_all_remotes: hay cambios pero no se proporcionó --message" >&2
            echo "  Usa: git_push_all_remotes --message \"tu mensaje\"" >&2
            return 1
        fi

        echo "Cambios detectados:"
        git status --short | while IFS= read -r line; do
            echo "  ${line}"
        done
        echo ""

        echo "Añadiendo todos los cambios..."
        git add -A

        echo "Haciendo commit: \"${commit_msg}\""
        git commit -m "$commit_msg"
        echo ""
    else
        echo "Directorio de trabajo limpio. Se empujarán commits existentes."
        echo ""
    fi

    # Push a cada remote
    local ok_count=0
    local fail_count=0
    local failed_remotes=()
    local remote_count
    remote_count="$(echo "$remotes" | wc -l | tr -d ' ')"

    while IFS= read -r remote; do
        # Verificar si la rama existe en el remote
        local push_flags=""
        if ! git ls-remote --heads "$remote" "$branch" 2>/dev/null | grep -q "$branch"; then
            push_flags="--set-upstream"
            echo "La rama '${branch}' no existe en '${remote}', se creará"
        fi

        echo "Push → ${remote} (${branch})..."
        # shellcheck disable=SC2086
        if git push $push_flags "$remote" "$branch" 2>&1; then
            echo "  Push completado → ${remote}/${branch}"
            ok_count=$((ok_count + 1))
        else
            echo "  Falló el push a ${remote}/${branch}" >&2
            fail_count=$((fail_count + 1))
            failed_remotes+=("$remote")
        fi
        echo ""
    done <<< "$remotes"

    echo "=== Resumen ==="
    echo "Push completado en ${ok_count}/${remote_count} remote(s)"

    if [[ $fail_count -gt 0 ]]; then
        echo "Fallaron ${fail_count} remote(s): ${failed_remotes[*]}" >&2
        return 1
    fi
}

# Ejecutar si se invoca directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    git_push_all_remotes "$@"
fi
