#!/usr/bin/env bash
#
# Metool Bootstrap Script
#
# This script sets up a fresh Mac or Linux workstation with:
# 1. Metool - modular shell environment management
# 2. Metool-packages - public package collection (including keycutter)
# 3. Keycutter - SSH key management with FIDO/YubiKey support
# 4. (Optional) Private packages module after SSH setup
#
# Quick install:
#   curl -fsSL https://raw.githubusercontent.com/mbailey/metool/main/contrib/bootstrap | bash
#
# Or with options:
#   curl -fsSL https://raw.githubusercontent.com/mbailey/metool/main/contrib/bootstrap | bash -s -- --skip-keycutter
#
set -euo pipefail

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color

# Logging functions
log() { echo -e "${GREEN}[bootstrap]${NC} $*"; }
error() { echo -e "${RED}[bootstrap]${NC} $*" >&2; }
warn() { echo -e "${YELLOW}[bootstrap]${NC} $*"; }
info() { echo -e "${BLUE}[bootstrap]${NC} $*"; }
header() { echo -e "\n${BOLD}${CYAN}=== $* ===${NC}\n"; }

# Default configuration
SKIP_KEYCUTTER=false
SKIP_PRIVATE=false
PRIVATE_MODULE_URL=""
METOOL_INSTALL_URL="https://raw.githubusercontent.com/mbailey/metool/main/install.sh"

# Parse arguments
parse_args() {
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --skip-keycutter)
                SKIP_KEYCUTTER=true
                shift
                ;;
            --skip-private)
                SKIP_PRIVATE=true
                shift
                ;;
            --private-module)
                PRIVATE_MODULE_URL="$2"
                shift 2
                ;;
            -h|--help)
                show_help
                exit 0
                ;;
            *)
                error "Unknown option: $1"
                show_help
                exit 1
                ;;
        esac
    done
}

show_help() {
    cat << 'EOF'
Metool Bootstrap Script

Usage: bootstrap [OPTIONS]

Options:
    --skip-keycutter    Skip keycutter installation and SSH key setup
    --skip-private      Skip prompting for private module
    --private-module URL  Pre-specify private module URL
    -h, --help          Show this help

Examples:
    # Full bootstrap (interactive)
    curl -fsSL https://raw.githubusercontent.com/mbailey/metool/main/contrib/bootstrap | bash

    # Skip keycutter setup
    curl -fsSL https://raw.githubusercontent.com/mbailey/metool/main/contrib/bootstrap | bash -s -- --skip-keycutter

    # With pre-specified private module
    curl -fsSL https://raw.githubusercontent.com/mbailey/metool/main/contrib/bootstrap | bash -s -- --private-module git@github.com:user/metool-packages-dev.git
EOF
}

# Check if command exists
command_exists() {
    command -v "$1" >/dev/null 2>&1
}

# Detect OS
detect_os() {
    if [[ "$OSTYPE" == "linux-gnu"* ]]; then
        echo "linux"
    elif [[ "$OSTYPE" == "darwin"* ]]; then
        echo "macos"
    else
        echo "unsupported"
    fi
}

