#!/bin/bash
#
# ECC CodeBuddy Uninstaller
# Uninstalls Everything Claude Code workflows from a CodeBuddy project.
#
# Usage:
#   ./uninstall.sh              # Uninstall from current directory
#   ./uninstall.sh ~            # Uninstall globally from ~/.codebuddy/
#

set -euo pipefail

# Resolve the directory where this script lives
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"

# CodeBuddy directory name
CODEBUDDY_DIR=".codebuddy"

resolve_path() {
    python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$1"
}

is_valid_manifest_entry() {
    local file_path="$1"

    case "$file_path" in
        ""|/*|~*|*/../*|../*|*/..|..)
            return 1
            ;;
    esac

    return 0
}

# Main uninstall function
do_uninstall() {
    local target_dir="$PWD"

    # Check if ~ was specified (or expanded to $HOME)
    if [ "$#" -ge 1 ]; then
        if [ "$1" = "~" ] || [ "$1" = "$HOME" ]; then
            target_dir="$HOME"
        fi
    fi

    # Check if we're already inside a .codebuddy directory
    local current_dir_name="$(basename "$target_dir")"
    local codebuddy_full_path

    if [ "$current_dir_name" = ".codebuddy" ]; then
        # Already inside the codebuddy directory, use it directly
        codebuddy_full_path="$target_dir"
    else
        # Normal case: append CODEBUDDY_DIR to target_dir
        codebuddy_full_path="$target_dir/$CODEBUDDY_DIR"
    fi

    echo "ECC CodeBuddy Uninstaller"
    echo "=========================="
    echo ""
    echo "Target:  $codebuddy_full_path/"
    echo ""

    if [ ! -d "$codebuddy_full_path" ]; then
        echo "Error: $CODEBUDDY_DIR directory not found at $target_dir"
        exit 1
    fi

    codebuddy_root_resolved="$(resolve_path "$codebuddy_full_path")"

    # Manifest file path
    MANIFEST="$codebuddy_full_path/.ecc-manifest"

    if [ ! -f "$MANIFEST" ]; then
        echo "Warning: No manifest file found (.ecc-manifest)"
        echo ""
        echo "This could mean:"
        echo "  1. ECC was installed with an older version without manifest support"
        echo "  2. The manifest file was manually deleted"
        echo ""
        read -p "Do you want to remove the entire $CODEBUDDY_DIR directory? (y/N) " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            echo "Uninstall cancelled."
            exit 0
        fi
        rm -rf "$codebuddy_full_path"
        echo "Uninstall complete!"
        echo ""
        echo "Removed: $codebuddy_full_path/"
        exit 0
    fi

    echo "Found manifest file - will only remove files installed by ECC"
    echo ""
    read -p "Are you sure you want to uninstall ECC from $CODEBUDDY_DIR? (y/N) " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        echo "Uninstall cancelled."
        exit 0
    fi

    # Counters
    removed=0
    skipped=0

    # Read manifest and remove files
    while IFS= read -r file_path; do
        [ -z "$file_path" ] && continue

        if ! is_valid_manifest_entry "$file_path"; then
            echo "Skipped: $file_path (invalid manifest entry)"
            skipped=$((skipped + 1))
            continue
        fi

        full_path="$codebuddy_full_path/$file_path"

        # Security check: ensure the path resolves inside the target directory.
        # Use Python to compute a reliable relative path so symlinks cannot
        # escape the boundary.
        relative="$(python3 -c 'import os,sys; print(os.path.relpath(os.path.abspath(sys.argv[1]), sys.argv[2]))' "$full_path" "$codebuddy_root_resolved")"
        case "$relative" in
            ../*|..)
                echo "Skipped: $file_path (outside target directory)"
                skipped=$((skipped + 1))
                continue
                ;;
        esac

        if [ -L "$full_path" ] || [ -f "$full_path" ]; then
            rm -f "$full_path"
            echo "Removed: $file_path"
            removed=$((removed + 1))
        elif [ -d "$full_path" ]; then
            # Only remove directory if it's empty
            if [ -z "$(ls -A "$full_path" 2>/dev/null)" ]; then
                rmdir "$full_path" 2>/dev/null || true
                if [ ! -d "$full_path" ]; then
                    echo "Removed: $file_path/"
                    removed=$((removed + 1))
                fi
            else
                echo "Skipped: $file_path/ (not empty - contains user files)"
                skipped=$((skipped + 1))
            fi
        else
            skipped=$((skipped + 1))
        fi
    done < "$MANIFEST"

    while IFS= read -r empty_dir; do
        [ "$empty_dir" = "$codebuddy_full_path" ] && continue
        relative_dir="${empty_dir#$codebuddy_full_path/}"
        rmdir "$empty_dir" 2>/dev/null || true
        if [ ! -d "$empty_dir" ]; then
            echo "Removed: $relative_dir/"
            removed=$((removed + 1))
        fi
    done < <(find "$codebuddy_full_path" -depth -type d -empty 2>/dev/null | sort -r)

    # Try to remove the main codebuddy directory if it's empty
    if [ -d "$codebuddy_full_path" ] && [ -z "$(ls -A "$codebuddy_full_path" 2>/dev/null)" ]; then
        rmdir "$codebuddy_full_path" 2>/dev/null || true
        if [ ! -d "$codebuddy_full_path" ]; then
            echo "Removed: $CODEBUDDY_DIR/"
            removed=$((removed + 1))
        fi
    fi

    echo ""
    echo "Uninstall complete!"
    echo ""
    echo "Summary:"
    echo "  Removed: $removed items"
    echo "  Skipped: $skipped items (not found or user-modified)"
    echo ""
    if [ -d "$codebuddy_full_path" ]; then
        echo "Note: $CODEBUDDY_DIR directory still exists (contains user-added files)"
    fi
}

# Execute uninstall
do_uninstall "$@"
