#!/bin/bash
# Configuration Setup Script
# This script helps initialize the configuration system for your Rust application

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

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

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

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

print_header() {
    echo -e "${BLUE}$1${NC}"
}

# Function to check if a command exists
command_exists() {
    command -v "$1" >/dev/null 2>&1
}

# Function to prompt for user input
prompt_user() {
    local prompt="$1"
    local default="$2"
    local result

    if [ -n "$default" ]; then
        echo -n "$prompt [$default]: "
    else
        echo -n "$prompt: "
    fi

    read -r result

    if [ -z "$result" ] && [ -n "$default" ]; then
        result="$default"
    fi

    echo "$result"
}

# Function to generate a random secret
generate_secret() {
    openssl rand -base64 32 2>/dev/null || echo "change-this-to-a-secure-random-string-$(date +%s)"
}

# Main setup function
setup_config() {
    print_header "=== Rust Application Configuration Setup ==="
    echo

    # Check dependencies
    print_status "Checking dependencies..."

    if ! command_exists "cargo"; then
        print_error "Cargo is required but not installed. Please install Rust first."
        exit 1
    fi

    # Determine environment
    print_status "Configuring environment..."

    ENVIRONMENT=$(prompt_user "Enter environment (dev/prod)" "dev")

    case "$ENVIRONMENT" in
        "dev"|"development")
            ENVIRONMENT="dev"
            CONFIG_FILE="config.dev.toml"
            ;;
        "prod"|"production")
            ENVIRONMENT="prod"
            CONFIG_FILE="config.prod.toml"
            ;;
        *)
            print_warning "Unknown environment '$ENVIRONMENT', using 'dev'"
            ENVIRONMENT="dev"
            CONFIG_FILE="config.dev.toml"
            ;;
    esac

    print_status "Environment: $ENVIRONMENT"
    print_status "Config file: $CONFIG_FILE"

    # Check if config file already exists
    if [ -f "$CONFIG_FILE" ]; then
        print_warning "Configuration file $CONFIG_FILE already exists."
        OVERWRITE=$(prompt_user "Overwrite existing file? (y/N)" "n")
        if [[ ! "$OVERWRITE" =~ ^[Yy]$ ]]; then
            print_status "Keeping existing configuration file."
            CONFIG_EXISTS=true
        else
            CONFIG_EXISTS=false
        fi
    else
        CONFIG_EXISTS=false
    fi

    # Create configuration file if it doesn't exist or should be overwritten
    if [ "$CONFIG_EXISTS" != true ]; then
        print_status "Creating configuration file..."

        # Get configuration values from user
        APP_NAME=$(prompt_user "Application name" "My Rust App")
        APP_VERSION=$(prompt_user "Application version" "0.1.0")

        if [ "$ENVIRONMENT" = "dev" ]; then
            SERVER_HOST=$(prompt_user "Server host" "127.0.0.1")
            SERVER_PORT=$(prompt_user "Server port" "3030")
            SERVER_PROTOCOL=$(prompt_user "Server protocol (http/https)" "http")
            LOG_LEVEL=$(prompt_user "Log level (debug/info/warn/error)" "debug")
            DATABASE_URL=$(prompt_user "Database URL" "postgresql://dev:dev@localhost:5432/${APP_NAME,,}_dev")
        else
            SERVER_HOST=$(prompt_user "Server host" "0.0.0.0")
            SERVER_PORT=$(prompt_user "Server port" "443")
            SERVER_PROTOCOL=$(prompt_user "Server protocol (http/https)" "https")
            LOG_LEVEL=$(prompt_user "Log level (debug/info/warn/error)" "info")
            DATABASE_URL=$(prompt_user "Database URL" "postgresql://prod:\${DATABASE_PASSWORD}@db.example.com:5432/${APP_NAME,,}_prod")
        fi

        # Create the configuration file
        cat > "$CONFIG_FILE" << EOF
# ${APP_NAME} Configuration - ${ENVIRONMENT^} Environment
[server]
protocol = "${SERVER_PROTOCOL}"
host = "${SERVER_HOST}"
port = ${SERVER_PORT}
environment = "${ENVIRONMENT}"
log_level = "${LOG_LEVEL}"

