#!/bin/bash

# Configuration Management Script for Rustelo
# Provides commands to manage, validate, and deploy configurations
# Usage: ./manage-config.sh [command] [options]

set -e

# Script configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_DIR="$(dirname "$SCRIPT_DIR")"
PROJECT_ROOT="$(dirname "$CONFIG_DIR")"
BACKUP_DIR="$CONFIG_DIR/backups"
ENVIRONMENTS=("dev" "prod" "example")

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

# Logging functions
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

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

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

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

log_debug() {
    if [ "${DEBUG:-0}" = "1" ]; then
        echo -e "${PURPLE}[DEBUG]${NC} $1"
    fi
}

# Show help
show_help() {
    cat << EOF
Configuration Management Script for Rustelo

USAGE:
    $0 [COMMAND] [OPTIONS]

COMMANDS:
    build ENV [OUTPUT]      Build configuration for environment
    validate ENV            Validate configuration for environment
    list-features           List available features
    list-environments       List available environments
    backup ENV              Backup existing configuration
    restore BACKUP_FILE     Restore configuration from backup
    diff ENV1 ENV2          Compare configurations between environments
    template FEATURE        Create new feature template
    clean                   Clean generated configurations
    status                  Show configuration status
    help                    Show this help message

ENVIRONMENTS:
    dev                     Development environment
    prod                    Production environment
    example                 Example/template environment

OPTIONS:
    --debug                 Enable debug output
    --dry-run               Show what would be done without executing
    --force                 Force operation without confirmation
    --quiet                 Suppress non-error output
    --backup-dir DIR        Use custom backup directory

EXAMPLES:
    $0 build dev                    # Build dev configuration
    $0 build prod config.prod.toml  # Build prod config with custom name
    $0 validate dev                 # Validate dev configuration
    $0 diff dev prod               # Compare dev and prod configurations
    $0 backup prod                 # Backup prod configuration
    $0 template auth               # Create new auth feature template
    $0 clean                       # Clean all generated configs
    $0 status                      # Show configuration status

ENVIRONMENT VARIABLES:
    CONFIG_DEBUG=1          Enable debug output
    CONFIG_QUIET=1          Suppress non-error output
    CONFIG_FORCE=1          Force operations without confirmation
    CONFIG_BACKUP_DIR=path  Custom backup directory

EOF
}

# Parse command line arguments
parse_args() {
    COMMAND=""
    ENV=""
    OUTPUT=""
    DEBUG="${DEBUG:-0}"
    DRY_RUN="${DRY_RUN:-0}"
    FORCE="${FORCE:-0}"
    QUIET="${QUIET:-0}"
    BACKUP_DIR_OVERRIDE=""

    while [[ $# -gt 0 ]]; do
        case $1 in
            --debug)
                DEBUG=1
                shift
                ;;
            --dry-run)
                DRY_RUN=1
                shift
                ;;
            --force)
                FORCE=1
                shift
                ;;
            --quiet)
                QUIET=1
                shift
                ;;
            --backup-dir)
                BACKUP_DIR_OVERRIDE="$2"
                shift 2
                ;;
            build|validate|backup|restore|diff|template|clean|status|list-features|list-environments|help)
                COMMAND="$1"
                shift
                ;;
            *)
                if [ -z "$ENV" ]; then
                    ENV="$1"
                elif [ -z "$OUTPUT" ]; then
                    OUTPUT="$1"
                else
                    log_error "Unknown argument: $1"
                    exit 1
                fi
                shift
                ;;
        esac
    done

    # Override backup directory if specified
    if [ -n "$BACKUP_DIR_OVERRIDE" ]; then
        BACKUP_DIR="$BACKUP_DIR_OVERRIDE"
    fi

    # Apply environment variables
    [ "${CONFIG_DEBUG:-0}" = "1" ] && DEBUG=1
    [ "${CONFIG_QUIET:-0}" = "1" ] && QUIET=1
    [ "${CONFIG_FORCE:-0}" = "1" ] && FORCE=1
    [ -n "${CONFIG_BACKUP_DIR:-}" ] && BACKUP_DIR="$CONFIG_BACKUP_DIR"
}

