# VM Cleanup Scheduler (Phase 2)
#
# Manages automatic cleanup of expired temporary VMs.
# Rule 1: Single purpose, Rule 4: Pure functions, Rule 5: Atomic operations

# Selective imports (ADR-025 Phase 3 Layer 2).
# vm/lifecycle.nu star-import was dead — dropped.
# Note: line ~211 embeds a string template with `use lib_provisioning/vm/cleanup_scheduler.nu *`
# (scheduler script written to disk at runtime) — NOT an actual import.
use lib_provisioning/vm/vm_persistence.nu [
    cleanup-expired-vms find-expired-vms get-vm-persistence-info
    get-vm-time-to-cleanup
]

export def "start-cleanup-scheduler" [
    --check-interval-minutes: int = 60
    --background = true
]: record {
    """
    Start the VM cleanup scheduler.

    Periodically checks for and cleans up expired temporary VMs.
    Can run in background or foreground.
    """

    if $background {
        # Start in background
        start-scheduler-background $check_interval_minutes
    } else {
        # Run foreground
        run-scheduler-loop $check_interval_minutes
    }
}

def start-scheduler-background [interval_minutes: int]: record {
    """Start scheduler in background"""

    let scheduler_file = (get-scheduler-pid-file)
    let scheduler_script = (get-scheduler-script-path)

    # Create scheduler script
    create-scheduler-script $interval_minutes $scheduler_script

    # Start in background (no try-catch)
    let start_result = (do { bash -c $"nohup nu ($scheduler_script) > /tmp/vm-cleanup-scheduler.log 2>&1 &" } | complete)
    if $start_result.exit_code != 0 {
        return {
            success: false
            error: $"Failed to start scheduler: ($start_result.stderr)"
        }
    }

    let pid_result = (do { bash -c "echo $!" } | complete)
    if $pid_result.exit_code != 0 {
        return {
            success: false
            error: $"Failed to get scheduler PID: ($pid_result.stderr)"
        }
    }

    let pid = ($pid_result.stdout | str trim)

    # Save PID (no try-catch)
    let save_pid_result = (do { bash -c $"echo ($pid) > ($scheduler_file)" } | complete)
    if $save_pid_result.exit_code != 0 {
        return {
            success: false
            error: $"Failed to save scheduler PID: ($save_pid_result.stderr)"
        }
    }

    {
        success: true
        pid: $pid
        message: "Cleanup scheduler started in background"
    }
}

export def "stop-cleanup-scheduler" []: record {
    """Stop the VM cleanup scheduler"""

    let scheduler_file = (get-scheduler-pid-file)

    if not ($scheduler_file | path exists) {
        return {
            success: true
            message: "Scheduler not running"
        }
    }

    # Load scheduler PID (no try-catch)
    let pid_result = (do { open $scheduler_file | str trim } | complete)
    if $pid_result.exit_code != 0 {
        return {
            success: false
            error: $"Failed to read scheduler PID: ($pid_result.stderr)"
        }
    }

    let pid = ($pid_result.stdout)

    # Kill scheduler process (no try-catch)
    let kill_result = (do { bash -c $"kill ($pid) 2>/dev/null || true" } | complete)
    if $kill_result.exit_code != 0 {
        return {
            success: false
            error: $"Failed to kill scheduler: ($kill_result.stderr)"
        }
    }

    # Remove PID file (no try-catch)
    let rm_result = (do { bash -c $"rm -f ($scheduler_file)" } | complete)
    if $rm_result.exit_code != 0 {
        return {
            success: false
            error: $"Failed to remove PID file: ($rm_result.stderr)"
        }
    }

    {
        success: true
        pid: $pid
        message: "Scheduler stopped"
    }
}

export def "get-cleanup-scheduler-status" []: record {
    """Get status of cleanup scheduler"""

    let scheduler_file = (get-scheduler-pid-file)
    let log_file = "/tmp/vm-cleanup-scheduler.log"

    if not ($scheduler_file | path exists) {
        return {
            running: false
            message: "Scheduler not running"
        }
    }

    # Load scheduler PID (no try-catch)
    let pid_result = (do { open $scheduler_file | str trim } | complete)
    if $pid_result.exit_code != 0 {
        return {
            running: false
            error: $"Failed to read scheduler PID: ($pid_result.stderr)"
        }
    }

    let pid = ($pid_result.stdout)

    # Check if process exists (no try-catch)
    let check_result = (do { bash -c $"kill -0 ($pid) 2>/dev/null && echo 'true' || echo 'false'" } | complete)
    let is_running = (
        if $check_result.exit_code == 0 {
            ($check_result.stdout | str trim)
        } else {
            "false"
        }
    )

    let log_exists = ($log_file | path exists)

    # Read log file if it exists (no try-catch)
    let last_log_lines = (
        if $log_exists {
            let log_result = (do { bash -c $"tail -5 ($log_file)" } | complete)
            if $log_result.exit_code == 0 {
                ($log_result.stdout | lines)
            } else {
                []
            }
        } else {
            []
        }
    )

    {
        running: ($is_running == "true")
        pid: $pid
        log_file: $log_file
        recent_logs: $last_log_lines
    }
}

