# OCI CLI Commands
# User-facing commands for OCI artifact management
# Version: 1.0.0

use lib_provisioning/config/loader.nu [get-config]
# Selective oci client imports (ADR-025 Phase 3 Layer 2).
use lib_provisioning/oci/client.nu [
    build-artifact-ref get-oci-config is-oci-available load-oci-token
    oci-artifact-exists oci-delete-artifact oci-get-artifact-manifest
    oci-get-artifact-tags oci-list-artifacts oci-pull-artifact
    oci-push-artifact test-oci-connection
]
use std log
# Former duplicate `use ./client.nu *` removed — replaced by selective above.

# Pull OCI artifact to local cache
export def "oci pull" [
    artifact: string          # Format: name:version or registry/namespace/name:version
    --registry: string        # Override default registry
    --namespace: string = "provisioning-extensions"  # Override default namespace
    --destination: string     # Local path (default: workspace extensions)
    --insecure                # Skip TLS verification
] -> nothing {
    let config = (get-config)

    # Parse artifact reference
    let parts = ($artifact | split row ":")
    let artifact_name = ($parts | get 0)
    let version = ($parts | get 1? | default "latest")

    # Determine registry
    let reg = if ($registry | is-not-empty) {
        $registry
    } else if ($config.registry? | is-not-empty) {
        $config.registry.oci.endpoint
    } else {
        "localhost:5000"
    }

    # Determine destination
    let dest = if ($destination | is-not-empty) {
        $destination
    } else {
        let ws_extensions = ($config.paths.extensions | path join $artifact_name)
        mkdir $ws_extensions
        $ws_extensions
    }

    # Get authentication token if configured
    let auth_token = if ($config.registry?.oci?.auth_token_path? | is-not-empty) {
        open ($config.registry.oci.auth_token_path | path expand)
    } else {
        ""
    }

    print $"Pulling ($reg)/($namespace)/($artifact_name):($version)..."

    let result = (pull-artifact $reg $namespace $artifact_name $version $dest
                  --auth-token $auth_token
                  --insecure=$insecure)

    if $result {
        print $"✓ Successfully pulled ($artifact_name):($version) to ($dest)"
    } else {
        error make {
            msg: $"Failed to pull ($artifact_name):($version)"
        }
    }
}

# Push local extension as OCI artifact
export def "oci push" [
    source_path: string       # Local extension directory
    artifact_name: string     # Artifact name
    version: string           # Artifact version
    --registry: string        # Override default registry
    --namespace: string = "provisioning-extensions"
    --insecure
] -> nothing {
    let config = (get-config)

    # Validate source exists
    if not ($source_path | path exists) {
        error make {
            msg: $"Source path not found: ($source_path)"
        }
    }

    # Determine registry
    let reg = if ($registry | is-not-empty) {
        $registry
    } else if ($config.registry? | is-not-empty) {
        $config.registry.oci.endpoint
    } else {
        "localhost:5000"
    }

    # Get authentication token
    let auth_token = if ($config.registry?.oci?.auth_token_path? | is-not-empty) {
        open ($config.registry.oci.auth_token_path | path expand)
    } else {
        ""
    }

    print $"Pushing ($artifact_name):($version) to ($reg)/($namespace)..."

    let result = (push-artifact $source_path $reg $namespace $artifact_name $version
                  --auth-token $auth_token
                  --insecure=$insecure)

    if $result {
        print $"✓ Successfully pushed ($artifact_name):($version)"
        print $"  Reference: ($reg)/($namespace)/($artifact_name):($version)"
    } else {
        error make {
            msg: $"Failed to push ($artifact_name):($version)"
        }
    }
}

# List available artifacts in registry
export def "oci list" [
    --namespace: string = "provisioning-extensions"
    --registry: string
    --insecure
] -> table {
    let config = (get-config)

    let reg = if ($registry | is-not-empty) {
        $registry
    } else if ($config.registry? | is-not-empty) {
        $config.registry.oci.endpoint
    } else {
        "localhost:5000"
    }

    let auth_token = if ($config.registry?.oci?.auth_token_path? | is-not-empty) {
        open ($config.registry.oci.auth_token_path | path expand)
    } else {
        ""
    }

    print $"Listing artifacts in ($reg)/($namespace)..."

    let artifacts = (list-artifacts $reg $namespace
                     --auth-token $auth_token
                     --insecure=$insecure)

    if ($artifacts | is-empty) {
        print "No artifacts found"
        return []
    }

    # Format as table
    $artifacts | each { |artifact|
        {
            name: $artifact
            registry: $reg
            namespace: $namespace
            reference: $"($reg)/($namespace)/($artifact)"
        }
    }
}

