#!/bin/bash

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

failed_repos=()
failed_msgs=()
success_repos=()

gitdirs=$(find . -type d -name ".git")

for gitdir in $gitdirs; do
    repo=$(dirname "$gitdir")
    cd "$repo" || continue
    echo -e "${CYAN}📁 Processing: $repo${NC}"
    repo_failed=0
    msg=""

    # Stash uncommitted changes if any
    uncommitted=$(git status --porcelain | wc -l | tr -d ' ')
    stashed=0
    if [ "$uncommitted" -gt 0 ]; then
        echo -e "  ${YELLOW}Stashing $uncommitted uncommitted change(s)...${NC}"
        if git stash push -u -m "Auto-stash before rebase and push by script"; then
            stashed=1
        else
            echo -e "  ${RED}Failed to stash changes! Skipping repo.${NC}"
            repo_failed=1
            msg="Failed to stash changes."
        fi
    fi

    if [ "$repo_failed" -eq 0 ]; then
        # Fetch and rebase
        git remote update > /dev/null 2>&1
        if git rev-parse --abbrev-ref --symbolic-full-name @{u} > /dev/null 2>&1; then
            echo -e "  ${YELLOW}Rebasing onto upstream...${NC}"
            if ! git rebase @{u}; then
                echo -e "  ${RED}Rebase failed! Attempting to abort and restore stash.${NC}"
                git rebase --abort
                repo_failed=1
                msg="Rebase failed."
            fi
        else
            echo -e "  ${RED}No upstream branch set. Skipping rebase and push.${NC}"
            repo_failed=1
            msg="No upstream branch set."
        fi
    fi

    if [ "$repo_failed" -eq 0 ]; then
        # Push local-only commits if any
        ahead=$(git rev-list --count @{u}..HEAD 2>/dev/null)
        if [ "$ahead" -gt 0 ]; then
            echo -e "  ${YELLOW}Pushing $ahead local commit(s) to remote...${NC}"
            if ! git push; then
                echo -e "  ${RED}Push failed!${NC}"
                repo_failed=1
                msg="Push failed."
            fi
        else
            echo -e "  ${GREEN}No local-only commits to push.${NC}"
        fi
    fi

    # Restore stashed changes if any
    if [ "$stashed" -eq 1 ]; then
        echo -e "  ${YELLOW}Restoring stashed changes...${NC}"
        if ! git stash pop; then
            echo -e "  ${RED}Stash pop failed! You may need to resolve conflicts manually.${NC}"
            repo_failed=1
            msg="Stash pop failed."
        fi
    fi

    # Final check
    ahead_final=0
    if git rev-parse --abbrev-ref --symbolic-full-name @{u} > /dev/null 2>&1; then
        ahead_final=$(git rev-list --count @{u}..HEAD 2>/dev/null)
    fi
    if [ "$repo_failed" -eq 0 ] && [ "$ahead_final" -eq 0 ]; then
        echo -e "  ${GREEN}✅ Repo is up to date with remote. No local-only commits.${NC}"
        success_repos+=("$repo")
    else
        if [ "$repo_failed" -eq 0 ]; then
            msg="Still $ahead_final local-only commit(s) after push!"
        fi
        echo -e "  ${RED}❌ $msg${NC}"
        failed_repos+=("$repo")
        failed_msgs+=("$msg")
    fi

    echo -e "${CYAN}──────────────────────────────────────────────${NC}"
    cd - > /dev/null || exit
done

# Summary
printf "\n${CYAN}===== SUMMARY =====${NC}\n"
if [ ${#success_repos[@]} -gt 0 ]; then
    echo -e "${GREEN}Repos successfully rebased and pushed:${NC}"
    for repo in "${success_repos[@]}"; do
        echo -e "  $repo"
    done
fi
if [ ${#failed_repos[@]} -gt 0 ]; then
    echo -e "\n${RED}Repos with issues:${NC}"
    for i in "${!failed_repos[@]}"; do
        echo -e "  ${failed_repos[$i]}: ${failed_msgs[$i]}"
    done
fi 