#!/usr/bin/env nu

# Installer creation tool - creates installation scripts for different platforms
#
# Creates:
# - Platform-specific installation scripts
# - Package manager integration (deb, rpm, msi)
# - Automated configuration setup
# - Service installation and management
# - Uninstall scripts and rollback procedures

use std log

def main [
    --distribution-path: string                 # Path to distribution to create installer for (required)
    --output-dir: string = "installers"        # Output directory for installers
    --installer-types: string = "shell,package" # Installer types: shell, package, gui, all
    --platforms: string = "linux,macos,windows" # Target platforms
    --include-services: bool = true             # Include service installation
    --create-uninstaller: bool = true           # Create uninstall scripts
    --sign-packages: bool = false               # Sign installation packages
    --validate-installer: bool = true           # Validate generated installers
    --compression: string = "gzip"              # Compression method for packages
    --verbose                                   # Enable verbose logging
]
{

    if $distribution_path == "" {
        log error "Distribution path is required"
        exit 1
    }

    let dist_root = ($distribution_path | path expand)

    if not ($dist_root | path exists) {
        log error $"Distribution path does not exist: ($dist_root)"
        exit 1
    }

    let installer_types_list = if $installer_types == "all" {
        ["shell", "package", "gui"]
    } else {
        ($installer_types | split row "," | each { str trim })
    }

    let platforms_list = ($platforms | split row "," | each { str trim })

    let installer_config = {
        distribution_path: $dist_root
        output_dir: ($output_dir | path expand)
        installer_types: $installer_types_list
        platforms: $platforms_list
        include_services: $include_services
        create_uninstaller: $create_uninstaller
        sign_packages: $sign_packages
        validate_installer: $validate_installer
        compression: $compression
        verbose: $verbose
    }

    log info $"Starting installer creation with config: ($installer_config)"

    # Ensure output directory exists
    mkdir ($installer_config.output_dir)

    let creation_results = []

    try {
        # Phase 1: Analyze distribution
        let analysis_result = analyze_distribution $installer_config

        let creation_results = ($creation_results | append { phase: "analysis", result: $analysis_result })

        if $analysis_result.status != "success" {
            log error $"Distribution analysis failed: ($analysis_result.reason)"
            exit 1
        }

        # Phase 2: Create shell installers
        let shell_result = if "shell" in $installer_config.installer_types {
            create_shell_installers $installer_config $analysis_result
        } else {
            { status: "skipped", reason: "shell installers not requested" }
        }

        let creation_results = ($creation_results | append { phase: "shell", result: $shell_result })

        # Phase 3: Create package installers
        let package_result = if "package" in $installer_config.installer_types {
            create_package_installers $installer_config $analysis_result
        } else {
            { status: "skipped", reason: "package installers not requested" }
        }

        let creation_results = ($creation_results | append { phase: "package", result: $package_result })

        # Phase 4: Create GUI installers
        let gui_result = if "gui" in $installer_config.installer_types {
            create_gui_installers $installer_config $analysis_result
        } else {
            { status: "skipped", reason: "GUI installers not requested" }
        }

        let creation_results = ($creation_results | append { phase: "gui", result: $gui_result })

        # Phase 5: Create uninstallers
        let uninstall_result = if $installer_config.create_uninstaller {
            create_uninstall_scripts $installer_config $analysis_result
        } else {
            { status: "skipped", reason: "uninstaller creation disabled" }
        }

        let creation_results = ($creation_results | append { phase: "uninstall", result: $uninstall_result })

        # Phase 6: Validate installers
        let validation_result = if $installer_config.validate_installer {
            validate_installers $installer_config $creation_results
        } else {
            { status: "skipped", reason: "installer validation disabled" }
        }

        let creation_results = ($creation_results | append { phase: "validation", result: $validation_result })

        let summary = {
            distribution_path: $installer_config.distribution_path
            output_directory: $installer_config.output_dir
            installer_types: ($installer_config.installer_types | length)
            platforms: ($installer_config.platforms | length)
            successful_phases: ($creation_results | where {|r| $r.result.status == "success"} | length)
            total_phases: ($creation_results | length)
            installers_created: (count_created_installers $creation_results)
            installer_config: $installer_config
            phases: $creation_results
        }

        log info $"Installer creation completed - ($summary.installers_created) installers created"

        return $summary

    } catch {|err|
        log error $"Installer creation failed: ($err.msg)"
        exit 1
    }
}

