#!/bin/bash

set -e  # Stop the script if any command fails

RED='\033[0;31m'
GREEN='\033[0;32m'
DIM='\033[2m'
NC='\033[0m' # No Color
SILENT="--silent"

# Check if the script was invoked with the "--verbose" flag
if [[ "$1" == "--verbose" ]]; then
    SILENT=""
fi

handle_error() {
    echo -e "${RED}Error: ${NC}$1";
    echo -e "Hint, run this tool again with logging: 'pnpm repair --verbose'"
    exit 1;
}

nvm_init() {
    if [ -z "$NVM_DIR" ] || [ ! -s "$NVM_DIR/nvm.sh" ]; then
        handle_error "Node version manager (nvm) is not found. Please make sure you have it installed."
    fi

    # Depending on the user env, nvm might not have been loaded
    \. "$NVM_DIR/nvm.sh"

    nvm use $SILENT || handle_error "Failed to switch Node.js version using nvm. Please make sure you have a valid nvm installation."
}

pnpm_uninstall_non_corepack_versions() {
    # The recommended way to use pnpm is by corepack
    # Having other installs might cause issues where you end up using older pnpm versions.

    # Remove versions installed globally with npm
    npm rm -g $SILENT pnpm

    # Remove versions installed globally with brew
    if command -v brew &> /dev/null && brew list --formula | grep -q "pnpm"; then
        brew uninstall pnpm --quiet --force || handle_error "Failed to uninstall pnpm with brew."
    fi
}

pnpm_bin_uninstall() {
    pnpm_uninstall_non_corepack_versions

    # Removes the pnpm home directory. 
    # Usually this is where the cache and globally installed packages lives, but can also contain older pnpm binary versions.
    if [ -n "$PNPM_HOME" ]; then
        rm -rf "$PNPM_HOME"
    fi

    # Removes cache
    rm -rf "$(pnpm store path)"
    # Removes globally installed packages
    rm -rf "$(pnpm root -g)"
}

pnpm_bin_install() {
    corepack enable || handle_error "Failed to install pnpm using corepack. Please make sure you have a valid NodeJs installation."
}

workspace_install() {
    # Install all workspace dependencies
    pnpm install --force $SILENT || handle_error "Failed to install dependencies."
}

workspace_clean_node_modules() {
    # Removes all node_modules in workspace
    find . -name "node_modules" -type d -exec rm -rf {} + || handle_error "Failed to delete node_modules."
}

workspace_clean_artifacts() {
    # Runs the clean script for all packages
    pnpm run -r $SILENT clean || handle_error "Failed to clean workspace artifacts."

    toRemove=(
        "dist" 
        "build" 
        ".cache" 
        "tsconfig.tsbuildinfo" 
        "tsbuildinfo"
    )

    # Delete all artifacts
    for dirOrFile in "${toRemove[@]}"; do
        find . -name "${dirOrFile}" -type d -exec rm -rf {} + || handle_error "Failed to delete ${dirOrFile}."
    done
}

workspace_build() {
    # Build all packages in the workspace
    pnpm run -r $SILENT build || handle_error "Failed to build workspace packages."
}

echo -e "💊 ${GREEN}Monorepo repair${NC}"
echo -e "${DIM}This process may take some time. Feel free to take a break while it runs.${NC}\n"

# Check if pnpm-workspace.yaml file exists in the current directory
if [ ! -f "$PWD/pnpm-workspace.yaml" ]; then
    handle_error "This script must be run from the workspace root directory."
fi

echo "1. Initializing node..."
nvm_init

echo "2. Repairing pnpm installation..."
pnpm_bin_uninstall
pnpm_bin_install

echo "3. Removing node_modules..."
workspace_clean_node_modules

echo "4. Re-installing packages..."
workspace_install

echo "5. Cleaning workspace..."
workspace_clean_artifacts

echo "6. Building packages..."
workspace_build

echo -e "\n✅All done!"
