# Workspace Management CLI Commands
# Commands for switching between workspaces and managing workspace registry

use ../user/config.nu *
use ../utils/hints.nu *
use ../platform/activation.nu *
use ./notation.nu *

# Activate a workspace (set as current)
export def "workspace activate" [
    spec: string  # Name of workspace or workspace:infra notation
    --quiet (-q)  # Suppress output messages
] {
    # Parse workspace:infra notation
    let parsed = (parse-workspace-infra-notation $spec)
    let workspace_name = $parsed.workspace

    # Validate workspace exists in registry
    if not (validate-workspace-exists $workspace_name) {
        print $"(ansi red)✗(ansi reset) Workspace '($workspace_name)' not found in registry"
        print $"(ansi yellow)💡(ansi reset) Available workspaces:"
        workspace list
        print ""
        print $"(ansi yellow)💡(ansi reset) Register it first with: provisioning workspace register ($workspace_name) <path>"
        return
    }

    # Get workspace path from registry
    let workspace_path = (get-workspace-path $workspace_name)

    # Validate workspace directory exists
    if not ($workspace_path | path exists) {
        print $"(ansi red)✗(ansi reset) Workspace directory not found: ($workspace_path)"
        print $"(ansi yellow)💡(ansi reset) The workspace may have been moved or deleted"
        return
    }

    # Validate workspace has config directory
    let config_path = ($workspace_path | path join "config")
    if not ($config_path | path exists) {
        print $"(ansi red)✗(ansi reset) Workspace is not migrated to new config system"
        print $"(ansi yellow)💡(ansi reset) Missing: ($config_path)"
        print $"(ansi yellow)💡(ansi reset) Run migration: provisioning workspace migrate ($workspace_name)"
        return
    }

    # Validate provisioning.ncl or provisioning.yaml exists
    let provisioning_nickel = ($config_path | path join "provisioning.ncl")
    let provisioning_yaml = ($config_path | path join "provisioning.yaml")

    if not (($provisioning_nickel | path exists) or ($provisioning_yaml | path exists)) {
        print $"(ansi red)✗(ansi reset) Missing workspace configuration"
        print $"(ansi yellow)💡(ansi reset) Missing: ($provisioning_nickel) or ($provisioning_yaml)"
        print $"(ansi yellow)💡(ansi reset) Run migration: provisioning workspace migrate ($workspace_name)"
        return
    }

    # Set as active workspace (required before platform activation)
    set-active-workspace $workspace_name $workspace_path

    # Set default infra if provided via workspace:infra notation
    if ($parsed.infra | is-not-empty) {
        # Validate infra exists
        let infra_path = ([$workspace_path "infra" $parsed.infra] | path join)
        let settings_file = ([$infra_path "settings.ncl"] | path join)

        if not ($settings_file | path exists) {
            print $"(ansi red)✗(ansi reset) Infrastructure '($parsed.infra)' not found in workspace '($workspace_name)'"
            print $"(ansi yellow)💡(ansi reset) Missing: ($settings_file)"
            return
        }

        # Set default infra
        set-workspace-default-infra $workspace_name $parsed.infra
        if not $quiet {
            print $"(ansi green)✓(ansi reset) Default infrastructure set to '($parsed.infra)'"
        }
    }

    # Activate platform services
    let platform_activated = (activate-workspace-platform $workspace_name --auto-start --wait --skip-optional)
    if not $platform_activated {
        print $"(ansi yellow)⚠️(ansi reset) Platform activation warning: services not fully available"
        print $"(ansi yellow)💡(ansi reset) You can still use the workspace, but some services may not be available"
    }

    if not $quiet {
        show-next-step "workspace_activate" {name: $workspace_name}
    }
}

# Switch to another workspace (alias for activate)
export def "workspace switch" [
    workspace_name: string  # Name of workspace to switch to
    --quiet (-q)  # Suppress output messages
] {
    workspace activate $workspace_name --quiet=$quiet
}