def run-scheduler-loop [interval_minutes: int] {
    """Run cleanup scheduler loop"""

    print "VM Cleanup Scheduler starting..."
    print $"Check interval: ($interval_minutes) minutes"
    print "Press Ctrl+C to stop scheduler"

    mut iteration = 0
    let max_iterations = 1_000_000  # Safety limit: ~2 years at 1 min intervals

    while { $iteration < $max_iterations } {
        # Run cleanup
        let result = (cleanup-expired-vms)

        if $result.cleaned_up > 0 {
            print $"[$(date now)] Cleaned up ($result.cleaned_up) VMs"
        }

        # Wait for next check
        print $"[$(date now)] Next check in ($interval_minutes) minutes"
        sleep ($interval_minutes)m

        $iteration += 1
    }

    print "Scheduler reached iteration limit - exiting"
}

def create-scheduler-script [interval: int, script_path: string] {
    """Create background scheduler script"""

    let script_content = $'
use lib_provisioning/vm/cleanup_scheduler.nu *

mut iteration = 0
let max_iterations = 1_000_000

while \{ $iteration < $max_iterations \} \{
    cleanup-expired-vms
    sleep ($interval)m
    $iteration += 1
\}
'

    bash -c $"cat > ($script_path) << 'SCRIPT'\n($script_content)\nSCRIPT"
}

export def "schedule-vm-cleanup" [
    vm_name: string               # VM name to cleanup
    delay_minutes: int = 0        # Minutes to delay before cleanup
]: record {
    """Schedule cleanup for a specific VM"""

    let persist_info = (get-vm-persistence-info $vm_name)

    if ($persist_info.mode // "") != "temporary" {
        return {
            success: false
            error: "VM is not temporary"
        }
    }

    let cleanup_time = (
        if $delay_minutes > 0 {
            (date now) + ($delay_minutes)m
        } else {
            date now
        }
    )

    let updated = (
        $persist_info
        | upsert scheduled_cleanup_at $cleanup_time
        | upsert cleanup_status "pending"
    )

    let persist_file = (get-persistence-file $vm_name)

    # Schedule cleanup (no try-catch)
    let schedule_result = (do { bash -c $"cat > ($persist_file) << 'EOF'\n($updated | to json)\nEOF" } | complete)
    if $schedule_result.exit_code != 0 {
        return {
            success: false
            error: $"Failed to schedule cleanup: ($schedule_result.stderr)"
        }
    }

    {
        success: true
        vm_name: $vm_name
        scheduled_cleanup_at: $cleanup_time
        message: $"Cleanup scheduled for ($vm_name)"
    }
}

export def "cancel-vm-cleanup" [
    vm_name: string               # VM name
]: record {
    """Cancel scheduled cleanup for a VM"""

    let persist_info = (get-vm-persistence-info $vm_name)

    if ($persist_info.mode // "") != "temporary" {
        return {
            success: false
            error: "VM is not temporary"
        }
    }

    # Set cleanup to far future (essentially disabled)
    let far_future = (
        (date now) + 8760h  # 1 year from now
    )

    let updated = (
        $persist_info
        | upsert scheduled_cleanup_at $far_future
        | upsert cleanup_status "cancelled"
    )

    let persist_file = (get-persistence-file $vm_name)

    # Cancel cleanup (no try-catch)
    let cancel_result = (do { bash -c $"cat > ($persist_file) << 'EOF'\n($updated | to json)\nEOF" } | complete)
    if $cancel_result.exit_code != 0 {
        return {
            success: false
            error: $"Failed to cancel cleanup: ($cancel_result.stderr)"
        }
    }

    {
        success: true
        vm_name: $vm_name
        message: "Cleanup cancelled for VM"
    }
}

export def "get-cleanup-queue" []: table {
    """Get list of VMs pending cleanup"""

    find-expired-vms
    | map {|vm|
        let time_info = (get-vm-time-to-cleanup $vm.vm_name)

        {
            vm_name: $vm.vm_name
            created_at: $vm.created_at
            ttl_hours: $vm.ttl_hours
            status: $vm.cleanup_status
            scheduled_cleanup_at: $vm.scheduled_cleanup_at
            time_remaining: $time_info
        }
    }
}

def get-scheduler-pid-file []: string {
    """Get PID file path for scheduler"""
    "/var/run/vm-cleanup-scheduler.pid"
}

def get-scheduler-script-path []: string {
    """Get scheduler script path"""
    $"{{paths.workspace}}/vms/.cleanup-scheduler.nu"
}

def get-persistence-file [vm_name: string]: string {
    """Get persistence file for VM"""
    $"{{paths.workspace}}/vms/persistence/($vm_name).json"
}
