# OCI Registry Service Integration

use ../config/loader.nu get-config

# Start registry service
export def start-oci-registry [
    registry_type: string = "zot"
    config_path?: string
] -> bool {
    print $"Starting OCI registry service \(($registry_type)\)..."

    let registry_dir = get-registry-directory $registry_type

    if not ($registry_dir | path exists) {
        print $"ERROR: Registry directory not found: ($registry_dir)"
        return false
    }

    cd $registry_dir

    let compose_file = if ($config_path | is-empty) {
        "docker-compose.yml"
    } else {
        $config_path
    }

    let result = (^docker-compose -f $compose_file up -d | complete)

    if $result.exit_code == 0 {
        print "✅ Registry service started"
        return true
    } else {
        print $"ERROR: Failed to start registry: ($result.stderr)"
        return false
    }
}

# Stop registry service
export def stop-oci-registry [
    registry_type: string = "zot"
] -> bool {
    print $"Stopping OCI registry service \(($registry_type)\)..."

    let registry_dir = get-registry-directory $registry_type

    if not ($registry_dir | path exists) {
        print $"ERROR: Registry directory not found: ($registry_dir)"
        return false
    }

    cd $registry_dir

    let result = (^docker-compose down | complete)

    if $result.exit_code == 0 {
        print "✅ Registry service stopped"
        return true
    } else {
        print $"ERROR: Failed to stop registry: ($result.stderr)"
        return false
    }
}

# Get registry status
export def get-oci-registry-status [
    registry_type: string = "zot"
] -> record {
    let registry_dir = get-registry-directory $registry_type

    if not ($registry_dir | path exists) {
        return {
            running: false
            error: "Registry directory not found"
        }
    }

    cd $registry_dir

    let result = (^docker-compose ps --format json | complete)

    if $result.exit_code != 0 {
        return {
            running: false
            error: $result.stderr
        }
    }

    let containers = ($result.stdout | from json)
    let running = ($containers | all { |c| $c.State == "running" })

    {
        running: $running
        containers: $containers
        type: $registry_type
    }
}

# Check registry health
export def check-oci-registry-health [
    registry_url: string
] -> bool {
    let result = (do {
        http get $"http://($registry_url)/v2/" --timeout 5sec
    } | complete)

    $result.exit_code == 0
}

# Get registry info
export def get-oci-registry-info [
    registry_url: string
] -> record {
    # Try to fetch catalog
    let catalog_result = (do {
        http get $"http://($registry_url)/v2/_catalog"
    } | complete)

    let catalog = if $catalog_result.exit_code == 0 {
        $catalog_result.stdout | from json
    } else {
        {repositories: []}
    }

    # Count namespaces
    let namespaces = ($catalog.repositories
        | each { |r| $r | split row "/" | first }
        | uniq
        | length)

    {
        url: $registry_url
        healthy: ($catalog_result.exit_code == 0)
        repositories: ($catalog.repositories | length)
        namespaces: $namespaces
        timestamp: (date now | format date "%Y-%m-%d %H:%M:%S")
    }
}

# Get repository list
export def get-oci-registry-repositories [
    registry_url: string
] -> list {
    let result = (do {
        http get $"http://($registry_url)/v2/_catalog"
    } | complete)

    if $result.exit_code != 0 {
        return []
    }

    let catalog = ($result.stdout | from json)
    $catalog.repositories
}

# Get repository tags
export def get-oci-repository-tags [
    registry_url: string
    repository: string
] -> list {
    let result = (do {
        http get $"http://($registry_url)/v2/($repository)/tags/list"
    } | complete)

    if $result.exit_code != 0 {
        return []
    }

    let tags = ($result.stdout | from json)
    $tags.tags | default []
}

# Get manifest for image
export def get-oci-image-manifest [
    registry_url: string
    repository: string
    tag: string
] -> record {
    let result = (do {
        http get $"http://($registry_url)/v2/($repository)/manifests/($tag)" --headers {
            "Accept": "application/vnd.oci.image.manifest.v1+json"
        }
    } | complete)

    if $result.exit_code != 0 {
        return {}
    }

    $result.stdout | from json
}