# List all known workspaces
export def "workspace list" [
    --format (-f): string = "table"  # Output format: table, json, yaml
    --notitles                       # Suppress section title and spacing
] {
    let workspaces = (list-workspaces)

    if ($workspaces | is-empty) {
        if not $notitles {
            print $"(ansi yellow)No workspaces registered(ansi reset)"
            print ""
            print $"(ansi cyan)💡(ansi reset) Register a workspace with:"
            print $"   provisioning workspace register <name> <path>"
        }
        return
    }

    match $format {
        "json" => { $workspaces | to json }
        "yaml" => { $workspaces | to yaml }
        _ => {
            if not $notitles {
                print ""
                print $"(ansi green_bold)Registered Workspaces:(ansi reset)"
                print ""
            }
            let active = (get-active-workspace)
            $workspaces | each { |ws|
                let is_active = ($ws.name == $active)
                let active_marker = if $is_active { $"(ansi green)●(ansi reset)" } else { " " }
                let name_display = if $is_active {
                    $"(ansi green_bold)($ws.name)(ansi reset)"
                } else {
                    $ws.name
                }
                print $"  ($active_marker) ($name_display)"
                print $"      Path: ($ws.path)"
                print $"      Last used: ($ws.last_used)"
                if not $notitles {
                    print ""
                }
            } | ignore
        }
    }
}

# Show currently active workspace
export def "workspace active" [] {
    let active_workspace = (get-active-workspace)

    if ($active_workspace == null) {
        print $"(ansi yellow)No active workspace(ansi reset)"
        print ""
        print $"(ansi cyan)💡(ansi reset) Activate a workspace with:"
        print $"   provisioning workspace activate <name>"
        return
    }

    let workspace_details = (get-active-workspace-details)

    print ""
    print $"(ansi green_bold)Active Workspace:(ansi reset)"
    print $"  Name: (ansi green)($workspace_details.name)(ansi reset)"
    print $"  Path: ($workspace_details.path)"
    print $"  Last used: ($workspace_details.last_used)"
    print ""
}

# Register a workspace in the central registry
export def "workspace register" [
    workspace_name: string  # Name of workspace
    workspace_path: string  # Path to workspace directory
    --activate (-a)  # Activate after registering
] {
    # Expand path
    let expanded_path = ($workspace_path | path expand)

    # Validate directory exists
    if not ($expanded_path | path exists) {
        print $"(ansi red)✗(ansi reset) Directory not found: ($expanded_path)"
        return
    }

    # Validate it's a directory
    if ($expanded_path | path type) != "dir" {
        print $"(ansi red)✗(ansi reset) Not a directory: ($expanded_path)"
        return
    }

    # Register workspace
    register-workspace $workspace_name $expanded_path

    # Activate if requested
    if $activate {
        print ""
        workspace activate $workspace_name
    }
}

# Remove workspace from registry (does not delete files)
export def "workspace remove" [
    workspace_name: string  # Name of workspace to remove
    --force (-f)  # Skip confirmation prompt
] {
    # Check if workspace exists
    if not (validate-workspace-exists $workspace_name) {
        print $"(ansi red)✗(ansi reset) Workspace '($workspace_name)' not found in registry"
        return
    }

    # Confirm deletion unless --force
    if not $force {
        print $"(ansi yellow)⚠(ansi reset) This will remove '($workspace_name)' from the registry"
        print $"(ansi cyan)ℹ(ansi reset) The workspace files will NOT be deleted"
        print ""

        let response = (input "Continue? (y/N): ")

        if $response != "y" and $response != "Y" {
            print $"(ansi yellow)Cancelled(ansi reset)"
            return
        }
    }

    # Remove workspace
    remove-workspace $workspace_name
}

# Show workspace preferences
export def "workspace preferences" [
    --format (-f): string = "table"  # Output format: table, json, yaml
] {
    let config = (load-user-config)

    match $format {
        "json" => { $config.preferences | to json }
        "yaml" => { $config.preferences | to yaml }
        _ => {
            print ""
            print $"(ansi green_bold)User Preferences:(ansi reset)"
            print ""
            $config.preferences | transpose key value | each { |pref|
                print $"  ($pref.key): (ansi cyan)($pref.value)(ansi reset)"
            }
            print ""
        }
    }
}