# Search for artifacts matching query
export def "oci search" [
    query: string             # Search query (artifact name pattern)
    --namespace: string = "provisioning-extensions"
    --registry: string
    --insecure
] -> table {
    let artifacts = (oci list --namespace $namespace --registry $registry --insecure=$insecure)

    $artifacts | where name =~ $query
}

# Show artifact tags (versions)
export def "oci tags" [
    artifact_name: string     # Artifact name
    --namespace: string = "provisioning-extensions"
    --registry: string
    --insecure
] -> table {
    let config = (get-config)

    let reg = if ($registry | is-not-empty) {
        $registry
    } else if ($config.registry? | is-not-empty) {
        $config.registry.oci.endpoint
    } else {
        "localhost:5000"
    }

    let auth_token = if ($config.registry?.oci?.auth_token_path? | is-not-empty) {
        open ($config.registry.oci.auth_token_path | path expand)
    } else {
        ""
    }

    print $"Fetching tags for ($artifact_name)..."

    let tags = (get-artifact-tags $reg $namespace $artifact_name
                --auth-token $auth_token
                --insecure=$insecure)

    if ($tags | is-empty) {
        print $"No tags found for ($artifact_name)"
        return []
    }

    # Format as table with semantic version sorting
    $tags | each { |tag|
        {
            artifact: $artifact_name
            version: $tag
            reference: $"($reg)/($namespace)/($artifact_name):($tag)"
        }
    } | sort-by version --reverse
}

# Inspect artifact manifest
export def "oci inspect" [
    artifact: string          # Format: name:version
    --namespace: string = "provisioning-extensions"
    --registry: string
    --insecure
    --format: string = "yaml"  # Output format: yaml, json
] -> nothing {
    let config = (get-config)

    # Parse artifact reference
    let parts = ($artifact | split row ":")
    let artifact_name = ($parts | get 0)
    let version = ($parts | get 1? | default "latest")

    let reg = if ($registry | is-not-empty) {
        $registry
    } else if ($config.registry? | is-not-empty) {
        $config.registry.oci.endpoint
    } else {
        "localhost:5000"
    }

    let auth_token = if ($config.registry?.oci?.auth_token_path? | is-not-empty) {
        open ($config.registry.oci.auth_token_path | path expand)
    } else {
        ""
    }

    print $"Inspecting ($reg)/($namespace)/($artifact_name):($version)..."

    let manifest = (get-artifact-manifest $reg $namespace $artifact_name $version
                    --auth-token $auth_token
                    --insecure=$insecure)

    if ($manifest | is-empty) {
        error make {
            msg: $"Artifact not found or manifest unavailable"
        }
    }

    # Output in requested format
    match $format {
        "json" => { $manifest | to json }
        "yaml" => { $manifest | to yaml }
        _ => { $manifest }
    } | print
}

# Login to OCI registry
export def "oci login" [
    registry: string          # Registry endpoint
    --username: string = "_token"  # Username (default: _token)
    --password-stdin          # Read password from stdin
    --token-file: string      # Path to token file
] -> nothing {
    let password = if $password_stdin {
        input --suppress-output "Password: "
    } else if ($token_file | is-not-empty) {
        open ($token_file | path expand)
    } else {
        input --suppress-output "Password: "
    }

    # Use docker login for credential storage
    let result = (do {
        print $"Logging in to [$registry]..."
        echo $password | docker login $registry --username $username --password-stdin

        print $"✓ Successfully logged in to [$registry]"
        print $"  Credentials stored in docker config"
        "success"
    } | complete)

    if $result.exit_code != 0 {
        error make {
            msg: $"Failed to login to [$registry]: ($result.stderr)"
        }
    }
}