# Check prerequisites
check_prerequisites() {
    header "Checking Prerequisites"

    local os=$(detect_os)
    local missing_deps=()

    # Git is required
    if ! command_exists git; then
        missing_deps+=("git")
    else
        log "Git installed"
    fi

    # Curl is required for downloading
    if ! command_exists curl; then
        missing_deps+=("curl")
    else
        log "Curl installed"
    fi

    # macOS-specific checks
    if [[ "$os" == "macos" ]]; then
        if ! command_exists brew; then
            warn "Homebrew not installed"
            info "Installing Homebrew..."
            /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

            # Add Homebrew to PATH for this session
            if [[ -f /opt/homebrew/bin/brew ]]; then
                eval "$(/opt/homebrew/bin/brew shellenv)"
            elif [[ -f /usr/local/bin/brew ]]; then
                eval "$(/usr/local/bin/brew shellenv)"
            fi
        fi
        log "Homebrew installed"
    fi

    # Install missing dependencies
    if [[ ${#missing_deps[@]} -gt 0 ]]; then
        error "Missing dependencies: ${missing_deps[*]}"

        if [[ "$os" == "macos" ]]; then
            info "Installing with Homebrew..."
            brew install "${missing_deps[@]}"
        elif [[ "$os" == "linux" ]]; then
            if command_exists apt-get; then
                info "Installing with apt..."
                sudo apt-get update && sudo apt-get install -y "${missing_deps[@]}"
            elif command_exists dnf; then
                info "Installing with dnf..."
                sudo dnf install -y "${missing_deps[@]}"
            else
                error "Please install manually: ${missing_deps[*]}"
                exit 1
            fi
        fi
    fi

    log "All prerequisites met"
}

# Install metool
install_metool() {
    header "Installing Metool"

    # Check if metool is already installed
    if command_exists mt || command_exists mtbin; then
        log "Metool appears to be installed"

        # Source metool to ensure it's available
        if [[ -f "$HOME/.metool/shell/metool/mt" ]]; then
            source "$HOME/.metool/shell/metool/mt"
            log "Metool loaded"
            return 0
        fi
    fi

    # Run metool installer
    info "Running metool installer..."
    curl -fsSL "$METOOL_INSTALL_URL" | bash

    # Source metool for this session
    if [[ -f "$HOME/.metool/shell/metool/mt" ]]; then
        source "$HOME/.metool/shell/metool/mt"
        log "Metool installed and loaded"
    else
        error "Metool installation may have failed"
        error "Please check ~/.metool/ and try again"
        exit 1
    fi
}

# Add metool-packages module and pull dependencies
setup_public_packages() {
    header "Setting Up Public Packages"

    # Check if module already added
    if [[ -L "$HOME/.metool/shell/modules/metool-packages" ]]; then
        log "metool-packages module already in working set"
    else
        info "Adding metool-packages module..."
        mt module add mbailey/metool-packages
    fi

    # Get the module path
    local module_path
    module_path=$(readlink -f "$HOME/.metool/shell/modules/metool-packages" 2>/dev/null || echo "")

    if [[ -z "$module_path" ]] || [[ ! -d "$module_path" ]]; then
        error "Failed to locate metool-packages module"
        exit 1
    fi

    # Check for .repos.txt and pull dependencies
    if [[ -f "$module_path/.repos.txt" ]]; then
        info "Pulling package dependencies (this may take a few minutes)..."

        # Run mt git pull in the module directory
        pushd "$module_path" > /dev/null
        mt git pull || {
            warn "Some repositories may have failed to clone"
            warn "You can retry later with: cd $module_path && mt git pull"
        }
        popd > /dev/null

        log "Package dependencies pulled"
    else
        warn "No .repos.txt found in metool-packages"
    fi
}

# Install keycutter package
install_keycutter() {
    header "Installing Keycutter"

    if [[ "$SKIP_KEYCUTTER" == "true" ]]; then
        info "Skipping keycutter installation (--skip-keycutter)"
        return 0
    fi

    # Check if keycutter is already available
    if command_exists keycutter; then
        log "Keycutter already installed"
    else
        # Check if keycutter package exists in metool-packages
        local keycutter_pkg="$HOME/.metool/shell/modules/metool-packages/keycutter"

        if [[ -L "$keycutter_pkg" ]] || [[ -d "$keycutter_pkg" ]]; then
            info "Installing keycutter package..."
            mt package add metool-packages/keycutter || {
                warn "Failed to add keycutter to package working set"
            }
            mt package install keycutter || {
                warn "Failed to install keycutter package"
                warn "You can install manually with: mt package install keycutter"
            }
        else
            warn "Keycutter package not found in metool-packages"
            warn "It may not have been cloned yet"
            warn "Try running: cd ~/.metool/shell/modules/metool-packages && mt git pull"
        fi
    fi

    # Guide through keycutter setup if available
    if command_exists keycutter; then
        setup_keycutter
    fi
}

# Guide user through keycutter setup
setup_keycutter() {
    header "SSH Key Setup with Keycutter"

    echo
    info "Keycutter is installed and ready to set up SSH keys."
    info "FIDO SSH keys provide hardware-backed security for your Git operations."
    echo

    # Check if user already has SSH keys
    local existing_keys=0
    if [[ -d "$HOME/.ssh/keycutter/keys" ]]; then
        existing_keys=$(find "$HOME/.ssh/keycutter/keys" -name "*.pub" 2>/dev/null | wc -l)
    fi

    if [[ $existing_keys -gt 0 ]]; then
        log "Found $existing_keys existing keycutter SSH key(s)"
        info "To create additional keys: keycutter create github.com_username"
        return 0
    fi

    echo "Would you like to set up SSH keys now?"
    echo "  1) Yes, set up SSH keys (recommended)"
    echo "  2) No, I'll do it later"
    echo
    read -p "Choice [1/2]: " -n 1 -r choice
    echo

    case "$choice" in
        1|"")
            echo
            info "To create a GitHub SSH key, you'll need:"
            info "  - A YubiKey or other FIDO2 device"
            info "  - Your GitHub username"
            echo
            read -p "Enter your GitHub username: " github_user

            if [[ -n "$github_user" ]]; then
                info "Creating SSH key for github.com_${github_user}..."
                keycutter create "github.com_${github_user}" || {
                    warn "Key creation may have failed"
                    warn "You can try again with: keycutter create github.com_${github_user}"
                }
            else
                warn "No username provided, skipping key creation"
                info "Create a key later with: keycutter create github.com_username"
            fi
            ;;
        2)
            info "SSH key setup skipped"
            info "Create keys later with: keycutter create github.com_username"
            ;;
        *)
            warn "Invalid choice, skipping SSH key setup"
            ;;
    esac
}

