#!/usr/bin/env bash
# Copyright 2024 RustFS Team
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -e

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

# Default values
REGISTRY="ghcr.io"
NAMESPACE="rustfs"
PLATFORMS="linux/amd64,linux/arm64"
PUSH=false
NO_CACHE=false
RELEASE=""
CHANNEL="release"

# Print usage
usage() {
    echo "Usage: $0 [OPTIONS]"
    echo ""
    echo "Options:"
    echo "  -r, --registry REGISTRY    Docker registry (default: ghcr.io)"
    echo "  -n, --namespace NAMESPACE  Image namespace (default: rustfs)"
    echo "  -p, --platforms PLATFORMS  Target platforms (default: linux/amd64,linux/arm64)"
    echo "  --push                     Push images to registry"
    echo "  --no-cache                 Disable build cache"
    echo "  --release VERSION          Specify release version (default: auto-detect from git)"
    echo "  --channel CHANNEL          Download channel: release or dev (default: release)"
    echo "  -h, --help                 Show this help message"
    echo ""
    echo "Examples:"
    echo "  $0                         # Build all variants locally"
    echo "  $0 --push                  # Build and push all variants"
    echo "  $0 --push --no-cache       # Build and push with no cache"
    echo "  $0 --release v1.0.0        # Build specific release version"
    echo "  $0 --channel dev           # Build with dev channel binaries"
    echo "  $0 --release latest --channel dev  # Build latest dev build"
}

# Print colored message
print_message() {
    local color=$1
    local message=$2
    echo -e "${color}${message}${NC}"
}

# Check if Docker buildx is available
check_buildx() {
    if ! docker buildx version >/dev/null 2>&1; then
        print_message $RED "❌ Docker buildx is not available. Please install Docker with buildx support."
        exit 1
    fi
}

# Setup buildx builder
setup_builder() {
    local builder_name="rustfs-builder"

    print_message $BLUE "🔧 Setting up Docker buildx builder..."

    # Check if builder exists
    if docker buildx ls | grep -q "$builder_name"; then
        print_message $YELLOW "⚠️  Builder '$builder_name' already exists, using existing one"
        docker buildx use "$builder_name"
    else
        # Create new builder
        docker buildx create --name "$builder_name" --driver docker-container --bootstrap
        docker buildx use "$builder_name"
        print_message $GREEN "✅ Created and activated builder '$builder_name'"
    fi

    # Inspect builder
    docker buildx inspect --bootstrap
}

# Get version from git
get_version() {
    if [ -n "$RELEASE" ]; then
        echo "$RELEASE"
        return
    fi

    # Try to get version from git tag
    if git describe --abbrev=0 --tags >/dev/null 2>&1; then
        git describe --abbrev=0 --tags
    else
        # Fallback to commit hash
        git rev-parse --short HEAD
    fi
}

