#!/usr/bin/env bash
# ==========================================================
# Rust Project Build & QA Pipeline Script (Generic)
# ----------------------------------------------------------
# Author : Alessandro Maestri
# Version: 1.9
# Date   : 2025-10-31
# Compatible with: bash / zsh (Linux, macOS, WSL)
# ==========================================================

set -e  # Exit immediately on error

# ----------------------------
# Default flags
# ----------------------------
RELEASE=false
SKIP_TESTS=false
QUIET=false
NO_CLEAN=false
VERBOSE=false
ONLY_BUILD=false
TARGET=""
SHOW_HELP=false
SHOW_TIME=false
START_TIME=0

# ----------------------------
# Helper: print Unicode emoji
# ----------------------------
print_unicode() {
    printf "\\U$1"
}

# ----------------------------
# Helper: show help text
# ----------------------------
show_help() {
    echo "===================================================="
    echo "🦀  Rust Project Build & QA Pipeline Script"
    echo "===================================================="
    echo
    echo "Usage:"
    echo "  ./build_check.sh [options]"
    echo
    echo "Options:"
    echo "  --release           Build in release mode (equivalent to 'cargo build --release')"
    echo "  --target <triple>   Specify a custom compilation target (e.g. x86_64-pc-windows-msvc)"
    echo "  --verbose, -vv      Enable verbose Cargo output (-vv)"
    echo "  --quiet             Minimal console output (suppress cargo stdout)"
    echo "  --skip-tests        Skip cargo test step"
    echo "  --no-clean          Skip cargo clean before build"
    echo "  --only-build        Run cargo build only (skip fmt, clippy, tests)"
    echo "  --time              Show total build duration at the end"
    echo "  --help, -h          Show this help message and exit"
    echo
    echo "Examples:"
    echo "  ./build_check.sh --release"
    echo "  ./build_check.sh --release --target x86_64-pc-windows-msvc"
    echo "  ./build_check.sh --only-build --time"
    echo "  ./build_check.sh --verbose"
    echo
    echo "Exit codes:"
    echo "  0 → all steps succeeded"
    echo "  1 → any step failed"
    echo
    exit 0
}

# ----------------------------
# Parse command-line arguments
# ----------------------------
while [[ $# -gt 0 ]]; do
    case "$1" in
        --release) RELEASE=true ;;
        --skip-tests) SKIP_TESTS=true ;;
        --quiet) QUIET=true ;;
        --no-clean) NO_CLEAN=true ;;
        --verbose|-vv) VERBOSE=true ;;
        --only-build) ONLY_BUILD=true ;;
        --time) SHOW_TIME=true ;;
        --target)
            shift
            TARGET="$1"
            ;;
        --help|-h)
            SHOW_HELP=true
            ;;
        *)
            echo "⚠️  Unknown option: $1"
            SHOW_HELP=true
            ;;
    esac
    shift
done

# Show help and exit if requested
if $SHOW_HELP; then
    show_help
fi

# Start timer if enabled
if $SHOW_TIME; then
    START_TIME=$(date +%s)
fi

# ----------------------------
# Helper: print step header
# ----------------------------
print_step() {
    echo "===================================================="
    echo "Step $1"
    echo "===================================================="
}

# ----------------------------
# Helper: run command with error handling
# ----------------------------
run_step() {
    local step="$1"
    shift
    local cmd=("$@")

    print_step "$step"

    if $QUIET && ! $VERBOSE; then
        if ! "${cmd[@]}" >/dev/null 2>&1; then
            print_unicode "274C"; echo "  Step failed: $step"
            echo "Command: ${cmd[*]}"
            exit 1
        fi
    else
        if ! "${cmd[@]}"; then
            print_unicode "274C"; echo "  Step failed: $step"
            echo "Command: ${cmd[*]}"
            exit 1
        fi
    fi
}

# ----------------------------
# Display configuration summary
# ----------------------------
echo "----------------------------------------------------"
echo " Build configuration summary:"
$RELEASE && echo "   • Mode   : Release" || echo "   • Mode   : Debug"
[[ -n "$TARGET" ]] && echo "   • Target : $TARGET"
$VERBOSE && echo "   • Verbose: Enabled (-vv)"
$ONLY_BUILD && echo "   • Mode   : Build only (--only-build)"
$SKIP_TESTS && echo "   • Tests  : Skipped"
$NO_CLEAN && echo "   • Clean  : Skipped"
$SHOW_TIME && echo "   • Timing : Enabled (--time)"
echo "----------------------------------------------------"
echo

# ----------------------------
# MAIN PIPELINE
# ----------------------------

BUILD_MODE=()
$RELEASE && BUILD_MODE+=(--release)
[[ -n "$TARGET" ]] && BUILD_MODE+=("--target" "$TARGET")
$VERBOSE && BUILD_MODE+=("-vv")

# Step [0]: cargo clean
if ! $NO_CLEAN; then
    print_step "[0/4] $(print_unicode 1F9F9) cargo clean"
    if $QUIET && ! $VERBOSE; then
        cargo clean >/dev/null 2>&1
    else
        cargo clean
    fi
else
    echo "===================================================="
    print_unicode 26A0; echo "  Cargo clean skipped (--no-clean)"
    echo "===================================================="
fi

# Step [1]: cargo build
run_step "[1/4] $(print_unicode 1F3D7) cargo build" cargo build "${BUILD_MODE[@]}"

# Short-circuit if --only-build
if $ONLY_BUILD; then
    echo
    echo "===================================================="
    print_unicode 1F528; echo " Build completed (--only-build mode active)."
    if $SHOW_TIME; then
        END_TIME=$(date +%s)
        ELAPSED=$((END_TIME - START_TIME))
        MIN=$((ELAPSED / 60))
        SEC=$((ELAPSED % 60))
        print_unicode 23F1; echo "  Total build time: ${MIN}m ${SEC}s"
    fi
    echo "===================================================="
    exit 0
fi

# Step [2]: cargo fmt
run_step "[2/4] $(print_unicode 2728) cargo fmt --all -- --check" \
    cargo fmt --all -- --check

# Step [3]: cargo clippy
if $VERBOSE; then
    run_step "[3/4] $(print_unicode 1F50D) cargo clippy (verbose)" \
        cargo clippy --all-targets --all-features -vv -- -D warnings
else
    run_step "[3/4] $(print_unicode 1F50D) cargo clippy" \
        cargo clippy --all-targets --all-features -- -D warnings
fi

# Step [4]: cargo test
if ! $SKIP_TESTS; then
    run_step "[4/4] $(print_unicode 1F9EA) cargo test" \
        cargo test --all "${BUILD_MODE[@]}"
else
    echo "===================================================="
    print_unicode 26A0; echo "  Tests skipped (--skip-tests)"
    echo "===================================================="
fi

# ----------------------------
# Final success message
# ----------------------------
echo
echo "===================================================="
print_unicode 2705; echo " Build OK! All steps completed successfully."

# Show total time if enabled
if $SHOW_TIME; then
    END_TIME=$(date +%s)
    ELAPSED=$((END_TIME - START_TIME))
    MIN=$((ELAPSED / 60))
    SEC=$((ELAPSED % 60))
    print_unicode 23F1; echo "  Total build time: ${MIN}m ${SEC}s"
fi
echo "===================================================="