EOF

        # Add TLS configuration if HTTPS
        if [ "$SERVER_PROTOCOL" = "https" ]; then
            if [ "$ENVIRONMENT" = "dev" ]; then
                TLS_CERT_PATH=$(prompt_user "TLS certificate path" "certs/server.crt")
                TLS_KEY_PATH=$(prompt_user "TLS private key path" "certs/server.key")
            else
                TLS_CERT_PATH=$(prompt_user "TLS certificate path" "/etc/ssl/certs/server.crt")
                TLS_KEY_PATH=$(prompt_user "TLS private key path" "/etc/ssl/private/server.key")
            fi

            cat >> "$CONFIG_FILE" << EOF
# TLS Configuration
[server.tls]
cert_path = "${TLS_CERT_PATH}"
key_path = "${TLS_KEY_PATH}"

EOF
        fi

        # Add database configuration
        cat >> "$CONFIG_FILE" << EOF
# Database Configuration
[database]
url = "${DATABASE_URL}"
max_connections = $([ "$ENVIRONMENT" = "dev" ] && echo "5" || echo "20")
min_connections = 1
connect_timeout = 30
idle_timeout = 600
max_lifetime = 1800

EOF

        # Add session configuration
        cat >> "$CONFIG_FILE" << EOF
# Session Configuration
[session]
secret = $([ "$ENVIRONMENT" = "dev" ] && echo "\"dev-secret-not-for-production\"" || echo "\"\${SESSION_SECRET}\"")
cookie_name = "session_id"
cookie_secure = $([ "$SERVER_PROTOCOL" = "https" ] && echo "true" || echo "false")
cookie_http_only = true
cookie_same_site = $([ "$ENVIRONMENT" = "dev" ] && echo "\"lax\"" || echo "\"strict\"")
max_age = $([ "$ENVIRONMENT" = "dev" ] && echo "7200" || echo "3600")

EOF

        # Add remaining configuration sections
                cat >> "$CONFIG_FILE" << EOF
        # CORS Configuration
        [cors]
        allowed_origins = [$([ "$ENVIRONMENT" = "dev" ] && echo "\"http://localhost:3030\", \"http://127.0.0.1:3030\"" || echo "\"https://yourdomain.com\"")]
        allowed_methods = ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
        allowed_headers = ["Content-Type", "Authorization", "X-Requested-With"]
        allow_credentials = true
        max_age = 3600

        # Static Files Configuration
        [static]
        assets_dir = "site/public"
        site_root = "target/site"
        site_pkg_dir = "pkg"

        # Server Directories Configuration
        [server_dirs]
        public_dir = $([ "$ENVIRONMENT" = "dev" ] && echo "\"site/public\"" || echo "\"/var/www/public\"")
        uploads_dir = $([ "$ENVIRONMENT" = "dev" ] && echo "\"uploads\"" || echo "\"/var/www/uploads\"")
        logs_dir = $([ "$ENVIRONMENT" = "dev" ] && echo "\"logs\"" || echo "\"/var/log/app\"")
        temp_dir = $([ "$ENVIRONMENT" = "dev" ] && echo "\"tmp\"" || echo "\"/tmp/app\"")
        cache_dir = $([ "$ENVIRONMENT" = "dev" ] && echo "\"cache\"" || echo "\"/var/cache/app\"")
        config_dir = $([ "$ENVIRONMENT" = "dev" ] && echo "\"config\"" || echo "\"/etc/app\"")
        data_dir = $([ "$ENVIRONMENT" = "dev" ] && echo "\"data\"" || echo "\"/var/lib/app\"")
        backup_dir = $([ "$ENVIRONMENT" = "dev" ] && echo "\"backups\"" || echo "\"/var/backups/app\"")

# Security Configuration
[security]
enable_csrf = $([ "$ENVIRONMENT" = "dev" ] && echo "false" || echo "true")
csrf_token_name = "csrf_token"
rate_limit_requests = $([ "$ENVIRONMENT" = "dev" ] && echo "1000" || echo "50")
rate_limit_window = 60
bcrypt_cost = $([ "$ENVIRONMENT" = "dev" ] && echo "4" || echo "12")

# OAuth Configuration
[oauth]
enabled = false