# Build and push images
build_and_push() {
    local version=$(get_version)
    local image_base="${REGISTRY}/${NAMESPACE}/rustfs"
    local build_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
    local vcs_ref=$(git rev-parse --short HEAD)

    print_message $BLUE "🚀 Building RustFS Docker images..."
    print_message $YELLOW "   Version: $version"
    print_message $YELLOW "   Registry: $REGISTRY"
    print_message $YELLOW "   Namespace: $NAMESPACE"
    print_message $YELLOW "   Platforms: $PLATFORMS"
    print_message $YELLOW "   Channel: $CHANNEL"
    print_message $YELLOW "   Build Date: $build_date"
    print_message $YELLOW "   VCS Ref: $vcs_ref"
    print_message $YELLOW "   Push: $PUSH"
    print_message $YELLOW "   No Cache: $NO_CACHE"
    echo ""

    # Build command base
    local build_cmd="docker buildx build"
    build_cmd+=" --platform $PLATFORMS"
    build_cmd+=" --build-arg RELEASE=$version"
    build_cmd+=" --build-arg CHANNEL=$CHANNEL"
    build_cmd+=" --build-arg BUILD_DATE=$build_date"
    build_cmd+=" --build-arg VCS_REF=$vcs_ref"

    if [ "$NO_CACHE" = true ]; then
        build_cmd+=" --no-cache"
    fi

    if [ "$PUSH" = true ]; then
        build_cmd+=" --push"
    else
        build_cmd+=" --load"
    fi

    # Build latest variant
    print_message $BLUE "🏗️  Building latest variant..."
    local latest_cmd="$build_cmd"

    # Add channel-specific tags
    if [ "$CHANNEL" = "dev" ]; then
        latest_cmd+=" -t ${image_base}:dev-latest"
    else
        latest_cmd+=" -t ${image_base}:latest"
    fi

    latest_cmd+=" --build-arg RELEASE=latest"
    latest_cmd+=" -f Dockerfile ."

    print_message $BLUE "📦 Executing: $latest_cmd"
    if eval $latest_cmd; then
        print_message $GREEN "✅ Successfully built latest variant"
    else
        print_message $RED "❌ Failed to build latest variant"
        print_message $YELLOW "💡 Note: Make sure rustfs binaries are available at:"
        print_message $YELLOW "   https://github.com/rustfs/rustfs/releases"
        exit 1
    fi

    # Prune build cache
    docker buildx prune -f

    # Build release variant (only if not latest)
    if [ "$RELEASE" != "latest" ]; then
        print_message $BLUE "🏗️  Building release variant..."
        local release_cmd="$build_cmd"
        release_cmd+=" -t ${image_base}:${version}"

        # Add channel-specific tags
        if [ "$CHANNEL" = "dev" ]; then
            release_cmd+=" -t ${image_base}:dev-${version}"
        else
            release_cmd+=" -t ${image_base}:release"
        fi

        release_cmd+=" --build-arg RELEASE=${version}"
        release_cmd+=" -f Dockerfile ."

        print_message $BLUE "📦 Executing: $release_cmd"
        if eval $release_cmd; then
            print_message $GREEN "✅ Successfully built release variant"
        else
            print_message $RED "❌ Failed to build release variant"
            print_message $YELLOW "💡 Note: Make sure rustfs binaries are available at:"
            print_message $YELLOW "   https://github.com/rustfs/rustfs/releases"
            exit 1
        fi
    else
        print_message $BLUE "⏭️  Skipping release variant (already built as latest)"
    fi

    # Final cleanup
    docker buildx prune -f
}

# Parse command line arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        -r|--registry)
            REGISTRY="$2"
            shift 2
            ;;
        -n|--namespace)
            NAMESPACE="$2"
            shift 2
            ;;
        -p|--platforms)
            PLATFORMS="$2"
            shift 2
            ;;
        --push)
            PUSH=true
            shift
            ;;
        --no-cache)
            NO_CACHE=true
            shift
            ;;
        --release)
            RELEASE="$2"
            shift 2
            ;;
        --channel)
            CHANNEL="$2"
            if [ "$CHANNEL" != "release" ] && [ "$CHANNEL" != "dev" ]; then
                print_message $RED "❌ Invalid channel: $CHANNEL. Must be 'release' or 'dev'"
                exit 1
            fi
            shift 2
            ;;
        -h|--help)
            usage
            exit 0
            ;;
        *)
            print_message $RED "❌ Unknown option: $1"
            usage
            exit 1
            ;;
    esac
done

# Main execution
main() {
    print_message $BLUE "🐳 RustFS Docker Buildx Build Script"
    print_message $YELLOW "📋 Build Strategy: Uses pre-built binaries from GitHub Releases"
    print_message $YELLOW "🚀 Production images only - optimized for distribution"
    echo ""

    # Check prerequisites
    check_buildx

    # Setup builder
    setup_builder
    echo ""

    # Start build process
    build_and_push

    print_message $GREEN "🎉 Build process completed successfully!"

    # Show built images if not pushing
    if [ "$PUSH" = false ]; then
        print_message $BLUE "📋 Built images:"
        docker images | grep "${NAMESPACE}/rustfs" | head -10
    fi
}

# Run main function
main
