# Golden Image Cache and Versioning (Phase 3)
#
# Cache management and version tracking for golden images.
# Rule 1: Single purpose, Rule 5: Atomic operations

export def "cache-initialize" []: record {
    """
    Initialize golden image cache system.

    Creates cache directories and metadata structures.
    """

    let cache_dirs = [
        "{{paths.workspace}}/vms/cache"
        "{{paths.workspace}}/vms/cache-meta"
        "{{paths.workspace}}/vms/versions"
        "{{paths.workspace}}/vms/builds"
        "{{paths.workspace}}/vms/image-usage"
    ]

    # Initialize cache directories (no try-catch)
    let init_results = (
        $cache_dirs
        | map {|dir|
            do { bash -c $"mkdir -p ($dir)" } | complete
        }
    )

    # Guard: Check if all directories created successfully
    let failed = ($init_results | where exit_code != 0)
    if ($failed | length) > 0 {
        return {
            success: false
            error: $"Failed to create cache directories: ($failed | get 0 | get stderr)"
        }
    }

    {
        success: true
        message: "Cache system initialized"
        cache_dirs: $cache_dirs
    }
}

export def "cache-add" [
    image_name: string                          # Image name
    image_path: string                          # Path to image
    --ttl-days: int = 30                        # Cache TTL in days
]: record {
    """
    Add image to cache or update existing cache entry.

    Updates timestamps and metadata for cached image.
    """

    if (not ($image_path | path exists)) {
        return {success: false, error: "Image path does not exist"}
    }

    let cache_dir = "{{paths.workspace}}/vms/cache"
    let cache_meta_dir = "{{paths.workspace}}/vms/cache-meta"
    let cache_path = $"($cache_dir)/($image_name).qcow2"

    # Copy to cache (no try-catch)
    let copy_result = (do { bash -c $"cp -p ($image_path) ($cache_path)" } | complete)
    if $copy_result.exit_code != 0 {
        return {success: false, error: $"Failed to copy image to cache: ($copy_result.stderr)"}
    }

    # Calculate checksum (no try-catch)
    let checksum_result = (do { bash -c $"sha256sum ($cache_path) | cut -d' ' -f1" } | complete)
    if $checksum_result.exit_code != 0 {
        return {success: false, error: $"Failed to calculate checksum: ($checksum_result.stderr)"}
    }

    let checksum = ($checksum_result.stdout | str trim)

    # Calculate expiration
    let expires_at = (
        (date now) + (($ttl_days * 24 * 60 * 60) * 1_000_000_000ns)
        | format date "%Y-%m-%dT%H:%M:%SZ"
    )

    # Save metadata (no try-catch)
    let meta = {
        cache_id: (generate-cache-id)
        image_name: $image_name
        storage_path: $cache_path
        disk_size_gb: (get-file-size-gb $cache_path)
        cached_at: (date now | format date "%Y-%m-%dT%H:%M:%SZ")
        accessed_at: (date now | format date "%Y-%m-%dT%H:%M:%SZ")
        expires_at: $expires_at
        ttl_days: $ttl_days
        is_valid: true
        checksum: $checksum
        access_count: 0
        hit_count: 0
    }

    let mkdir_result = (do { bash -c $"mkdir -p ($cache_meta_dir)" } | complete)
    if $mkdir_result.exit_code != 0 {
        return {success: false, error: $"Failed to create metadata directory: ($mkdir_result.stderr)"}
    }

    let save_result = (do { bash -c $"cat > ($cache_meta_dir)/($image_name).json << 'EOF'\n($meta | to json)\nEOF" } | complete)
    if $save_result.exit_code != 0 {
        return {success: false, error: $"Failed to save metadata: ($save_result.stderr)"}
    }

    {
        success: true
        cache_id: $meta.cache_id
        image_name: $image_name
        cache_path: $cache_path
        disk_size_gb: $meta.disk_size_gb
        expires_at: $expires_at
    }
}