# Logout from OCI registry
export def "oci logout" [
    registry: string          # Registry endpoint
] -> nothing {
    let result = (do {
        docker logout $registry
        print $"✓ Logged out from [$registry]"
        "success"
    } | complete)

    if $result.exit_code != 0 {
        error make {
            msg: $"Failed to logout from [$registry]: ($result.stderr)"
        }
    }
}

# Delete artifact from registry
export def "oci delete" [
    artifact: string          # Format: name:version
    --namespace: string = "provisioning-extensions"
    --registry: string
    --insecure
    --force                   # Skip confirmation
] -> nothing {
    let config = (get-config)

    # Parse artifact reference
    let parts = ($artifact | split row ":")
    let artifact_name = ($parts | get 0)
    let version = ($parts | get 1? | default "latest")

    let reg = if ($registry | is-not-empty) {
        $registry
    } else if ($config.registry? | is-not-empty) {
        $config.registry.oci.endpoint
    } else {
        "localhost:5000"
    }

    let full_ref = $"($reg)/($namespace)/($artifact_name):($version)"

    # Confirm deletion unless --force
    if not $force {
        let confirm = (input $"Delete ($full_ref)? (y/N): ")
        if ($confirm | str downcase) != "y" {
            print "Deletion cancelled"
            return
        }
    }

    let auth_token = if ($config.registry?.oci?.auth_token_path? | is-not-empty) {
        open ($config.registry.oci.auth_token_path | path expand)
    } else {
        ""
    }

    print $"Deleting ($full_ref)..."

    let result = (delete-artifact $reg $namespace $artifact_name $version
                  --auth-token $auth_token
                  --insecure=$insecure)

    if $result {
        print $"✓ Successfully deleted ($full_ref)"
    } else {
        error make {
            msg: $"Failed to delete ($full_ref)"
        }
    }
}

# Copy artifact between registries
export def "oci copy" [
    source: string            # Format: [registry/namespace/]name:version
    destination: string       # Format: [registry/namespace/]name:version
    --insecure
] -> nothing {
    # Parse source
    let src_parts = ($source | split row "/")
    let src_registry = if ($src_parts | length) > 2 {
        $src_parts | get 0
    } else {
        "localhost:5000"
    }
    let src_namespace = if ($src_parts | length) > 2 {
        $src_parts | get 1
    } else {
        "provisioning-extensions"
    }
    let src_artifact = if ($src_parts | length) > 2 {
        $src_parts | get 2
    } else {
        $src_parts | get 0
    }

    let src_name_ver = ($src_artifact | split row ":")
    let src_name = ($src_name_ver | get 0)
    let src_version = ($src_name_ver | get 1? | default "latest")

    # Parse destination
    let dest_parts = ($destination | split row "/")
    let dest_registry = if ($dest_parts | length) > 2 {
        $dest_parts | get 0
    } else {
        "localhost:5000"
    }
    let dest_namespace = if ($dest_parts | length) > 2 {
        $dest_parts | get 1
    } else {
        "provisioning-extensions"
    }
    let dest_artifact = if ($dest_parts | length) > 2 {
        $dest_parts | get 2
    } else {
        $dest_parts | get 0
    }

    let dest_name_ver = ($dest_artifact | split row ":")
    let dest_name = ($dest_name_ver | get 0)
    let dest_version = ($dest_name_ver | get 1? | default $src_version)

    print $"Copying ($src_registry)/($src_namespace)/($src_name):($src_version)"
    print $"     to ($dest_registry)/($dest_namespace)/($dest_name):($dest_version)"

    let result = (copy-artifact $src_registry $src_namespace
                  $dest_registry $dest_namespace
                  $src_name $src_version
                  --insecure=$insecure)

    if $result {
        print $"✓ Successfully copied artifact"
    } else {
        error make {
            msg: "Failed to copy artifact"
        }
    }
}

# Show OCI configuration
export def "oci config" [] -> record {
    let config = (get-config)

    {
        tool: (detect-oci-tool)
        registry: ($config.registry?.oci?.endpoint? | default "localhost:5000")
        namespace: ($config.registry?.oci?.namespaces? | default {})
        cache_dir: ($env.HOME | path join ".provisioning" "oci-cache")
        tls_enabled: ($config.registry?.oci?.tls_enabled? | default false)
    }
}