# Analyze the distribution to understand its structure
def analyze_distribution [installer_config: record]
{
    log info "Analyzing distribution structure..."

    let start_time = (date now)

    try {
        let dist_path = $installer_config.distribution_path

        # Detect distribution type and structure
        let dist_info = {
            is_archive: (($dist_path | path type) == "file")
            is_directory: (($dist_path | path type) == "dir")
            name: ($dist_path | path basename)
        }

        # If it's an archive, we need to extract it temporarily for analysis
        let analysis_path = if $dist_info.is_archive {
            extract_distribution_for_analysis $dist_path $installer_config
        } else {
            $dist_path
        }

        # Analyze distribution contents
        let components = analyze_distribution_components $analysis_path

        # Detect version information
        let version_info = detect_distribution_version $analysis_path

        # Analyze installation requirements
        let requirements = analyze_installation_requirements $analysis_path $components

        {
            status: "success"
            distribution_info: $dist_info
            analysis_path: $analysis_path
            components: $components
            version_info: $version_info
            requirements: $requirements
            duration: ((date now) - $start_time)
        }

    } catch {|err|
        {
            status: "failed"
            reason: $err.msg
            duration: ((date now) - $start_time)
        }
    }
}

# Extract distribution archive for analysis
def extract_distribution_for_analysis [dist_path: string, installer_config: record]
{
    let temp_dir = ($installer_config.output_dir | path join "tmp" "analysis")
    mkdir $temp_dir

    let dist_name = ($dist_path | path basename)

    if ($dist_name | str ends-with ".tar.gz") or ($dist_name | str ends-with ".tgz") {
        cd $temp_dir
        tar -xzf $dist_path
    } else if ($dist_name | str ends-with ".zip") {
        cd $temp_dir
        unzip $dist_path
    } else {
        error $"Unsupported archive format: ($dist_name)"
    }

    # Find the extracted directory (usually a single top-level directory)
    let extracted_contents = (ls $temp_dir)
    if ($extracted_contents | length) == 1 and (($extracted_contents | get 0.type) == "dir") {
        return ($extracted_contents | get 0.name)
    } else {
        return $temp_dir
    }
}

# Analyze distribution components
def analyze_distribution_components [analysis_path: string]
{
    let components = {
        has_platform: (($analysis_path | path join "platform") | path exists)
        has_core: (($analysis_path | path join "core") | path exists)
        has_config: (($analysis_path | path join "config") | path exists)
        has_docs: (($analysis_path | path join "docs") | path exists)
        has_services: (($analysis_path | path join "services") | path exists)
    }

    # Find executables
    let executables = if $components.has_platform {
        ls ($analysis_path | path join "platform") | where type == file | get name
    } else if $components.has_core and (($analysis_path | path join "core" "bin") | path exists) {
        ls ($analysis_path | path join "core" "bin") | where type == file | get name
    } else {
        []
    }

    # Find configuration files
    let config_files = if $components.has_config {
        find ($analysis_path | path join "config") -name "*.toml" -o -name "*.yaml" -o -name "*.json" | lines
    } else {
        []
    }

    # Find service definitions
    let service_files = if $components.has_services {
        find ($analysis_path | path join "services") -name "*.service" -o -name "*.yml" -o -name "*.yaml" | lines
    } else {
        []
    }

    let components = ($components
        | insert executables $executables
        | insert config_files $config_files
        | insert service_files $service_files
        | insert total_size (get_directory_size $analysis_path))

    return $components
}

