#!/usr/bin/env bash
# Pipeline: full_git_pull — Pull automatico de fn_registry + sub-repos + submodules + fn sync
# Descubre repos locales, stashea dirty trees, hace pull --ff-only, actualiza submodules,
# regenera registry.db y ejecuta fn sync.
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INFRA_DIR="$SCRIPT_DIR/../infra"

source "$INFRA_DIR/discover_git_repos.sh"
source "$INFRA_DIR/git_pull_with_stash.sh"
source "$INFRA_DIR/pass_get.sh"

full_git_pull() {
    # Resolver raiz del registry. Deriva de SCRIPT_DIR (bash/functions/pipelines/)
    # para funcionar en cualquier PC sin path hardcodeado.
    local registry_root="${FN_REGISTRY_ROOT:-$(cd "$SCRIPT_DIR/../../.." && pwd)}"
    cd "$registry_root"

    echo "=== full_git_pull: inicio ===" >&2
    echo "Registry root: $registry_root" >&2

    # --- Paso 1: Descubrir repos ---
    echo "" >&2
    echo "[1/5] Descubriendo repos git..." >&2
    local repos
    repos=$(discover_git_repos "$registry_root")
    local n_repos
    n_repos=$(echo "$repos" | grep -c . || true)
    echo "  Encontrados: $n_repos repos" >&2

    # --- Paso 2: Pull de cada repo ---
    echo "" >&2
    echo "[2/5] Pullando repos..." >&2
    local pull_summary=""
    local diverged=()
    local conflicts=()

    while IFS= read -r repo; do
        [[ -z "$repo" ]] && continue
        local result
        result=$(git_pull_with_stash "$repo" 2>/dev/null || true)

        # Recuperacion automatica de [diverged]: si el merge no genera
        # conflictos lo aceptamos (ort strategy) — TBD: master debe quedar
        # alineado con remote tras /full-git-pull. Si hay conflictos,
        # abortamos el merge y reportamos para intervencion manual.
        if [[ "$result" == "[diverged]"* ]]; then
            local repo_name
            repo_name="$(basename "$repo")"
            echo "  [recover] $repo_name: diverged, intentando merge auto" >&2
            local upstream
            upstream=$(git -C "$repo" rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null || true)
            if [[ -n "$upstream" ]]; then
                local merge_out
                if merge_out=$(git -C "$repo" merge --no-ff --no-edit "$upstream" 2>&1); then
                    result="[merged-auto] $repo_name (resolved against $upstream)"
                else
                    git -C "$repo" merge --abort 2>/dev/null || true
                    result="[diverged] $repo_name (merge auto con conflicto — manual)"
                fi
            fi
        fi

        if [[ -n "$result" ]]; then
            echo "  $result" >&2
            pull_summary="$pull_summary"$'\n'"  $result"
            if [[ "$result" == "[diverged]"* ]]; then
                diverged+=("$repo")
            elif [[ "$result" == "[stash-conflict]"* ]]; then
                conflicts+=("$repo")
            fi
        fi
    done <<< "$repos"

    # --- Paso 3: Submodules del repo principal ---
    echo "" >&2
    echo "[3/5] Actualizando submodulos del repo principal..." >&2
    local submodule_summary="  [skip] sin submodulos"
    if [[ -f "$registry_root/.gitmodules" ]]; then
        local sub_out
        sub_out=$(git -C "$registry_root" submodule update --init --recursive 2>&1 | tail -10 || true)
        echo "$sub_out" >&2
        submodule_summary="  OK: $sub_out"
    fi

    # --- Paso 3b: Pull de ~/.password-store ---
    echo "" >&2
    echo "[3b] Pullando ~/.password-store..." >&2
    local pass_dir="${PASSWORD_STORE_DIR:-$HOME/.password-store}"
    local pass_summary="  [skip] password-store: no encontrado"
    if [[ -d "$pass_dir/.git" ]]; then
        local pass_result
        pass_result=$(git_pull_with_stash "$pass_dir" 2>/dev/null || true)
        echo "  $pass_result" >&2
        pass_summary="  $pass_result"
        if [[ "$pass_result" == "[diverged]"* ]]; then
            diverged+=("$pass_dir")
        elif [[ "$pass_result" == "[stash-conflict]"* ]]; then
            conflicts+=("$pass_dir")
        fi
    fi

    # --- Paso 4: Regenerar registry.db ---
    echo "" >&2
    echo "[4/5] Regenerando registry.db..." >&2
    local index_summary="  [skip] fn no encontrado"
    local fn_bin="$registry_root/fn"
    if [[ -x "$fn_bin" ]]; then
        local index_out
        index_out=$(CGO_ENABLED=1 "$fn_bin" index 2>&1 | tail -3 || true)
        echo "$index_out" >&2
        index_summary="  OK: $index_out"
    else
        echo "  [warn] $fn_bin no encontrado — intentando build..." >&2
        if command -v go >/dev/null 2>&1; then
            CGO_ENABLED=1 go build -tags fts5 -o "$fn_bin" "$registry_root/cmd/fn/" 2>&1 >&2 || true
            if [[ -x "$fn_bin" ]]; then
                local index_out
                index_out=$(CGO_ENABLED=1 "$fn_bin" index 2>&1 | tail -3 || true)
                echo "$index_out" >&2
                index_summary="  OK (post-build): $index_out"
            fi
        fi
    fi

    # --- Paso 5: fn sync ---
    echo "" >&2
    echo "[5/5] Ejecutando fn sync..." >&2
    local sync_summary="  [skip] fn sync: credenciales no disponibles"
    if [[ -x "$fn_bin" ]]; then
        local api_user api_pass api_token
        api_user=$(pass_get registry/basicauth-user | head -n1 2>/dev/null || true)
        api_pass=$(pass_get registry/basicauth-pass | head -n1 2>/dev/null || true)
        api_token=$(pass_get registry/api-token | head -n1 2>/dev/null || true)

        if [[ -n "$api_user" && -n "$api_pass" && -n "$api_token" ]]; then
            export FN_REGISTRY_API="https://${api_user}:${api_pass}@registry.organic-machine.com"
            export REGISTRY_API_TOKEN="$api_token"
            local sync_out
            sync_out=$("$fn_bin" sync 2>&1) && {
                sync_summary="  OK: $sync_out"
            } || {
                sync_summary="  [error] fn sync: $sync_out"
            }
            echo "  $sync_summary" >&2
        else
            echo "  [warn] Credenciales registry no disponibles — omitiendo fn sync" >&2
        fi
    fi

    # --- Paso 6: Reclonar sub-repos hijos de cada project (issue 0171) ---
    # Tras fn sync, registry.db contiene las filas apps/analysis de TODOS los PCs.
    # clone_project_subrepos clona en este disco los hijos que falten (skip si ya
    # existen). Asi, clonar el project paraguas y correr /full-git-pull reconstruye
    # su arbol entero sin adivinar nombres de sub-repos: registry.db ES el manifest.
    echo "" >&2
    echo "[6/6] Reclonando sub-repos de projects..." >&2
    local reclone_summary="  [skip] sin projects o registry.db"
    if [[ -f "$registry_root/registry.db" ]] && command -v sqlite3 >/dev/null 2>&1; then
        export FN_REGISTRY_ROOT="$registry_root"
        export GITEA_URL="${GITEA_URL:-$(pass_get agentes/gitea-url | head -n1 2>/dev/null || true)}"
        local clone_script="$SCRIPT_DIR/clone_project_subrepos.sh"
        local any_cloned=0
        if [[ -f "$clone_script" ]]; then
            while IFS= read -r proj_id; do
                [[ -z "$proj_id" ]] && continue
                local clone_out
                clone_out=$(bash "$clone_script" "$proj_id" 2>&1 || true)
                if echo "$clone_out" | grep -q '\[cloned\]'; then
                    any_cloned=1
                    echo "  $proj_id: nuevos sub-repos clonados" >&2
                fi
            done < <(sqlite3 "$registry_root/registry.db" "SELECT id FROM projects;" 2>/dev/null)
            if [[ "$any_cloned" -eq 1 ]]; then
                echo "  re-index tras clonado..." >&2
                [[ -x "$fn_bin" ]] && CGO_ENABLED=1 "$fn_bin" index >/dev/null 2>&1 || true
                reclone_summary="  OK: nuevos sub-repos clonados + re-index"
            else
                reclone_summary="  OK: nada que clonar (todo presente)"
            fi
        else
            reclone_summary="  [skip] clone_project_subrepos.sh no encontrado"
        fi
    fi
    echo "  $reclone_summary" >&2

    # --- Resumen ---
    echo ""
    echo "===== RESUMEN full_git_pull ====="
    echo ""
    echo "Pull status por repo:"
    if [[ -n "$pull_summary" ]]; then
        echo "$pull_summary"
    else
        echo "  (ninguno)"
    fi
    echo ""
    echo "pass-secrets:"
    echo "$pass_summary"
    echo ""
    echo "Submodulos:"
    echo "$submodule_summary"
    echo ""
    echo "fn index:"
    echo "$index_summary"
    echo ""
    echo "fn sync:"
    echo "$sync_summary"
    echo ""
    echo "Reclonado sub-repos de projects:"
    echo "$reclone_summary"

    if [[ ${#diverged[@]} -gt 0 || ${#conflicts[@]} -gt 0 ]]; then
        echo ""
        echo "[!!] ATENCION — el agente DEBE resolver antes de declarar pull OK:"
        for r in "${diverged[@]+"${diverged[@]}"}"; do
            echo "  [diverged] $r  → git rebase o git merge manual"
        done
        for r in "${conflicts[@]+"${conflicts[@]}"}"; do
            echo "  [stash-conflict] $r  → resolver conflicto y git stash drop"
        done
        echo ""
        echo "================================="
        return 1
    fi

    echo ""
    echo "================================="
}

full_git_pull "$@"