# Check if environment is valid
validate_environment() {
    local env="$1"
    for valid_env in "${ENVIRONMENTS[@]}"; do
        if [ "$env" = "$valid_env" ]; then
            return 0
        fi
    done
    log_error "Invalid environment: $env"
    log_error "Valid environments: ${ENVIRONMENTS[*]}"
    return 1
}

# Create backup directory if it doesn't exist
ensure_backup_dir() {
    if [ ! -d "$BACKUP_DIR" ]; then
        mkdir -p "$BACKUP_DIR"
        log_debug "Created backup directory: $BACKUP_DIR"
    fi
}

# Build configuration
cmd_build() {
    local env="$1"
    local output="${2:-config.toml}"

    if [ -z "$env" ]; then
        log_error "Environment required for build command"
        return 1
    fi

    if ! validate_environment "$env"; then
        return 1
    fi

    log_info "Building configuration for environment: $env"

    # Use Python script if available, otherwise use bash script
    if [ "$DRY_RUN" = "1" ]; then
        log_info "Would build configuration using shell script"
        return 0
    fi
    "$SCRIPT_DIR/build-config.sh" "$env" "$output"
}

# Validate configuration
cmd_validate() {
    local env="$1"

    if [ -z "$env" ]; then
        log_error "Environment required for validate command"
        return 1
    fi

    if ! validate_environment "$env"; then
        return 1
    fi

    log_info "Validating configuration for environment: $env"

    if [ "$DRY_RUN" = "1" ]; then
        log_info "Would validate configuration"
        return 0
    fi

    # Use Python script if available
    CONFIG_VALIDATE_ONLY=1 "$SCRIPT_DIR/build-config.sh" "$env"
}

