#!/bin/bash
# Debian Image Builder Script
# This script demonstrates the complete Debian image building pipeline

set -euo pipefail

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

# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
OUTPUT_DIR="${PROJECT_ROOT}/output"
BUILD_DIR="${PROJECT_ROOT}/build"
MANIFEST_DIR="${BUILD_DIR}/manifests"

# Default values
RELEASE="trixie"
ARCH="amd64"
IMAGE_TYPE="qcow2"
VERBOSE=false
CLEAN=false

# Function to print colored output
print_status() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

print_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

print_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# Function to show usage
show_usage() {
    cat << EOF
Usage: $0 [OPTIONS]

Build a Debian image using the debian-bootc-image-builder pipeline.

OPTIONS:
    -r, --release RELEASE     Debian release (default: trixie)
    -a, --arch ARCH          Architecture (default: amd64)
    -t, --type TYPE          Image type: qcow2, desktop, server, development (default: qcow2)
    -o, --output DIR         Output directory (default: ./output)
    -v, --verbose            Enable verbose output
    -c, --clean              Clean build directory before building
    -h, --help               Show this help message

EXAMPLES:
    $0 --type desktop --release trixie
    $0 --type server --arch amd64 --verbose
    $0 --type development --clean

EOF
}

# Function to parse command line arguments
parse_args() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            -r|--release)
                RELEASE="$2"
                shift 2
                ;;
            -a|--arch)
                ARCH="$2"
                shift 2
                ;;
            -t|--type)
                IMAGE_TYPE="$2"
                shift 2
                ;;
            -o|--output)
                OUTPUT_DIR="$2"
                shift 2
                ;;
            -v|--verbose)
                VERBOSE=true
                shift
                ;;
            -c|--clean)
                CLEAN=true
                shift
                ;;
            -h|--help)
                show_usage
                exit 0
                ;;
            *)
                print_error "Unknown option: $1"
                show_usage
                exit 1
                ;;
        esac
    done
}

# Function to validate inputs
validate_inputs() {
    print_status "Validating inputs..."
    
    # Validate release
    case "$RELEASE" in
        trixie|bookworm|bullseye)
            ;;
        *)
            print_error "Unsupported release: $RELEASE"
            print_error "Supported releases: trixie, bookworm, bullseye"
            exit 1
            ;;
    esac
    
    # Validate architecture
    case "$ARCH" in
        amd64|arm64|i386)
            ;;
        *)
            print_error "Unsupported architecture: $ARCH"
            print_error "Supported architectures: amd64, arm64, i386"
            exit 1
            ;;
    esac
    
    # Validate image type
    case "$IMAGE_TYPE" in
        qcow2|desktop|server|development)
            ;;
        *)
            print_error "Unsupported image type: $IMAGE_TYPE"
            print_error "Supported types: qcow2, desktop, server, development"
            exit 1
            ;;
    esac
    
    print_success "Input validation passed"
}