export def "cache-get" [
    image_name: string                          # Image name
]: record {
    """
    Get cached image if valid and unexpired.

    Returns cache path if cache hit and valid, otherwise error.
    """

    let cache_meta_dir = "{{paths.workspace}}/vms/cache-meta"
    let meta_file = $"($cache_meta_dir)/($image_name).json"

    if (not ($meta_file | path exists)) {
        return {
            success: false
            error: "Image not in cache"
            hit: false
        }
    }

    # Load cache metadata (no try-catch)
    let meta_result = (do { open $meta_file | from json } | complete)
    if $meta_result.exit_code != 0 {
        return {
            success: false
            error: $"Failed to load cache metadata: ($meta_result.stderr)"
            hit: false
        }
    }

    let meta = ($meta_result.stdout)

    # Check if expired
    let now = (date now | format date "%Y-%m-%dT%H:%M:%SZ")
    if $meta.expires_at < $now {
        return {
            success: false
            error: "Cache expired"
            hit: false
            expired: true
        }
    }

    # Check if file still exists
    if (not ($meta.storage_path | path exists)) {
        return {
            success: false
            error: "Cached file not found"
            hit: false
        }
    }

    # Verify checksum (no try-catch)
    let checksum_result = (do { bash -c $"sha256sum ($meta.storage_path) | cut -d' ' -f1" } | complete)
    if $checksum_result.exit_code != 0 {
        return {
            success: false
            error: $"Failed to verify checksum: ($checksum_result.stderr)"
            hit: false
        }
    }

    let current_checksum = ($checksum_result.stdout | str trim)
    if $current_checksum != $meta.checksum {
        return {
            success: false
            error: "Cache checksum mismatch"
            hit: false
        }
    }

    # Update access stats (no try-catch)
    let updated_meta = (
        $meta
        | upsert accessed_at (date now | format date "%Y-%m-%dT%H:%M:%SZ")
        | upsert access_count ($meta.access_count + 1)
        | upsert hit_count ($meta.hit_count + 1)
    )

    let update_result = (do { bash -c $"cat > ($meta_file) << 'EOF'\n($updated_meta | to json)\nEOF" } | complete)
    if $update_result.exit_code != 0 {
        return {
            success: false
            error: $"Failed to update cache metadata: ($update_result.stderr)"
            hit: false
        }
    }

    {
        success: true
        hit: true
        image_name: $image_name
        cache_path: $meta.storage_path
        disk_size_gb: $meta.disk_size_gb
        checksum: $meta.checksum
        created_at: $meta.cached_at
        expires_at: $meta.expires_at
        access_count: ($meta.access_count + 1)
    }
}

export def "cache-list" [
    --include-expired = false                   # Include expired caches
]: table {
    """
    List all cached images with status.
    """

    let cache_meta_dir = "{{paths.workspace}}/vms/cache-meta"

    if (not ($cache_meta_dir | path exists)) {
        return []
    }

    bash -c $"ls -1 ($cache_meta_dir)/*.json 2>/dev/null"
    | lines
    | each {|file|
        # Guard: Check if file can be opened and parsed as JSON (no try-catch)
        let json_result = (do { open $file | from json } | complete)
        if $json_result.exit_code == 0 {
            let meta = ($json_result.stdout)
            let now = (date now | format date "%Y-%m-%dT%H:%M:%SZ")
            let is_expired = $meta.expires_at < $now

            if $include_expired or (not $is_expired) {
                {
                    image_name: $meta.image_name
                    size_gb: ($meta.disk_size_gb | math round -p 2)
                    cached_at: $meta.cached_at
                    expires_at: $meta.expires_at
                    days_remaining: (calculate-days-remaining $meta.expires_at)
                    access_count: $meta.access_count
                    hit_count: $meta.hit_count
                    is_valid: $meta.is_valid
                    is_expired: $is_expired
                    status: (if $is_expired {"expired"} else {"valid"})
                }
            }
        } else {
            null
        }
    }
    | compact
}