# Detect distribution version
def detect_distribution_version [analysis_path: string]
{
    # Try to find version from metadata
    let metadata_files = [
        ($analysis_path | path join "core-metadata.json")
        ($analysis_path | path join "platform-metadata.json")
        ($analysis_path | path join "metadata.json")
        ($analysis_path | path join "VERSION")
    ]

    for metadata_file in $metadata_files {
        if ($metadata_file | path exists) {
            let version = try {
                if ($metadata_file | str ends-with ".json") {
                    let data = (open $metadata_file)
                    return $data.version
                } else {
                    open $metadata_file --raw | str trim
                }
            } catch {
                "unknown"
            }

            if $version != "unknown" {
                return { version: $version, source: ($metadata_file | path basename) }
            }
        }
    }

    # Fallback: try to extract from directory name
    let dir_name = ($analysis_path | path basename)
    let version_match = ($dir_name | parse --regex ".*-([0-9]+\\.[0-9]+\\.[0-9]+)")

    if ($version_match | length) > 0 {
        return { version: ($version_match | get 0.capture0), source: "directory_name" }
    }

    return { version: "unknown", source: "none" }
}

# Analyze installation requirements
def analyze_installation_requirements [analysis_path: string, components: record]
{
    let requirements = {
        system_user: "provisioning"
        system_group: "provisioning"
        install_dirs: []
        config_dirs: []
        data_dirs: []
        log_dirs: []
        service_dependencies: []
        port_requirements: []
    }

    # Standard installation directories
    if $components.has_platform or ($components.executables | length) > 0 {
        $requirements.install_dirs = ($requirements.install_dirs | append "/usr/local/bin")
    }

    if $components.has_core {
        $requirements.install_dirs = ($requirements.install_dirs | append "/usr/local/lib/provisioning")
    }

    if $components.has_config {
        $requirements.config_dirs = ($requirements.config_dirs | append "/etc/provisioning")
    }

    # Data and log directories
    $requirements.data_dirs = ($requirements.data_dirs | append "/var/lib/provisioning")
    $requirements.log_dirs = ($requirements.log_dirs | append "/var/log/provisioning")

    # Service dependencies (would analyze service files to determine)
    if $components.has_services {
        $requirements.service_dependencies = ($requirements.service_dependencies | append "network.target")
    }

    # Port requirements (would analyze configuration to determine)
    $requirements.port_requirements = ($requirements.port_requirements | append { port: 8080, description: "Main API" })

    return $requirements
}

# Create shell installers for different platforms
def create_shell_installers [
    installer_config: record
    analysis_result: record
]
{
    log info "Creating shell installers..."

    let start_time = (date now)

    try {
        let created_installers = []

        for platform in $installer_config.platforms {
            match $platform {
                "linux" | "macos" => {
                    let installer_result = create_unix_shell_installer $platform $installer_config $analysis_result

                    if $installer_result.status == "success" {
                        $created_installers = ($created_installers | append $installer_result)
                    }
                }
                "windows" => {
                    let installer_result = create_windows_batch_installer $installer_config $analysis_result

                    if $installer_result.status == "success" {
                        $created_installers = ($created_installers | append $installer_result)
                    }
                }
                _ => {
                    log warning $"Unsupported platform for shell installer: ($platform)"
                }
            }
        }

        {
            status: "success"
            installers_created: ($created_installers | length)
            created_installers: $created_installers
            duration: ((date now) - $start_time)
        }

    } catch {|err|
        {
            status: "failed"
            reason: $err.msg
            duration: ((date now) - $start_time)
        }
    }
}

# Create Unix shell installer
def create_unix_shell_installer [
    platform: string
    installer_config: record
    analysis_result: record
]
{
    let version = $analysis_result.version_info.version
    let components = $analysis_result.components
    let requirements = $analysis_result.requirements

    let installer_content = $"#!/bin/bash
# Provisioning System Installer
# Platform: ($platform)
# Version: ($version)

set -e

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

# Configuration
INSTALL_USER=\"($requirements.system_user)\"
INSTALL_GROUP=\"($requirements.system_group)\"
SERVICE_NAME=\"provisioning\"

# Installation directories
BIN_DIR=\"/usr/local/bin\"
LIB_DIR=\"/usr/local/lib/provisioning\"
CONFIG_DIR=\"/etc/provisioning\"
DATA_DIR=\"/var/lib/provisioning\"
LOG_DIR=\"/var/log/provisioning\"

# Functions
log_info() {
    echo -e \"${GREEN}[INFO]${NC} $1\"
}

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

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

check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error \"This script must be run as root (use sudo)\"
        exit 1
    fi
}