# Function to setup build environment
setup_build_env() {
    print_status "Setting up build environment..."
    
    # Create directories
    mkdir -p "$OUTPUT_DIR"
    mkdir -p "$BUILD_DIR"
    mkdir -p "$MANIFEST_DIR"
    
    if [[ "$CLEAN" == true ]]; then
        print_status "Cleaning build directory..."
        rm -rf "$BUILD_DIR"/*
        mkdir -p "$MANIFEST_DIR"
    fi
    
    print_success "Build environment ready"
}

# Function to run tests
run_tests() {
    print_status "Running tests..."
    
    cd "$PROJECT_ROOT"
    
    # Run unit tests
    print_status "Running unit tests..."
    if make test-unit > /dev/null 2>&1; then
        print_success "Unit tests passed"
    else
        print_error "Unit tests failed"
        exit 1
    fi
    
    # Run integration tests
    print_status "Running integration tests..."
    if make test-integration > /dev/null 2>&1; then
        print_success "Integration tests passed"
    else
        print_error "Integration tests failed"
        exit 1
    fi
    
    print_success "All tests passed"
}

# Function to generate manifest
generate_manifest() {
    print_status "Generating osbuild manifest for $IMAGE_TYPE image..."
    
    local manifest_file="$MANIFEST_DIR/debian-${RELEASE}-${IMAGE_TYPE}.json"
    
    # Create a simple manifest for demonstration
    cat > "$manifest_file" << EOF
{
  "version": "2",
  "stages": [
    {
      "type": "org.osbuild.debian-filesystem",
      "options": {
        "rootfs_type": "ext4",
        "ostree_integration": true,
        "home_symlink": true
      }
    },
    {
      "type": "org.osbuild.apt",
      "options": {
        "packages": [
          "linux-image-${ARCH}",
          "systemd",
          "initramfs-tools",
          "grub-efi-${ARCH}",
          "ostree"
        ],
        "release": "${RELEASE}",
        "arch": "${ARCH}",
        "repos": [
          {
            "name": "debian",
            "url": "http://deb.debian.org/debian",
            "suite": "${RELEASE}",
            "components": ["main", "contrib", "non-free"]
          }
        ]
      }
    },
    {
      "type": "org.osbuild.debian-kernel",
      "options": {
        "kernel_package": "linux-image-${ARCH}",
        "initramfs_tools": true,
        "ostree_integration": true,
        "modules_autoload": true
      }
    },
    {
      "type": "org.osbuild.debian-grub",
      "options": {
        "ostree_integration": true,
        "uefi": true,
        "secure_boot": false,
        "timeout": 5,
        "default_entry": 0
      }
    }
EOF
    
    # Add image-specific stages
    case "$IMAGE_TYPE" in
        desktop)
            cat >> "$manifest_file" << EOF
    ,
    {
      "type": "org.osbuild.debian-desktop-config",
      "options": {
        "desktop_environment": "kde",
        "display_manager": "sddm",
        "user_sessions": true,
        "applications": true,
        "theme": "breeze"
      }
    }
EOF
            ;;
        server)
            cat >> "$manifest_file" << EOF
    ,
    {
      "type": "org.osbuild.debian-server-config",
      "options": {
        "security_hardening": true,
        "firewall": "ufw",
        "ssh": {
          "port": 22,
          "root_login": false,
          "key_auth_only": false
        }
      }
    }
EOF
            ;;
        development)
            cat >> "$manifest_file" << EOF
    ,
    {
      "type": "org.osbuild.debian-desktop-config",
      "options": {
        "desktop_environment": "kde",
        "display_manager": "sddm",
        "user_sessions": true,
        "applications": true,
        "theme": "breeze"
      }
    },
    {
      "type": "org.osbuild.debian-development-config",
      "options": {
        "development_tools": true,
        "container_runtime": "docker",
        "dev_user": "debian"
      }
    }
EOF
            ;;
    esac
    
    # Close the manifest
    cat >> "$manifest_file" << EOF
  ],
  "assembler": {
    "type": "org.osbuild.qcow2",
    "options": {
      "filename": "debian-${RELEASE}-${IMAGE_TYPE}.qcow2"
    }
  }
}
EOF
    
    print_success "Manifest generated: $manifest_file"
    
    if [[ "$VERBOSE" == true ]]; then
        print_status "Manifest contents:"
        cat "$manifest_file" | jq '.' 2>/dev/null || cat "$manifest_file"
    fi
}

# Function to simulate osbuild execution
simulate_osbuild() {
    print_status "Simulating osbuild execution..."
    
    local manifest_file="$MANIFEST_DIR/debian-${RELEASE}-${IMAGE_TYPE}.json"
    local output_file="$OUTPUT_DIR/debian-${RELEASE}-${IMAGE_TYPE}.qcow2"
    
    # Create a mock output file
    print_status "Creating mock QCOW2 image..."
    dd if=/dev/zero of="$output_file" bs=1M count=100 2>/dev/null || {
        # Fallback if dd fails
        print_warning "dd failed, creating empty file"
        touch "$output_file"
    }
    
    print_success "Mock image created: $output_file"
    
    # Show image info
    if command -v qemu-img >/dev/null 2>&1; then
        print_status "Image information:"
        qemu-img info "$output_file" 2>/dev/null || print_warning "qemu-img not available"
    fi
}

# Function to run validation
run_validation() {
    print_status "Running validation..."
    
    local output_file="$OUTPUT_DIR/debian-${RELEASE}-${IMAGE_TYPE}.qcow2"
    
    # Check if output file exists
    if [[ ! -f "$output_file" ]]; then
        print_error "Output file not found: $output_file"
        exit 1
    fi
    
    # Check file size
    local file_size=$(stat -c%s "$output_file" 2>/dev/null || stat -f%z "$output_file" 2>/dev/null || echo "0")
    if [[ "$file_size" -gt 0 ]]; then
        print_success "Output file size: $file_size bytes"
    else
        print_warning "Output file is empty (this is expected for mock builds)"
    fi
    
    print_success "Validation completed"
}

# Function to show build summary
show_summary() {
    print_status "Build Summary"
    echo "=================="
    echo "Release: $RELEASE"
    echo "Architecture: $ARCH"
    echo "Image Type: $IMAGE_TYPE"
    echo "Output Directory: $OUTPUT_DIR"
    echo "Build Directory: $BUILD_DIR"
    echo ""
    echo "Generated Files:"
    echo "- Manifest: $MANIFEST_DIR/debian-${RELEASE}-${IMAGE_TYPE}.json"
    echo "- Image: $OUTPUT_DIR/debian-${RELEASE}-${IMAGE_TYPE}.qcow2"
    echo ""
    print_success "Build completed successfully!"
}

# Main function
main() {
    print_status "Starting Debian image build..."
    print_status "Project root: $PROJECT_ROOT"
    
    # Parse arguments
    parse_args "$@"
    
    # Validate inputs
    validate_inputs
    
    # Setup build environment
    setup_build_env
    
    # Run tests
    run_tests
    
    # Generate manifest
    generate_manifest
    
    # Simulate osbuild execution
    simulate_osbuild
    
    # Run validation
    run_validation
    
    # Show summary
    show_summary
}

# Run main function with all arguments
main "$@"