[oauth.google]
client_id = "\${GOOGLE_CLIENT_ID}"
client_secret = "\${GOOGLE_CLIENT_SECRET}"
redirect_uri = "${SERVER_PROTOCOL}://${SERVER_HOST}:${SERVER_PORT}/auth/google/callback"

[oauth.github]
client_id = "\${GITHUB_CLIENT_ID}"
client_secret = "\${GITHUB_CLIENT_SECRET}"
redirect_uri = "${SERVER_PROTOCOL}://${SERVER_HOST}:${SERVER_PORT}/auth/github/callback"

# Email Configuration
[email]
enabled = false
smtp_host = "smtp.gmail.com"
smtp_port = 587
smtp_username = "\${SMTP_USERNAME}"
smtp_password = "\${SMTP_PASSWORD}"
from_email = "noreply@example.com"
from_name = "${APP_NAME}"

# Redis Configuration
[redis]
enabled = false
url = "redis://localhost:6379"
pool_size = 10
connection_timeout = 5
command_timeout = 5

# Application Settings
[app]
name = "${APP_NAME}"
version = "${APP_VERSION}"
debug = $([ "$ENVIRONMENT" = "dev" ] && echo "true" || echo "false")
enable_metrics = $([ "$ENVIRONMENT" = "dev" ] && echo "true" || echo "true")
enable_health_check = true
enable_compression = $([ "$ENVIRONMENT" = "dev" ] && echo "false" || echo "true")
max_request_size = $([ "$ENVIRONMENT" = "dev" ] && echo "52428800" || echo "5242880")

# Logging Configuration
[logging]
format = $([ "$ENVIRONMENT" = "dev" ] && echo "\"text\"" || echo "\"json\"")
level = "${LOG_LEVEL}"
file_path = "logs/app.log"
max_file_size = 10485760
max_files = 5
enable_console = true
enable_file = $([ "$ENVIRONMENT" = "dev" ] && echo "true" || echo "true")

# Content Management
[content]
enabled = false
content_dir = "content"
cache_enabled = $([ "$ENVIRONMENT" = "dev" ] && echo "false" || echo "true")
cache_ttl = 3600
max_file_size = 5242880

# Feature Flags
[features]
auth = true
tls = $([ "$SERVER_PROTOCOL" = "https" ] && echo "true" || echo "false")
content_db = true
two_factor_auth = false
EOF

        print_status "Configuration file created: $CONFIG_FILE"
    fi

    # Create .env file
    ENV_FILE=".env"
    if [ "$ENVIRONMENT" = "dev" ]; then
        ENV_FILE=".env.development"
    elif [ "$ENVIRONMENT" = "prod" ]; then
        ENV_FILE=".env.production"
    fi

    if [ -f "$ENV_FILE" ]; then
        print_warning "Environment file $ENV_FILE already exists."
        OVERWRITE_ENV=$(prompt_user "Overwrite existing environment file? (y/N)" "n")
        if [[ ! "$OVERWRITE_ENV" =~ ^[Yy]$ ]]; then
            print_status "Keeping existing environment file."
            ENV_EXISTS=true
        else
            ENV_EXISTS=false
        fi
    else
        ENV_EXISTS=false
    fi

    if [ "$ENV_EXISTS" != true ]; then
        print_status "Creating environment file..."

        cat > "$ENV_FILE" << EOF
# Environment Configuration for ${ENVIRONMENT^}
ENVIRONMENT=${ENVIRONMENT}

# Database Configuration
EOF

        if [ "$ENVIRONMENT" = "dev" ]; then
            cat >> "$ENV_FILE" << EOF
DATABASE_URL=postgresql://dev:dev@localhost:5432/myapp_dev

# Session Configuration
SESSION_SECRET=dev-secret-not-for-production
EOF
        else
            cat >> "$ENV_FILE" << EOF
DATABASE_PASSWORD=your-production-database-password

# Session Configuration
SESSION_SECRET=$(generate_secret)
EOF
        fi

        cat >> "$ENV_FILE" << EOF

# OAuth Configuration (optional)
# GOOGLE_CLIENT_ID=your-google-client-id
# GOOGLE_CLIENT_SECRET=your-google-client-secret
# GITHUB_CLIENT_ID=your-github-client-id
# GITHUB_CLIENT_SECRET=your-github-client-secret

