#!/bin/bash

# Base Image Pre-Pull Script for Bakery-IA
# This script pre-pulls all required base images to reduce Docker Hub usage
# Supports both local development and production environments with Gitea registry
# Run this script before building services to cache base images locally

set -e

# Function to display usage
usage() {
    echo "Usage: $0 [options]"
    echo ""
    echo "Options:"
    echo "  -e, --environment ENV    Set environment (dev|prod) - default: dev"
    echo "  -r, --registry REG       Custom registry URL - default: localhost:5000 (dev) or gitea registry (prod)"
    echo "  --skip-auth              Skip Docker Hub authentication"
    echo "  --push-images            Push images to registry (default: true for dev, false for prod)"
    echo "  --no-push-images         Don't push images to registry"
    echo "  -h, --help               Show this help message"
    echo ""
    echo "Examples:"
    echo "  $0                                      # Run in dev mode with local registry"
    echo "  $0 -e prod                              # Run in production mode with Gitea registry"
    echo "  $0 -e prod -r registry.example.com:5000 # Run in production with custom registry"
    echo "  $0 --skip-auth                          # Skip Docker Hub auth (for air-gapped envs)"
    exit 1
}

# Parse command line arguments
ENVIRONMENT="dev"
REGISTRY=""
SKIP_AUTH=false
PUSH_IMAGES=""
while [[ $# -gt 0 ]]; do
    case $1 in
        -e|--environment)
            ENVIRONMENT="$2"
            shift 2
            ;;
        -r|--registry)
            REGISTRY="$2"
            shift 2
            ;;
        --skip-auth)
            SKIP_AUTH=true
            shift
            ;;
        --push-images)
            PUSH_IMAGES=true
            shift
            ;;
        --no-push-images)
            PUSH_IMAGES=false
            shift
            ;;
        -h|--help)
            usage
            ;;
        *)
            echo "Unknown option: $1"
            usage
            ;;
    esac
done