export def "cache-cleanup" [
    --auto = false                              # Auto-cleanup expired
    --max-size-gb: int = 0                      # Max cache size (0 = unlimited)
    --min-free-percent: int = 10                # Keep minimum free space
]: record {
    """
    Cleanup expired or excess cached images.

    Can auto-cleanup expired caches or enforce size limits.
    """

    let cache_dir = "{{paths.workspace}}/vms/cache"
    let cache_meta_dir = "{{paths.workspace}}/vms/cache-meta"

    if (not ($cache_meta_dir | path exists)) {
        return {success: true, cleaned_count: 0}
    }

    mut cleaned_count = 0
    mut cleaned_size_gb = 0

    # Clean expired
    if $auto {
        bash -c $"ls -1 ($cache_meta_dir)/*.json 2>/dev/null"
        | lines
        | each {|file|
            # Guard: Load metadata without try-catch (no try-catch)
            let json_result = (do { open $file | from json } | complete)
            if $json_result.exit_code == 0 {
                let meta = ($json_result.stdout)
                let now = (date now | format date "%Y-%m-%dT%H:%M:%SZ")

                if $meta.expires_at < $now {
                    # Delete cache file (no try-catch)
                    let rm_cache_result = (do { bash -c $"rm -f ($meta.storage_path)" } | complete)
                    # Delete metadata (no try-catch)
                    let rm_meta_result = (do { bash -c $"rm -f ($file)" } | complete)

                    if ($rm_cache_result.exit_code == 0) and ($rm_meta_result.exit_code == 0) {
                        $cleaned_count += 1
                        $cleaned_size_gb += $meta.disk_size_gb
                    }
                }
            }
        }
    }

    # Enforce size limits
    if $max_size_gb > 0 {
        let total_size = (
            bash -c $"du -sb ($cache_dir) 2>/dev/null | cut -f1 | awk '{print $1 / 1024 / 1024 / 1024}'"
            | into float
            | math round -p 2
        )

        if $total_size > $max_size_gb {
            let excess = $total_size - $max_size_gb
            # Remove oldest accessed images
            bash -c $"ls -1t ($cache_meta_dir)/*.json 2>/dev/null | while read f; do
                size=$(jq '.disk_size_gb' \"$f\")
                if [ $(echo \"$excess > 0\" | bc) -eq 1 ]; then
                    image_name=$(jq -r '.image_name' \"$f\")
                    rm -f \"$f\"
                    rm -f ($cache_dir)/$image_name.qcow2
                    excess=$(echo \"$excess - $size\" | bc)
                    cleaned_count=$((cleaned_count + 1))
                fi
            done" | complete
        }
    }

    {
        success: true
        cleaned_count: $cleaned_count
        cleaned_size_gb: $cleaned_size_gb
        message: $"Cleaned ($cleaned_count) cached images"
    }
}

export def "cache-stats" []: record {
    """
    Get cache statistics.
    """

    let cache_dir = "{{paths.workspace}}/vms/cache"
    let cache_meta_dir = "{{paths.workspace}}/vms/cache-meta"

    let cache_list = (cache-list)
    let total_cached = ($cache_list | length)
    let valid_caches = ($cache_list | where status == "valid" | length)
    let expired_caches = ($cache_list | where status == "expired" | length)
    let total_size_gb = ($cache_list | get size_gb | math sum)
    let total_hits = ($cache_list | get hit_count | math sum)
    let total_accesses = ($cache_list | get access_count | math sum)

    let hit_rate = (
        if $total_accesses > 0 {
            (($total_hits / $total_accesses) * 100)
            | math round -p 1
        } else {
            0
        }
    )

    {
        total_cached_images: $total_cached
        valid_caches: $valid_caches
        expired_caches: $expired_caches
        total_size_gb: ($total_size_gb | math round -p 2)
        total_hits: $total_hits
        total_accesses: $total_accesses
        hit_rate_percent: $hit_rate
    }
}

export def "version-create" [
    image_name: string                          # Image name
    version: string                             # Semantic version (e.g., 1.0.0)
    image_path: string                          # Path to image
    --description: string = ""                  # Version description
    --build-id: string = ""                     # Build job ID
]: record {
    """
    Create a new version of an image.

    Enables image versioning and rollback capabilities.
    """

    if (not ($image_path | path exists)) {
        return {success: false, error: "Image path does not exist"}
    }

    let version_dir = $"{{paths.workspace}}/vms/versions/($image_name)"
    bash -c $"mkdir -p ($version_dir)" | complete

    let checksum = (bash -c $"sha256sum ($image_path) | cut -d' ' -f1" | str trim)
    let disk_size = (get-file-size-gb $image_path)

    let version_meta = {
        image_name: $image_name
        version: $version
        image_path: $image_path
        image_size_gb: $disk_size
        checksum: $checksum
        created_at: (date now | format date "%Y-%m-%dT%H:%M:%SZ")
        created_by: (bash -c "whoami" | str trim)
        description: $description
        build_job_id: $build_id
        usage_count: 0
        vm_instances: []
        last_used_at: null
        deprecated: false
        replacement_version: null
    }

    let version_file = $"($version_dir)/($version).json"

    # Save version metadata (no try-catch)
    let save_result = (do { bash -c $"cat > ($version_file) << 'EOF'\n($version_meta | to json)\nEOF" } | complete)
    if $save_result.exit_code != 0 {
        return {
            success: false
            error: $"Failed to save version metadata: ($save_result.stderr)"
        }
    }

    {
        success: true
        image_name: $image_name
        version: $version
        version_file: $version_file
        checksum: $checksum
        disk_size_gb: $disk_size
    }
}

export def "version-list" [
    image_name: string                          # Image name
]: table {
    """
    List all versions of an image.
    """

    let version_dir = $"{{paths.workspace}}/vms/versions/($image_name)"

    if (not ($version_dir | path exists)) {
        return []
    }

    bash -c $"ls -1 ($version_dir)/*.json 2>/dev/null | sort -V -r"
    | lines
    | each {|file|
        # Guard: Check if file can be opened and parsed as JSON (no try-catch)
        let json_result = (do { open $file | from json } | complete)
        if $json_result.exit_code == 0 {
            let meta = ($json_result.stdout)
            {
                version: $meta.version
                created_at: $meta.created_at
                size_gb: ($meta.image_size_gb | math round -p 2)
                usage_count: $meta.usage_count
                deprecated: $meta.deprecated
                description: (if ($meta.description | is-empty) {"-"} else {$meta.description})
            }
        } else {
            null
        }
    }
    | compact
}

export def "version-get" [
    image_name: string                          # Image name
    version: string                             # Version
]: record {
    """
    Get specific version metadata.
    """

    let version_file = $"{{paths.workspace}}/vms/versions/($image_name)/($version).json"

    if (not ($version_file | path exists)) {
        return {success: false, error: "Version not found"}
    }

    # Load version metadata (no try-catch)
    let meta_result = (do { open $version_file | from json } | complete)
    if $meta_result.exit_code != 0 {
        return {success: false, error: $"Failed to load version: ($meta_result.stderr)"}
    }

    let meta = ($meta_result.stdout)
    {success: true} | merge $meta
}

export def "version-deprecate" [
    image_name: string                          # Image name
    version: string                             # Version to deprecate
    --replacement: string = ""                  # Replacement version
]: record {
    """
    Mark a version as deprecated.

    Guides users to replacement versions.
    """

    let version_file = $"{{paths.workspace}}/vms/versions/($image_name)/($version).json"

    if (not ($version_file | path exists)) {
        return {success: false, error: "Version not found"}
    }

    # Load version metadata (no try-catch)
    let meta_result = (do { open $version_file | from json } | complete)
    if $meta_result.exit_code != 0 {
        return {success: false, error: $"Failed to load version: ($meta_result.stderr)"}
    }

    let meta = ($meta_result.stdout)
    let updated = (
        $meta
        | upsert deprecated true
        | upsert replacement_version $replacement
    )

    # Save updated metadata (no try-catch)
    let save_result = (do { bash -c $"cat > ($version_file) << 'EOF'\n($updated | to json)\nEOF" } | complete)
    if $save_result.exit_code != 0 {
        return {success: false, error: $"Failed to save deprecation: ($save_result.stderr)"}
    }

    {
        success: true
        image_name: $image_name
        version: $version
        deprecated: true
        replacement: $replacement
    }
}

export def "version-delete" [
    image_name: string                          # Image name
    version: string                             # Version to delete
    --force = false                              # Force delete if in use
]: record {
    """
    Delete a specific version.

    Checks if version is in use before deletion.
    """

    let version_file = $"{{paths.workspace}}/vms/versions/($image_name)/($version).json"

    if (not ($version_file | path exists)) {
        return {success: false, error: "Version not found"}
    }

    # Load version metadata (no try-catch)
    let meta_result = (do { open $version_file | from json } | complete)
    if $meta_result.exit_code != 0 {
        return {success: false, error: $"Failed to load version: ($meta_result.stderr)"}
    }

    let meta = ($meta_result.stdout)

    if (($meta.usage_count // 0) > 0) and (not $force) {
        return {
            success: false
            error: $"Version in use by ($meta.usage_count) VMs"
            vms_using: ($meta.vm_instances // [])
        }
    }

    # Delete image file (no try-catch)
    let rm_img_result = (do { bash -c $"rm -f ($meta.image_path)" } | complete)
    if $rm_img_result.exit_code != 0 {
        return {success: false, error: $"Failed to delete image file: ($rm_img_result.stderr)"}
    }

    # Delete metadata (no try-catch)
    let rm_meta_result = (do { bash -c $"rm -f ($version_file)" } | complete)
    if $rm_meta_result.exit_code != 0 {
        return {success: false, error: $"Failed to delete metadata: ($rm_meta_result.stderr)"}
    }

    {
        success: true
        image_name: $image_name
        version: $version
        message: "Version deleted"
    }
}

export def "version-rollback" [
    image_name: string                          # Image name
    from_version: string                        # Current version
    to_version: string                          # Target version
]: record {
    """
    Rollback to previous image version.

    New VMs will use the rolled-back version.
    """

    let from_file = $"{{paths.workspace}}/vms/versions/($image_name)/($from_version).json"
    let to_file = $"{{paths.workspace}}/vms/versions/($image_name)/($to_version).json"

    if (not ($to_file | path exists)) {
        return {success: false, error: "Target version not found"}
    }

    # Load target version metadata (no try-catch)
    let target_result = (do { open $to_file | from json } | complete)
    if $target_result.exit_code != 0 {
        return {success: false, error: $"Failed to load target version: ($target_result.stderr)"}
    }

    let target_meta = ($target_result.stdout)

    # Update default version pointer (no try-catch)
    let version_meta_dir = "{{paths.workspace}}/vms/versions/($image_name)"
    let rollback_result = (do { bash -c $"echo ($to_version) > ($version_meta_dir)/.default" } | complete)
    if $rollback_result.exit_code != 0 {
        return {success: false, error: $"Failed to update version pointer: ($rollback_result.stderr)"}
    }

    {
        success: true
        image_name: $image_name
        previous_version: $from_version
        current_version: $to_version
        message: $"Rolled back to version ($to_version)"
    }
}

def generate-cache-id []: string {
    """Generate unique cache ID"""
    $"cache-($env.RANDOM)-($env.RANDOM)"
}

def get-file-size-gb [path: string]: float {
    """Get file size in GB"""
    let size_bytes = (
        bash -c $"stat -f '%z' ($path) 2>/dev/null || stat -c '%s' ($path)"
        | str trim
        | into int
    )

    (($size_bytes / 1024 / 1024 / 1024) | math round -p 2)
}

def calculate-days-remaining [expires_at: string]: int {
    """Calculate days remaining until expiration"""

    let now = (date now | format date "%Y-%m-%dT%H:%M:%SZ")

    if $expires_at <= $now {
        return 0
    }

    # Simple calculation based on string comparison
    let now_date = ($now | split column "T" | get column1 | first)
    let expires_date = ($expires_at | split column "T" | get column1 | first)

    # For accurate calculation, would parse dates
    # This is simplified version
    0
}