# Set workspace preference
export def "workspace set-preference" [
    key: string    # Preference key
    value: string  # Preference value
] {
    set-user-preference $key $value
}

# Get workspace preference
export def "workspace get-preference" [
    key: string  # Preference key
] {
    let value = (get-user-preference $key)

    if ($value == null) {
        print $"(ansi yellow)Preference '($key)' not found(ansi reset)"
    } else {
        print $value
    }
}

# Show workspace version information
export def "workspace version" [
    workspace_name?: string  # Workspace name (default: active workspace)
    --format (-f): string = "table"  # Output format: table, json, yaml
] {
    use version.nu *

    # Get workspace to check
    let ws_name = if ($workspace_name | is-not-empty) {
        $workspace_name
    } else {
        let active = (get-active-workspace)
        if ($active == null or ($active | is-empty)) {
            print $"(ansi red)No active workspace(ansi reset)"
            print $"(ansi yellow)Specify workspace name or activate a workspace first(ansi reset)"
            return
        }
        $active
    }

    # Get workspace path
    let ws_path = (get-workspace-path $ws_name)

    if ($ws_path == null or not ($ws_path | path exists)) {
        print $"(ansi red)Workspace not found: ($ws_name)(ansi reset)"
        return
    }

    # Get version summary
    let summary = (get-version-summary $ws_path)

    match $format {
        "json" => { $summary | to json }
        "yaml" => { $summary | to yaml }
        _ => {
            print ""
            print $"(ansi green_bold)Workspace Version Information(ansi reset)"
            print ""
            print $"(ansi cyan)System:(ansi reset)"
            print $"  Version: ($summary.system.version)"
            print ""
            print $"(ansi cyan)Workspace:(ansi reset)"
            print $"  Name: ($summary.workspace.name)"
            print $"  Path: ($summary.workspace.path)"
            print $"  Version: ($summary.workspace.version)"
            print $"  Schema Version: ($summary.workspace.schema_version)"
            print $"  Format Version: ($summary.workspace.format_version)"
            print $"  Created: ($summary.workspace.created)"
            print $"  Last Updated: ($summary.workspace.last_updated)"
            print ""
            print $"(ansi cyan)Compatibility:(ansi reset)"
            print $"  Compatible: ($summary.compatibility.compatible)"
            print $"  Reason: ($summary.compatibility.reason)"
            print $"  Message: ($summary.compatibility.message)"

            if ($summary.compatibility.requires_migration? | default false) {
                print $"  Requires Migration: (ansi yellow)Yes(ansi reset)"
            }

            print ""
            print $"(ansi cyan)Migrations:(ansi reset)"
            print $"  Total: ($summary.migrations.count)"

            if ($summary.migrations.last_migration != null) {
                let last = $summary.migrations.last_migration
                print $"  Last Migration:"
                print $"    From: ($last.from_version) → To: ($last.to_version)"
                print $"    Type: ($last.migration_type)"
                print $"    Time: ($last.timestamp)"
                print $"    Success: ($last.success)"
            }

            print ""
        }
    }
}

# Migrate workspace to newer version
export def "workspace migrate" [
    workspace_name?: string  # Workspace name (default: active workspace)
    --skip-backup (-s)       # Skip backup creation
    --force (-f)             # Force migration without confirmation
    --target-version: string # Target version (default: current system version)
] {
    use migration.nu *

    # Get workspace to migrate
    let ws_name = if ($workspace_name | is-not-empty) {
        $workspace_name
    } else {
        let active = (get-active-workspace)
        if ($active == null or ($active | is-empty)) {
            print $"(ansi red)No active workspace(ansi reset)"
            print $"(ansi yellow)Specify workspace name or activate a workspace first(ansi reset)"
            return
        }
        $active
    }

    # Execute migration
    let result = (migrate-workspace $ws_name --skip-backup=$skip_backup --force=$force --target-version=($target_version | default ""))

    if not $result.success {
        if ($result.cancelled? | default false) {
            return
        }

        print $"(ansi red)Migration failed(ansi reset)"

        if ($result.error | is-not-empty) {
            print $"Error: ($result.error)"
        }

        exit 1
    }

    if ($result.no_migration_needed? | default false) {
        print $"(ansi green)✓(ansi reset) ($result.message)"
        return
    }

    print $"(ansi green)Migration completed successfully(ansi reset)"
}