# Function to check if required tools are available
check_required_tools() {
    local missing_tools=()

    # Check for required tools
    for tool in docker curl jq kubectl; do
        if ! command -v "$tool" &> /dev/null; then
            missing_tools+=("$tool")
        fi
    done

    if [ ${#missing_tools[@]} -gt 0 ]; then
        echo "Error: Missing required tools: ${missing_tools[*]}"
        echo "Please install them before running this script."
        echo ""
        echo "On macOS (with Homebrew):"
        echo "  brew install docker curl jq kubectl"
        echo ""
        echo "On Ubuntu/Debian:"
        echo "  sudo apt-get install docker.io curl jq kubectl"
        echo ""
        echo "On CentOS/RHEL:"
        echo "  sudo yum install docker curl jq kubectl"
        exit 1
    fi
}

# Check for required tools
check_required_tools

echo "=========================================="
echo "Bakery-IA Base Image Pre-Pull Script"
echo "Environment: $ENVIRONMENT"
echo "=========================================="
echo ""

# Set defaults based on environment
if [ "$ENVIRONMENT" = "prod" ]; then
    # Production environment - use Gitea registry
    if [ -z "$REGISTRY" ]; then
        # Try to get Gitea registry from Kubernetes
        if kubectl get secret gitea-registry-secret -n bakery-ia &>/dev/null; then
            # Extract registry URL from the secret
            REGISTRY_JSON=$(kubectl get secret gitea-registry-secret -n bakery-ia -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d)
            REGISTRY=$(echo "$REGISTRY_JSON" | jq -r '.auths | keys[]' | head -n 1)
            echo "Detected Gitea registry: $REGISTRY"
        else
            echo "Error: Could not detect Gitea registry automatically"
            echo "Please specify the registry with -r/--registry option"
            echo "Example: $0 -e prod -r registry.bakewise.ai"
            exit 1
        fi
    fi

    # Default to not pushing images in production - they should be built by CI/CD
    if [ -z "$PUSH_IMAGES" ]; then
        PUSH_IMAGES=false
    fi
elif [ "$ENVIRONMENT" = "dev" ]; then
    # Development environment - use local registry
    if [ -z "$REGISTRY" ]; then
        REGISTRY="localhost:5000"
    fi

    # Default to pushing images in dev
    if [ -z "$PUSH_IMAGES" ]; then
        PUSH_IMAGES=true
    fi
else
    echo "Error: Invalid environment. Use 'dev' or 'prod'"
    exit 1
fi

echo "Registry configuration:"
echo "  Environment: $ENVIRONMENT"
echo "  Registry: $REGISTRY"
echo "  Push Images: $PUSH_IMAGES"
echo ""

# Docker Hub credentials (use environment variables or defaults)
DOCKER_USERNAME="${DOCKER_HUB_USERNAME:-uals}"
DOCKER_PASSWORD="${DOCKER_HUB_PASSWORD:-dckr_pat_zzEY5Q58x1S0puraIoKEtbpue3A}"

# Authenticate with Docker Hub if not skipping auth
if [ "$SKIP_AUTH" = false ]; then
    echo "Authenticating with Docker Hub..."
    if ! echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin; then
        echo "⚠ Warning: Docker Hub authentication failed. Continuing anyway..."
    else
        echo "✓ Authentication successful"
    fi
else
    echo "Skipping Docker Hub authentication (--skip-auth flag set)"
fi
echo ""

# Define all base images used in the project
# These are the base images needed for the services
BASE_IMAGES=(
    # Service base images (Python microservices)
    "python:3.11-slim"
    # Frontend base images (Node.js build + Nginx runtime)
    "node:18-alpine"
    "nginx:1.25-alpine"
    # Database images
    "postgres:17-alpine"
    "redis:7.4-alpine"
    "rabbitmq:4.1-management-alpine"
    # Utility images
    "busybox:1.36"
    "curlimages/curl:latest"
    "bitnami/kubectl:latest"
    # Alpine variants
    "alpine:3.18"
    "alpine:3.19"
    "alpine/git:2.43.0"
    # CI/CD images
    "gcr.io/kaniko-project/executor:v1.23.0"
    "gcr.io/go-containerregistry/crane:latest"
    "registry.k8s.io/kustomize/kustomize:v5.3.0"
    # Storage images
    "minio/minio:RELEASE.2024-11-07T00-52-20Z"
    "minio/mc:RELEASE.2024-11-17T19-35-25Z"
    # Geocoding
    "mediagis/nominatim:4.4"
    # Mail server (Mailu - from GHCR)
    "ghcr.io/mailu/nginx:2024.06"
    "ghcr.io/mailu/admin:2024.06"
    "ghcr.io/mailu/postfix:2024.06"
    "ghcr.io/mailu/dovecot:2024.06"
    "ghcr.io/mailu/rspamd:2024.06"
)

# If using registry, verify it's running
if [ "$PUSH_IMAGES" = true ]; then
    echo "Checking registry at $REGISTRY..."
    if curl -s http://$REGISTRY/v2/ >/dev/null 2>&1; then
        echo "✓ Registry is accessible"
    elif curl -s https://$REGISTRY/v2/ >/dev/null 2>&1; then
        echo "✓ Registry is accessible (HTTPS)"
        # Update registry to use HTTPS if needed
        REGISTRY="https://$REGISTRY"
    else
        echo "⚠ Registry is not accessible at $REGISTRY"
        echo "Will only pull images locally (no registry push)"
        PUSH_IMAGES=false
    fi
fi

echo ""
echo "Base images to pre-pull:"
echo "----------------------------------------"
for image in "${BASE_IMAGES[@]}"; do
    echo "  - $image"
done
echo ""

echo "Starting pre-pull process..."
echo "----------------------------------------"

# Track success/failure
FAILED_IMAGES=()
SUCCESS_COUNT=0

# Pull each base image
for image in "${BASE_IMAGES[@]}"; do
    echo "Pulling: $image"

    # Pull the image
    if ! docker pull "$image"; then
        echo "  ⚠ Failed to pull $image"
        FAILED_IMAGES+=("$image")
        continue
    fi

    # Tag for registry if enabled
    if [ "$PUSH_IMAGES" = true ]; then
        # Extract registry host and image name
        if [[ "$REGISTRY" == https://* ]]; then
            REGISTRY_HOST=${REGISTRY#https://}
        else
            REGISTRY_HOST=$REGISTRY
        fi

        # Format for registry: replace /, :, -, and . with _
        local_repo="$(echo $image | sed 's|/|_|g' | sed 's|:|_|g' | sed 's|-|_|g' | sed 's|\.|_|g' | tr '[:upper:]' '[:lower:]')"
        registry_image="$REGISTRY_HOST/${local_repo}:latest"

        docker tag "$image" "$registry_image"
        echo "  Tagged as: $registry_image"

        # Push to registry
        if docker push "$registry_image"; then
            echo "  ✓ Pushed to registry"
        else
            echo "  ⚠ Failed to push to registry (image still available locally)"
        fi
    fi

    echo "  ✓ Successfully pulled $image"
    SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
    echo ""
done

echo "=========================================="
echo "Base Image Pre-Pull Complete!"
echo "=========================================="
echo ""
echo "Summary:"
echo "  - Total images: ${#BASE_IMAGES[@]}"
echo "  - Successfully pulled: $SUCCESS_COUNT"
if [ ${#FAILED_IMAGES[@]} -gt 0 ]; then
    echo "  - Failed: ${#FAILED_IMAGES[@]}"
    echo "  - Failed images: ${FAILED_IMAGES[*]}"
fi
echo "  - Environment: $ENVIRONMENT"
if [ "$PUSH_IMAGES" = true ]; then
    echo "  - Registry: $REGISTRY"
else
    echo "  - Registry: None (local Docker only)"
fi
echo ""

# Exit with error if any images failed
if [ ${#FAILED_IMAGES[@]} -gt 0 ]; then
    echo "⚠ Some images failed to pull. This may be due to Docker Hub rate limits."
    echo "Please try again later or configure Docker Hub credentials."
    exit 1
fi

echo "✓ All images pulled successfully!"

if [ "$ENVIRONMENT" = "prod" ] && [ "$PUSH_IMAGES" = false ]; then
    echo ""
    echo "💡 Note: In production mode, images are not pushed to registry."
    echo "   Images should be built and pushed by your CI/CD pipeline."
    echo "   Make sure your CI/CD pipeline has built and pushed the required images."
    echo ""
    echo "💡 To build and push service images to Gitea registry:"
    echo "   1. Ensure your CI/CD pipeline is running (Tekton)"
    echo "   2. Push a commit to trigger the pipeline: git commit --allow-empty -m 'Trigger build'"
    echo "   3. Or manually trigger a pipeline run"
    echo ""
    echo "💡 Check pipeline status:"
    echo "   kubectl get pipelineruns -n tekton-pipelines"
    echo "   kubectl get pods -n tekton-pipelines"
fi