create_user() {
    if ! id \"$INSTALL_USER\" >/dev/null 2>&1; then
        log_info \"Creating user: $INSTALL_USER\"
        useradd -r -s /bin/false -m -d \"$DATA_DIR\" \"$INSTALL_USER\"
        usermod -a -G \"$INSTALL_GROUP\" \"$INSTALL_USER\" 2>/dev/null || true
    else
        log_info \"User $INSTALL_USER already exists\"
    fi
}

create_directories() {
    log_info \"Creating directories...\"
    mkdir -p \"$BIN_DIR\" \"$LIB_DIR\" \"$CONFIG_DIR\" \"$DATA_DIR\" \"$LOG_DIR\"

    # Set ownership
    chown -R \"$INSTALL_USER:$INSTALL_GROUP\" \"$DATA_DIR\" \"$LOG_DIR\"
    chmod 755 \"$DATA_DIR\" \"$LOG_DIR\"
}

install_binaries() {
    log_info \"Installing binaries...\"
    if [[ -d \"platform\" ]]; then
        cp platform/* \"$BIN_DIR/\"
        chmod +x \"$BIN_DIR\"/provisioning-*
    elif [[ -d \"core/bin\" ]]; then
        cp core/bin/* \"$BIN_DIR/\"
        chmod +x \"$BIN_DIR\"/provisioning*
    else
        log_error \"No binaries found to install\"
        return 1
    fi
}

install_libraries() {
    if [[ -d \"core\" ]]; then
        log_info \"Installing core libraries...\"
        cp -r core/* \"$LIB_DIR/\"
        chown -R root:root \"$LIB_DIR\"
        find \"$LIB_DIR\" -type f -name \"*.nu\" -exec chmod 644 {} \\;
    fi
}

install_configuration() {
    if [[ -d \"config\" ]]; then
        log_info \"Installing configuration...\"
        cp config/*.toml \"$CONFIG_DIR/\" 2>/dev/null || true
        cp config/*.template \"$CONFIG_DIR/\" 2>/dev/null || true

        # Set secure permissions on config files
        chown -R root:\"$INSTALL_GROUP\" \"$CONFIG_DIR\"
        chmod 755 \"$CONFIG_DIR\"
        find \"$CONFIG_DIR\" -name \"*.toml\" -exec chmod 640 {} \\;
    fi
}

install_services() {
    if [[ -d \"services\" ]] && command -v systemctl >/dev/null 2>&1; then
        log_info \"Installing systemd services...\"
        cp services/*.service /etc/systemd/system/ 2>/dev/null || true
        systemctl daemon-reload

        # Enable but don't start services
        for service in services/*.service; do
            if [[ -f \"$service\" ]]; then
                service_name=$(basename \"$service\")
                log_info \"Enabling service: $service_name\"
                systemctl enable \"$service_name\"
            fi
        done
    fi
}

configure_environment() {
    log_info \"Configuring environment...\"

    # Create environment file
    cat > /etc/environment.d/provisioning.conf << EOF
PROVISIONING_HOME=\"$LIB_DIR\"
PROVISIONING_CONFIG=\"$CONFIG_DIR\"
PROVISIONING_DATA=\"$DATA_DIR\"
PROVISIONING_LOG=\"$LOG_DIR\"
EOF

    # Create shell profile
    cat > /etc/profile.d/provisioning.sh << 'EOF'
# Provisioning System Environment
if [ -d \"/usr/local/bin\" ]; then
    case \":$PATH:\" in
        *:/usr/local/bin:*) ;;
        *) PATH=\"/usr/local/bin:$PATH\" ;;
    esac
fi
export PROVISIONING_HOME=\"/usr/local/lib/provisioning\"
export PROVISIONING_CONFIG=\"/etc/provisioning\"
EOF
}

setup_logrotate() {
    log_info \"Setting up log rotation...\"
    cat > /etc/logrotate.d/provisioning << 'EOF'
/var/log/provisioning/*.log {
    daily
    missingok
    rotate 52
    compress
    delaycompress
    notifempty
    create 644 provisioning provisioning
}
EOF
}

main() {
    log_info \"Starting Provisioning System installation...\"

    check_root
    create_user
    create_directories
    install_binaries
    install_libraries
    install_configuration

    if [[ \"$1\" != \"--no-services\" ]]; then
        install_services
    fi

    configure_environment
    setup_logrotate

    log_info \"Installation completed successfully!\"
    log_info \"\"
    log_info \"Next steps:\"
    log_info \"  1. Review configuration in $CONFIG_DIR\"
    log_info \"  2. Start services: sudo systemctl start provisioning\"
    log_info \"  3. Run 'provisioning help' to get started\"
    log_info \"\"
    log_info \"For more information, see the documentation in $LIB_DIR/docs\"
}

# Handle command line arguments
case \"$1\" in
    --help|-h)
        echo \"Provisioning System Installer ($version)\"
        echo \"\"
        echo \"Usage: $0 [OPTIONS]\"
        echo \"\"
        echo \"Options:\"
        echo \"  --no-services    Skip service installation\"
        echo \"  --help, -h       Show this help message\"
        exit 0
        ;;
    *)
        main \"$@\"
        ;;
esac
"

    let installer_file = ($installer_config.output_dir | path join $"install-($platform).sh")
    $installer_content | save $installer_file
    chmod +x $installer_file

    {
        platform: $platform
        status: "success"
        installer_type: "shell"
        installer_file: $installer_file
        size: ($installer_content | str length)
    }
}

# Create Windows batch installer
def create_windows_batch_installer [
    installer_config: record
    analysis_result: record
]
{
    let version = $analysis_result.version_info.version
    let components = $analysis_result.components

    let installer_content = $"@echo off
REM Provisioning System Installer
REM Platform: Windows
REM Version: ($version)

setlocal EnableDelayedExpansion

REM Configuration
set \"INSTALL_DIR=C:\\Program Files\\Provisioning\"
set \"CONFIG_DIR=C:\\ProgramData\\Provisioning\"
set \"SERVICE_NAME=ProvisioningService\"

echo.
echo ========================================
echo Provisioning System Installer ($version)
echo ========================================
echo.

REM Check for administrator privileges
net session >nul 2>&1
if %errorLevel% neq 0 (
    echo ERROR: This script must be run as Administrator
    echo Right-click and select \"Run as administrator\"
    pause
    exit /b 1
)

echo Creating directories...
mkdir \"%INSTALL_DIR%\\bin\" 2>nul
mkdir \"%INSTALL_DIR%\\lib\" 2>nul
mkdir \"%CONFIG_DIR%\" 2>nul

echo Installing binaries...
if exist \"platform\\\" (
    xcopy platform\\* \"%INSTALL_DIR%\\bin\\\" /Y /Q
) else if exist \"core\\bin\\\" (
    xcopy core\\bin\\* \"%INSTALL_DIR%\\bin\\\" /Y /Q
) else (
    echo ERROR: No binaries found to install
    pause
    exit /b 1
)

echo Installing libraries...
if exist \"core\\\" (
    xcopy core\\* \"%INSTALL_DIR%\\lib\\\" /Y /Q /S
)

echo Installing configuration...
if exist \"config\\\" (
    xcopy config\\* \"%CONFIG_DIR%\\\" /Y /Q /S
)

echo Configuring environment...
REM Add installation directory to system PATH
for /f \"usebackq tokens=2,*\" %%A in (`reg query HKCU\\Environment /v PATH`) do set \"current_path=%%B\"
echo !current_path! | findstr /C:\"%INSTALL_DIR%\\bin\" >nul
if !errorLevel! neq 0 (
    setx PATH \"!current_path!;%INSTALL_DIR%\\bin\"
    echo Added %INSTALL_DIR%\\bin to PATH
)

REM Set environment variables
setx PROVISIONING_HOME \"%INSTALL_DIR%\"
setx PROVISIONING_CONFIG \"%CONFIG_DIR%\"

echo.
echo Installation completed successfully!
echo.
echo Next steps:
echo   1. Review configuration in %CONFIG_DIR%
echo   2. Run 'provisioning-orchestrator --help' to get started
echo   3. Check the documentation in %INSTALL_DIR%\\lib\\docs
echo.
echo NOTE: You may need to restart your command prompt for PATH changes to take effect.
echo.
pause
"

    let installer_file = ($installer_config.output_dir | path join "install-windows.bat")
    $installer_content | save $installer_file

    {
        platform: "windows"
        status: "success"
        installer_type: "batch"
        installer_file: $installer_file
        size: ($installer_content | str length)
    }
}

# Create package installers (deb, rpm, msi)
def create_package_installers [
    installer_config: record
    analysis_result: record
]
{
    log info "Creating package installers..."

    let start_time = (date now)

    # Package creation would involve:
    # 1. Creating package control files
    # 2. Building packages with appropriate tools
    # 3. Signing packages if requested

    log warning "Package installer creation not fully implemented"

    {
        status: "skipped"
        reason: "package installers not fully implemented"
        installers_created: 0
        duration: ((date now) - $start_time)
    }
}

# Create GUI installers
def create_gui_installers [
    installer_config: record
    analysis_result: record
]
{
    log info "Creating GUI installers..."

    let start_time = (date now)

    # GUI installer creation would involve:
    # 1. Creating installer definition files
    # 2. Using platform-specific tools (NSIS, InstallShield, etc.)
    # 3. Including custom installation wizards

    log warning "GUI installer creation not fully implemented"

    {
        status: "skipped"
        reason: "GUI installers not fully implemented"
        installers_created: 0
        duration: ((date now) - $start_time)
    }
}

# Create uninstall scripts
def create_uninstall_scripts [
    installer_config: record
    analysis_result: record
]
{
    log info "Creating uninstall scripts..."

    let start_time = (date now)

    try {
        let created_uninstallers = []

        for platform in $installer_config.platforms {
            match $platform {
                "linux" | "macos" => {
                    let uninstaller_result = create_unix_uninstaller $platform $installer_config $analysis_result

                    if $uninstaller_result.status == "success" {
                        $created_uninstallers = ($created_uninstallers | append $uninstaller_result)
                    }
                }
                "windows" => {
                    let uninstaller_result = create_windows_uninstaller $installer_config $analysis_result

                    if $uninstaller_result.status == "success" {
                        $created_uninstallers = ($created_uninstallers | append $uninstaller_result)
                    }
                }
                _ => {
                    log warning $"Unsupported platform for uninstaller: ($platform)"
                }
            }
        }

        {
            status: "success"
            uninstallers_created: ($created_uninstallers | length)
            created_uninstallers: $created_uninstallers
            duration: ((date now) - $start_time)
        }

    } catch {|err|
        {
            status: "failed"
            reason: $err.msg
            duration: ((date now) - $start_time)
        }
    }
}

# Create Unix uninstaller
def create_unix_uninstaller [
    platform: string
    installer_config: record
    analysis_result: record
]
{
    let version = $analysis_result.version_info.version
    let requirements = $analysis_result.requirements

    let uninstaller_content = $"#!/bin/bash
# Provisioning System Uninstaller
# Platform: ($platform)
# Version: ($version)

set -e

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

log_info() {
    echo -e \"${GREEN}[INFO]${NC} $1\"
}

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

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

check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error \"This script must be run as root (use sudo)\"
        exit 1
    fi
}

confirm_uninstall() {
    echo \"This will completely remove the Provisioning System from your system.\"
    echo \"This includes:\"
    echo \"  - All binaries and libraries\"
    echo \"  - Configuration files\"
    echo \"  - Service definitions\"
    echo \"  - Log files and data\"
    echo \"\"
    read -p \"Are you sure you want to continue? (y/N): \" -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        log_info \"Uninstallation cancelled\"
        exit 0
    fi
}

stop_services() {
    log_info \"Stopping services...\"
    if command -v systemctl >/dev/null 2>&1; then
        systemctl stop provisioning* 2>/dev/null || true
        systemctl disable provisioning* 2>/dev/null || true
    fi
}

remove_binaries() {
    log_info \"Removing binaries...\"
    rm -f /usr/local/bin/provisioning*
}

remove_libraries() {
    log_info \"Removing libraries...\"
    rm -rf /usr/local/lib/provisioning
}

remove_configuration() {
    log_info \"Removing configuration...\"
    rm -rf /etc/provisioning
}

remove_data() {
    if [[ \"$1\" == \"--keep-data\" ]]; then
        log_info \"Keeping data directory (--keep-data specified)\"
    else
        log_info \"Removing data and logs...\"
        rm -rf /var/lib/provisioning
        rm -rf /var/log/provisioning
    fi
}

remove_services() {
    log_info \"Removing service definitions...\"
    rm -f /etc/systemd/system/provisioning*.service
    if command -v systemctl >/dev/null 2>&1; then
        systemctl daemon-reload
    fi
}

remove_environment() {
    log_info \"Removing environment configuration...\"
    rm -f /etc/environment.d/provisioning.conf
    rm -f /etc/profile.d/provisioning.sh
    rm -f /etc/logrotate.d/provisioning
}

remove_user() {
    if [[ \"$1\" == \"--keep-user\" ]]; then
        log_info \"Keeping system user (--keep-user specified)\"
    else
        log_info \"Removing system user...\"
        userdel provisioning 2>/dev/null || true
    fi
}

main() {
    log_info \"Starting Provisioning System uninstallation...\"

    check_root
    confirm_uninstall

    stop_services
    remove_services
    remove_binaries
    remove_libraries
    remove_configuration
    remove_data \"$1\"
    remove_environment
    remove_user \"$1\"

    log_info \"Uninstallation completed successfully!\"
    log_info \"\"
    log_info \"Thank you for using the Provisioning System.\"
}

case \"$1\" in
    --help|-h)
        echo \"Provisioning System Uninstaller ($version)\"
        echo \"\"
        echo \"Usage: $0 [OPTIONS]\"
        echo \"\"
        echo \"Options:\"
        echo \"  --keep-data      Keep data directory and logs\"
        echo \"  --keep-user      Keep system user account\"
        echo \"  --help, -h       Show this help message\"
        exit 0
        ;;
    *)
        main \"$@\"
        ;;
esac
"

    let uninstaller_file = ($installer_config.output_dir | path join $"uninstall-($platform).sh")
    $uninstaller_content | save $uninstaller_file
    chmod +x $uninstaller_file

    {
        platform: $platform
        status: "success"
        uninstaller_type: "shell"
        uninstaller_file: $uninstaller_file
        size: ($uninstaller_content | str length)
    }
}

# Create Windows uninstaller
def create_windows_uninstaller [
    installer_config: record
    analysis_result: record
]
{
    let version = $analysis_result.version_info.version

    let uninstaller_content = $"@echo off
REM Provisioning System Uninstaller
REM Platform: Windows
REM Version: ($version)

setlocal EnableDelayedExpansion

echo.
echo ==========================================
echo Provisioning System Uninstaller ($version)
echo ==========================================
echo.

REM Check for administrator privileges
net session >nul 2>&1
if %errorLevel% neq 0 (
    echo ERROR: This script must be run as Administrator
    pause
    exit /b 1
)

echo This will completely remove the Provisioning System from your system.
echo.
set /p \"confirm=Are you sure you want to continue? (y/N): \"
if /I not \"!confirm!\"==\"y\" (
    echo Uninstallation cancelled
    exit /b 0
)

echo.
echo Stopping services...
REM Stop any running services here

echo Removing installation directory...
if exist \"C:\\Program Files\\Provisioning\" (
    rmdir /S /Q \"C:\\Program Files\\Provisioning\"
)

echo Removing configuration...
if exist \"C:\\ProgramData\\Provisioning\" (
    rmdir /S /Q \"C:\\ProgramData\\Provisioning\"
)

echo Removing environment variables...
reg delete HKCU\\Environment /v PROVISIONING_HOME /f 2>nul
reg delete HKCU\\Environment /v PROVISIONING_CONFIG /f 2>nul

echo Removing from PATH...
for /f \"usebackq tokens=2,*\" %%A in (`reg query HKCU\\Environment /v PATH 2^>nul`) do (
    set \"current_path=%%B\"
    set \"new_path=!current_path:C:\\Program Files\\Provisioning\\bin;=!\"
    set \"new_path=!new_path:;C:\\Program Files\\Provisioning\\bin=!\"
    if not \"!new_path!\"==\"!current_path!\" (
        setx PATH \"!new_path!\"
        echo Removed from PATH
    )
)

echo.
echo Uninstallation completed successfully!
echo Thank you for using the Provisioning System.
echo.
pause
"

    let uninstaller_file = ($installer_config.output_dir | path join "uninstall-windows.bat")
    $uninstaller_content | save $uninstaller_file

    {
        platform: "windows"
        status: "success"
        uninstaller_type: "batch"
        uninstaller_file: $uninstaller_file
        size: ($uninstaller_content | str length)
    }
}

# Validate generated installers
def validate_installers [
    installer_config: record
    creation_results: list
]
{
    log info "Validating installers..."

    let start_time = (date now)

    # Installer validation would involve:
    # 1. Syntax checking of shell scripts
    # 2. Testing installation in clean environments
    # 3. Verifying uninstaller functionality

    log warning "Installer validation not fully implemented"

    {
        status: "skipped"
        reason: "installer validation not fully implemented"
        validated_installers: 0
        duration: ((date now) - $start_time)
    }
}

# Count created installers from results
def count_created_installers [creation_results: list] -> int {
    let shell_count = try {
        let shell_result = ($creation_results | where phase == "shell" | get 0.result)
        $shell_result.installers_created
    } catch { 0 }

    let package_count = try {
        let package_result = ($creation_results | where phase == "package" | get 0.result)
        $package_result.installers_created
    } catch { 0 }

    let gui_count = try {
        let gui_result = ($creation_results | where phase == "gui" | get 0.result)
        $gui_result.installers_created
    } catch { 0 }

    let uninstall_count = try {
        let uninstall_result = ($creation_results | where phase == "uninstall" | get 0.result)
        $uninstall_result.uninstallers_created
    } catch { 0 }

    return ($shell_count + $package_count + $gui_count + $uninstall_count)
}

# Get directory size helper
def get_directory_size [dir: string] -> int {
    if not ($dir | path exists) {
        return 0
    }

    try {
        find $dir -type f | each {|file| ls $file | get 0.size } | math sum | if $in == null { 0 } else { $in }
    } catch {
        0
    }
}

# Show installer creation status
def "main status" [distribution_path: string = ""] {
    if $distribution_path == "" {
        return {
            error: "distribution path required"
            usage: "main status <distribution-path>"
            supported_platforms: ["linux", "macos", "windows"]
            installer_types: ["shell", "package", "gui"]
        }
    }

    let dist_path = ($distribution_path | path expand)

    if not ($dist_path | path exists) {
        return {
            error: "distribution path does not exist"
            path: $dist_path
        }
    }

    # Quick analysis of distribution
    let dist_info = {
        path: $dist_path
        type: ($dist_path | path type)
        name: ($dist_path | path basename)
        size: (get_directory_size $dist_path)
    }

    {
        distribution: $dist_info
        can_create_installers: true
        supported_platforms: ["linux", "macos", "windows"]
        installer_types: ["shell", "package", "gui"]
        features: {
            shell_installers: true
            package_installers: false  # Not fully implemented
            gui_installers: false      # Not fully implemented
            uninstallers: true
            service_management: true
        }
    }
}

# Quick installer creation with minimal options
def "main quick" [
    distribution_path: string                   # Distribution to create installer for
    --platform: string = "linux"               # Single platform
    --output-dir: string = "installers"        # Output directory
] {
    main $distribution_path --platforms $platform --installer-types shell --output-dir $output_dir
}