# Email Configuration (optional)
# SMTP_USERNAME=your-smtp-username
# SMTP_PASSWORD=your-smtp-password

# Server Overrides (optional)
# SERVER_HOST=0.0.0.0
# SERVER_PORT=8080
# LOG_LEVEL=debug
EOF

        print_status "Environment file created: $ENV_FILE"
    fi

    # Create directories
    print_status "Creating directories..."

    # Create basic directories
    mkdir -p logs
    mkdir -p content/public

    # Create server directories based on environment
    if [ "$ENVIRONMENT" = "dev" ]; then
        mkdir -p site/public uploads works-pv/tmp config backups
        print_status "Created development directories: site/public, uploads, works-pv/tmp, config, backups"
    else
        print_status "Production directories should be created by system administrator with proper permissions"
        print_warning "Required directories: /var/www/public, /var/www/uploads, /var/log/app, /tmp/app, /var/cache/app, /etc/app, /var/lib/app, /var/backups/app"
    fi

    if [ "$SERVER_PROTOCOL" = "https" ]; then
        mkdir -p certs
        print_warning "HTTPS is enabled. You'll need to provide TLS certificates in the certs/ directory."
    fi

    # Create a default config.toml symlink if it doesn't exist
    if [ ! -f "config.toml" ]; then
        ln -sf "$CONFIG_FILE" config.toml
        print_status "Created config.toml symlink to $CONFIG_FILE"
    fi

    # Validate configuration
    print_status "Validating configuration..."

    if command_exists "cargo"; then
        if cargo run --bin config_tool -- validate 2>/dev/null; then
            print_status "Configuration validation passed!"
        else
            print_warning "Configuration validation failed. Please check your settings."
        fi
    else
        print_warning "Could not validate configuration (cargo not found)."
    fi

    # Display next steps
    print_header "=== Setup Complete ==="
    echo
    print_status "Configuration has been set up successfully!"
    echo
    print_status "Next steps:"
    echo "1. Review and customize your configuration file: $CONFIG_FILE"
    echo "2. Set up your environment variables: $ENV_FILE"
    echo "3. If using HTTPS, place your TLS certificates in the certs/ directory"
    echo "4. Set up your database and update the connection string"
    echo "5. Configure OAuth providers if needed"
    echo "6. Run 'cargo run --bin config_tool -- show' to view your configuration"
    echo "7. Start your application with 'cargo run'"
    echo

    if [ "$ENVIRONMENT" = "prod" ]; then
        print_warning "Production environment detected!"
        echo "- Make sure to set secure values for SESSION_SECRET and DATABASE_PASSWORD"
        echo "- Review all security settings in your configuration"
        echo "- Use proper secrets management in production"
        echo "- Enable HTTPS with valid TLS certificates"
    fi

    print_status "For more information, see CONFIG_README.md"
}

# Function to show usage
show_usage() {
    echo "Usage: $0 [OPTIONS]"
    echo
    echo "Options:"
    echo "  -h, --help     Show this help message"
    echo "  -e, --env ENV  Set environment (dev/prod)"
    echo "  -f, --force    Overwrite existing files without prompting"
    echo
    echo "Examples:"
    echo "  $0                    # Interactive setup"
    echo "  $0 -e dev             # Setup for development"
    echo "  $0 -e prod            # Setup for production"
    echo "  $0 -f                 # Force overwrite existing files"
}

# Parse command line arguments
FORCE=false
ENV_ARG=""

while [[ $# -gt 0 ]]; do
    case $1 in
        -h|--help)
            show_usage
            exit 0
            ;;
        -e|--env)
            ENV_ARG="$2"
            shift 2
            ;;
        -f|--force)
            FORCE=true
            shift
            ;;
        *)
            print_error "Unknown option: $1"
            show_usage
            exit 1
            ;;
    esac
done

# Set environment if provided
if [ -n "$ENV_ARG" ]; then
    ENVIRONMENT="$ENV_ARG"
fi

# Set force mode
if [ "$FORCE" = true ]; then
    export FORCE_OVERWRITE=true
fi

# Run setup
setup_config