# List available features
cmd_list_features() {
    log_info "Available features:"

    if [ -d "$CONFIG_DIR/features" ]; then
        for feature_dir in "$CONFIG_DIR/features"/*; do
            if [ -d "$feature_dir" ]; then
                local feature_name=$(basename "$feature_dir")
                log_info "  - $feature_name"

                # Show available environments for this feature
                local envs=()
                for env in "${ENVIRONMENTS[@]}"; do
                    if [ -f "$feature_dir/$env.toml" ]; then
                        envs+=("$env")
                    fi
                done

                if [ ${#envs[@]} -gt 0 ]; then
                    log_info "    Environments: ${envs[*]}"
                fi
            fi
        done
    else
        log_error "Features directory not found: $CONFIG_DIR/features"
        return 1
    fi
}

# List available environments
cmd_list_environments() {
    log_info "Available environments:"

    for env in "${ENVIRONMENTS[@]}"; do
        log_info "  - $env"

        # Check if base configuration exists
        if [ -f "$CONFIG_DIR/base/$env.toml" ]; then
            log_info "    Base config: ✓"
        else
            log_info "    Base config: ✗"
        fi

        # Count available features
        local feature_count=0
        if [ -d "$CONFIG_DIR/features" ]; then
            for feature_dir in "$CONFIG_DIR/features"/*; do
                if [ -d "$feature_dir" ] && [ -f "$feature_dir/$env.toml" ]; then
                    ((feature_count++))
                fi
            done
        fi
        log_info "    Available features: $feature_count"
    done
}

# Compare configurations between environments
cmd_diff() {
    local env1="$1"
    local env2="$2"

    if [ -z "$env1" ] || [ -z "$env2" ]; then
        log_error "Two environments required for diff command"
        return 1
    fi

    if ! validate_environment "$env1" || ! validate_environment "$env2"; then
        return 1
    fi

    log_info "Comparing configurations: $env1 vs $env2"

    # Create temporary files
    local temp1=$(mktemp)
    local temp2=$(mktemp)
    trap "rm -f $temp1 $temp2" EXIT

    # Build configurations
    if ! cmd_build "$env1" "$temp1"; then
        log_error "Failed to build configuration for $env1"
        return 1
    fi

    if ! cmd_build "$env2" "$temp2"; then
        log_error "Failed to build configuration for $env2"
        return 1
    fi

    # Compare configurations
    if command -v diff &> /dev/null; then
        diff -u "$temp1" "$temp2" || true
    else
        log_warning "diff command not available, using basic comparison"
        if cmp -s "$temp1" "$temp2"; then
            log_info "Configurations are identical"
        else
            log_info "Configurations differ"
        fi
    fi
}

# Create backup of configuration
cmd_backup() {
    local env="$1"
    local config_file="${2:-config.toml}"

    if [ -z "$env" ]; then
        log_error "Environment required for backup command"
        return 1
    fi

    if ! validate_environment "$env"; then
        return 1
    fi

    ensure_backup_dir

    local timestamp=$(date +%Y%m%d_%H%M%S)
    local backup_file="$BACKUP_DIR/config_${env}_${timestamp}.toml"

    if [ -f "$config_file" ]; then
        if [ "$DRY_RUN" = "1" ]; then
            log_info "Would backup $config_file to $backup_file"
            return 0
        fi

        cp "$config_file" "$backup_file"
        log_success "Configuration backed up to: $backup_file"
    else
        log_error "Configuration file not found: $config_file"
        return 1
    fi
}

# Restore configuration from backup
cmd_restore() {
    local backup_file="$1"
    local output_file="${2:-config.toml}"

    if [ -z "$backup_file" ]; then
        log_error "Backup file required for restore command"
        return 1
    fi

    if [ ! -f "$backup_file" ]; then
        log_error "Backup file not found: $backup_file"
        return 1
    fi

    if [ "$DRY_RUN" = "1" ]; then
        log_info "Would restore $backup_file to $output_file"
        return 0
    fi

    # Create backup of current file if it exists
    if [ -f "$output_file" ]; then
        local timestamp=$(date +%Y%m%d_%H%M%S)
        local current_backup="$BACKUP_DIR/config_current_${timestamp}.toml"
        ensure_backup_dir
        cp "$output_file" "$current_backup"
        log_info "Current configuration backed up to: $current_backup"
    fi

    cp "$backup_file" "$output_file"
    log_success "Configuration restored from: $backup_file"
}

# Create new feature template
cmd_template() {
    local feature_name="$1"

    if [ -z "$feature_name" ]; then
        log_error "Feature name required for template command"
        return 1
    fi

    local feature_dir="$CONFIG_DIR/features/$feature_name"

    if [ -d "$feature_dir" ]; then
        if [ "$FORCE" != "1" ]; then
            log_error "Feature directory already exists: $feature_dir"
            log_error "Use --force to overwrite"
            return 1
        fi
    fi

    if [ "$DRY_RUN" = "1" ]; then
        log_info "Would create feature template: $feature_name"
        return 0
    fi

    # Create feature directory
    mkdir -p "$feature_dir"

    # Create template files for each environment
    for env in "${ENVIRONMENTS[@]}"; do
        local template_file="$feature_dir/$env.toml"
        cat > "$template_file" << EOF
# $feature_name Feature Configuration - $(echo $env | sed 's/./\U&/') Environment
# Settings for the $feature_name feature

[features]
$feature_name = true

[$feature_name]
enabled = true
# Add your feature-specific settings here

# Example configuration options:
# option1 = "value1"
# option2 = 42
# option3 = true
EOF
        log_info "Created template file: $template_file"
    done

    # Create README for the feature
    cat > "$feature_dir/README.md" << EOF
# $feature_name Feature

Description of the $feature_name feature.

## Configuration Options

### Environment-Specific Settings

#### Development (\`dev.toml\`)
- Optimized for development and debugging
- Relaxed security settings
- Verbose logging enabled

#### Production (\`prod.toml\`)
- Optimized for production performance
- Strict security settings
- Minimal logging

#### Example (\`example.toml\`)
- Complete documentation of all options
- Best practice configurations
- Commented examples

## Usage

Enable this feature by setting:

\`\`\`toml
[features]
$feature_name = true
\`\`\`

## Dependencies

List any features that this feature depends on.

## Security Considerations

Document any security implications of this feature.
EOF

    log_success "Feature template created: $feature_name"
}

# Clean generated configurations
cmd_clean() {
    log_info "Cleaning generated configurations..."

    if [ "$DRY_RUN" = "1" ]; then
        log_info "Would clean generated configuration files"
        return 0
    fi

    local cleaned_count=0

    # Remove generated config files
    for config_file in config.toml config.*.toml; do
        if [ -f "$config_file" ]; then
            rm "$config_file"
            log_info "Removed: $config_file"
            ((cleaned_count++))
        fi
    done

    # Remove temporary files
    for temp_file in /tmp/config_*.toml /tmp/rustelo_config_*.toml; do
        if [ -f "$temp_file" ]; then
            rm "$temp_file"
            log_info "Removed: $temp_file"
            ((cleaned_count++))
        fi
    done

    log_success "Cleaned $cleaned_count files"
}

# Show configuration status
cmd_status() {
    log_info "Configuration system status:"

    # Check directories
    log_info "Directories:"
    for dir in base features scripts; do
        if [ -d "$CONFIG_DIR/$dir" ]; then
            log_info "  $dir: ✓"
        else
            log_info "  $dir: ✗"
        fi
    done

    # Check base configurations
    log_info "Base configurations:"
    for env in "${ENVIRONMENTS[@]}"; do
        if [ -f "$CONFIG_DIR/base/$env.toml" ]; then
            log_info "  $env: ✓"
        else
            log_info "  $env: ✗"
        fi
    done

    # Check features
    log_info "Features:"
    if [ -d "$CONFIG_DIR/features" ]; then
        for feature_dir in "$CONFIG_DIR/features"/*; do
            if [ -d "$feature_dir" ]; then
                local feature_name=$(basename "$feature_dir")
                local env_count=0
                for env in "${ENVIRONMENTS[@]}"; do
                    if [ -f "$feature_dir/$env.toml" ]; then
                        ((env_count++))
                    fi
                done
                log_info "  $feature_name: $env_count/${#ENVIRONMENTS[@]} environments"
            fi
        done
    fi

    # Check scripts
    log_info "Scripts:"
    for script in build-config.sh; do
        if [ -f "$SCRIPT_DIR/$script" ]; then
            log_info "  $script: ✓"
        else
            log_error "  $script: ✗"
        fi
    done

    # Check tools
    log_info "Tools:"
    if command -v python3 &> /dev/null; then
        log_info "  python3: ✓"
        if python3 -c "import toml" 2>/dev/null; then
            log_info "  toml (Python): ✓"
        else
            log_info "  toml (Python): ✗"
        fi
    else
        log_info "  python3: ✗"
    fi

    if command -v toml &> /dev/null; then
        log_info "  toml (CLI): ✓"
    else
        log_info "  toml (CLI): ✗"
    fi
}

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

    # Enable debug if requested
    if [ "$DEBUG" = "1" ]; then
        set -x
    fi

    # Handle quiet mode
    if [ "$QUIET" = "1" ]; then
        exec 1>/dev/null
    fi

    # Execute command
    case "$COMMAND" in
        build)
            cmd_build "$ENV" "$OUTPUT"
            ;;
        validate)
            cmd_validate "$ENV"
            ;;
        list-features)
            cmd_list_features
            ;;
        list-environments)
            cmd_list_environments
            ;;
        diff)
            cmd_diff "$ENV" "$OUTPUT"
            ;;
        backup)
            cmd_backup "$ENV" "$OUTPUT"
            ;;
        restore)
            cmd_restore "$ENV" "$OUTPUT"
            ;;
        template)
            cmd_template "$ENV"
            ;;
        clean)
            cmd_clean
            ;;
        status)
            cmd_status
            ;;
        help|"")
            show_help
            ;;
        *)
            log_error "Unknown command: $COMMAND"
            show_help
            exit 1
            ;;
    esac
}

# Run main function
main "$@"