# Check workspace compatibility
export def "workspace check-compatibility" [
    workspace_name?: string  # Workspace name (default: active workspace)
] {
    use version.nu *

    # Get workspace to check
    let ws_name = if ($workspace_name | is-not-empty) {
        $workspace_name
    } else {
        let active = (get-active-workspace)
        if ($active == null or ($active | is-empty)) {
            print $"(ansi red)No active workspace(ansi reset)"
            print $"(ansi yellow)Specify workspace name or activate a workspace first(ansi reset)"
            return
        }
        $active
    }

    # Get workspace path
    let ws_path = (get-workspace-path $ws_name)

    if ($ws_path == null or not ($ws_path | path exists)) {
        print $"(ansi red)Workspace not found: ($ws_name)(ansi reset)"
        return
    }

    # Check compatibility
    let compatibility = (check-workspace-compatibility $ws_path)

    print ""
    print $"(ansi green_bold)Workspace Compatibility Check(ansi reset)"
    print ""
    print $"(ansi cyan)Workspace:(ansi reset) ($ws_name)"
    print $"(ansi cyan)Path:(ansi reset) ($ws_path)"
    print ""

    let status_color = if $compatibility.compatible { "green" } else { "red" }
    let status_icon = if $compatibility.compatible { "✓" } else { "✗" }

    print $"(ansi ($status_color))($status_icon) ($compatibility.message)(ansi reset)"
    print ""

    if not $compatibility.compatible {
        print $"(ansi yellow)Reason:(ansi reset) ($compatibility.reason)"

        if ($compatibility.requires_migration? | default false) {
            print ""
            print $"(ansi cyan)To fix this, run:(ansi reset)"
            print $"  provisioning workspace migrate ($ws_name)"
        } else if ($compatibility.requires_upgrade? | default false) {
            print ""
            print $"(ansi cyan)System or workspace needs upgrade(ansi reset)"
        }

        print ""
    }
}

# List workspace backups
export def "workspace list-backups" [
    workspace_name?: string  # Workspace name (default: active workspace)
] {
    use migration.nu *

    # Get workspace to check
    let ws_name = if ($workspace_name | is-not-empty) {
        $workspace_name
    } else {
        let active = (get-active-workspace)
        if ($active == null or ($active | is-empty)) {
            print $"(ansi red)No active workspace(ansi reset)"
            print $"(ansi yellow)Specify workspace name or activate a workspace first(ansi reset)"
            return
        }
        $active
    }

    let backups = (list-workspace-backups $ws_name)

    if ($backups | is-empty) {
        print $"(ansi yellow)No backups found for workspace '($ws_name)'(ansi reset)"
        return
    }

    print ""
    print $"(ansi green_bold)Workspace Backups for ($ws_name)(ansi reset)"
    print ""

    $backups | select name created reason size | table
}

# Restore workspace from backup
export def "workspace restore-backup" [
    backup_path: string  # Path to backup directory
    --force (-f)         # Force restore without confirmation
] {
    use migration.nu *

    let result = (restore-workspace-from-backup $backup_path --force=$force)

    if not $result.success {
        if ($result.cancelled? | default false) {
            return
        }

        print $"(ansi red)Restore failed(ansi reset)"

        if ($result.error | is-not-empty) {
            print $"Error: ($result.error)"
        }

        exit 1
    }
}