# Set up private packages module
setup_private_packages() {
    header "Private Packages (Optional)"

    if [[ "$SKIP_PRIVATE" == "true" ]]; then
        info "Skipping private module setup (--skip-private)"
        return 0
    fi

    # Use pre-specified URL if provided
    local private_url="$PRIVATE_MODULE_URL"

    if [[ -z "$private_url" ]]; then
        echo
        info "You can add a private packages module (requires SSH keys)."
        info "This is typically for personal/work-specific packages."
        echo
        echo "Enter private module URL (or press Enter to skip):"
        echo "  Example: git@github.com:username/metool-packages-dev.git"
        echo "  Example: username/metool-packages-dev"
        echo
        read -p "Private module URL: " private_url
    fi

    if [[ -z "$private_url" ]]; then
        info "No private module specified, skipping"
        return 0
    fi

    info "Adding private module: $private_url"

    if mt module add "$private_url"; then
        log "Private module added"

        # Extract module name for pulling
        local module_name
        module_name=$(basename "${private_url%.git}")

        local module_path="$HOME/.metool/shell/modules/$module_name"

        if [[ -d "$module_path" ]] && [[ -f "$module_path/.repos.txt" ]]; then
            info "Pulling private module dependencies..."
            pushd "$module_path" > /dev/null
            mt git pull || warn "Some dependencies may have failed"
            popd > /dev/null
        fi

        echo
        info "Private module ready!"
        info "List packages with: mt package list $module_name/*"
        info "Install packages with: mt package add $module_name/package-name && mt package install package-name"
    else
        error "Failed to add private module"
        error "This may be because SSH keys aren't set up yet"
        info "After setting up SSH, add module with: mt module add $private_url"
    fi
}

# Print summary
print_summary() {
    header "Bootstrap Complete!"

    echo -e "${GREEN}Metool is now installed and configured.${NC}"
    echo
    echo "Quick reference:"
    echo "  mt module list          # List installed modules"
    echo "  mt package list         # List available packages"
    echo "  mt package install PKG  # Install a package"
    echo "  mt --help               # Show all commands"
    echo

    if command_exists keycutter; then
        echo "Keycutter commands:"
        echo "  keycutter create SERVICE_USER  # Create SSH key"
        echo "  keycutter --help               # Show all commands"
        echo
    fi

    echo "Next steps:"
    echo "  1. Start a new terminal (or run: source ~/.bashrc)"

    if ! command_exists keycutter || [[ "$SKIP_KEYCUTTER" == "true" ]]; then
        echo "  2. Set up SSH keys: keycutter create github.com_username"
    fi

    echo
    info "Documentation: https://github.com/mbailey/metool"
}

# Main function
main() {
    parse_args "$@"

    echo
    echo -e "${BOLD}${CYAN}"
    echo "  __  __      _              _   ____              _       _                   "
    echo " |  \/  | ___| |_ ___   ___ | | | __ )  ___   ___ | |_ ___| |_ _ __ __ _ _ __  "
    echo " | |\/| |/ _ \ __/ _ \ / _ \| | |  _ \ / _ \ / _ \| __/ __| __| '__/ _\` | '_ \ "
    echo " | |  | |  __/ || (_) | (_) | | | |_) | (_) | (_) | |_\__ \ |_| | | (_| | |_) |"
    echo " |_|  |_|\___|\__\___/ \___/|_| |____/ \___/ \___/ \__|___/\__|_|  \__,_| .__/ "
    echo "                                                                        |_|    "
    echo -e "${NC}"
    echo

    check_prerequisites
    install_metool
    setup_public_packages
    install_keycutter
    setup_private_packages
    print_summary
}

# Run main
main "$@"