# Delete image tag
export def delete-oci-image-tag [
    registry_url: string
    repository: string
    tag: string
] -> bool {
    # First get the manifest digest
    let manifest_result = (do {
        http get $"http://($registry_url)/v2/($repository)/manifests/($tag)" --headers {
            "Accept": "application/vnd.oci.image.manifest.v1+json"
        } --full
    } | complete)

    if $manifest_result.exit_code != 0 {
        print $"ERROR: Failed to get manifest: ($manifest_result.stderr)"
        return false
    }

    let manifest = ($manifest_result.stdout | from json)
    let digest = ($manifest.headers | where name == "Docker-Content-Digest" | first | get value)

    # Delete using digest
    let delete_result = (do {
        http delete $"http://($registry_url)/v2/($repository)/manifests/($digest)"
    } | complete)

    if $delete_result.exit_code == 0 {
        print $"✅ Image ($repository):($tag) deleted"
        return true
    } else {
        print $"ERROR: Failed to delete image: ($delete_result.stderr)"
        return false
    }
}

# Garbage collection (Zot)
export def run-oci-registry-gc [
    registry_type: string = "zot"
] -> bool {
    match $registry_type {
        "zot" => {
            # Zot runs GC automatically based on config
            print "ℹ Zot runs garbage collection automatically"
            print "  Check config.json for GC settings"
            return true
        }
        "distribution" => {
            # Distribution requires manual GC
            print "Running garbage collection..."

            let registry_dir = get-registry-directory $registry_type

            let result = (^docker-compose exec registry \
                registry garbage-collect /etc/docker/registry/config.yml | complete)

            if $result.exit_code == 0 {
                print "✅ Garbage collection completed"
                return true
            } else {
                print $"ERROR: GC failed: ($result.stderr)"
                return false
            }
        }
        "harbor" => {
            print "ℹ Harbor runs GC via UI or API"
            print "  Use Harbor admin interface for GC"
            return true
        }
        _ => {
            print $"ERROR: Unknown registry type: ($registry_type)"
            return false
        }
    }
}

# Get registry metrics (if available)
export def get-oci-registry-metrics [
    registry_url: string
    registry_type: string = "zot"
] -> string {
    let metrics_url = match $registry_type {
        "zot" => $"http://($registry_url)/metrics"
        "distribution" => $"http://($registry_url):5001/metrics"
        _ => null
    }

    if ($metrics_url | is-empty) {
        return "Metrics not available for this registry type"
    }

    let result = (do {
        http get $metrics_url
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout
    } else {
        $"ERROR: Failed to fetch metrics: ($result.stderr)"
    }
}

# Helper: Get registry directory
def get-registry-directory [registry_type: string] -> string {
    let config = (get-config)
    let base_path = ($config | get paths.base)
    $"($base_path)/provisioning/platform/oci-registry/($registry_type)"
}

# Push artifact to registry
export def push-oci-artifact [
    registry_url: string
    repository: string
    tag: string
    artifact_path: string
] -> bool {
    if not ($artifact_path | path exists) {
        print $"ERROR: Artifact not found: ($artifact_path)"
        return false
    }

    # This would require oras or docker buildx
    print "ℹ Use 'oras push' or 'docker push' to upload artifacts"
    print $"  Target: ($registry_url)/($repository):($tag)"
    print $"  Artifact: ($artifact_path)"

    false
}

# Pull artifact from registry
export def pull-oci-artifact [
    registry_url: string
    repository: string
    tag: string
    output_path: string
] -> bool {
    # This would require oras or docker pull
    print "ℹ Use 'oras pull' or 'docker pull' to download artifacts"
    print $"  Source: ($registry_url)/($repository):($tag)"
    print $"  Output: ($output_path)"

    false
}
