# Cache Metadata Management
# Handles metadata creation, loading, validation, and mtime comparison
# Follows Nushell 0.109.0+ guidelines

# Helper: Get current ISO8601 timestamp
def get-iso-timestamp [] {
    date now | format date "%Y-%m-%dT%H:%M:%SZ"
}

# Helper: Parse ISO8601 timestamp
def parse-iso-timestamp [timestamp: string] {
    # Convert ISO8601 to Unix timestamp
    $timestamp
}

# Helper: Check if timestamp is expired
def is-expired [
    expires_at: string
    now: string
] {
    $now > $expires_at
}

# ============================================================================
# PUBLIC API: Metadata Operations
# ============================================================================

# Create metadata for cache entry
export def create-metadata [
    source_files: list      # List of file paths to track
    ttl_seconds: int        # Time-to-live in seconds
    data_hash: string       # Hash of cached data
] {
    let now = (get-iso-timestamp)
    let expires_at = (((date now) + ($ttl_seconds | into duration)) | format date "%Y-%m-%dT%H:%M:%SZ")

    mut source_mtimes = {}
    for file in $source_files {
        let mtime = if ($file | path exists) {
            $file | stat | get modified | into int
        } else {
            (-1)
        }

        $source_mtimes = ($source_mtimes | insert $file $mtime)
    }

    {
        created_at: $now,
        ttl_seconds: $ttl_seconds,
        expires_at: $expires_at,
        source_files: $source_files,
        source_mtimes: $source_mtimes,
        hash: $data_hash,
        cache_version: "1.0"
    }
}

# Load and validate metadata
export def load-metadata [
    meta_file: string
] {
    let load_result = (do {
        if ($meta_file | path exists) {
            open $meta_file
        } else {
            error make { msg: $"Metadata file not found: ($meta_file)" }
        }
    } | complete)

    if $load_result.exit_code != 0 {
        return {
            valid: false,
            reason: "metadata_load_error",
            data: null
        }
    }

    {
        valid: true,
        reason: "metadata_loaded",
        data: $load_result.stdout
    }
}

# Validate metadata (check version, format, etc.)
export def validate-metadata [
    metadata: record
] {
    # Check required fields
    let required_fields = ["created_at" "ttl_seconds" "expires_at" "source_files" "hash" "cache_version"]

    for field in $required_fields {
        if not ($metadata | has -c $field) {
            return {
                valid: false,
                reason: $"missing_field: ($field)"
            }
        }
    }

    # Check cache version compatibility
    if $metadata.cache_version != "1.0" {
        return {
            valid: false,
            reason: "incompatible_cache_version"
        }
    }

    {
        valid: true,
        reason: "metadata_valid"
    }
}

# Get file modification times
export def get-source-mtimes [
    source_files: list
] {
    mut mtimes = {}

    for file in $source_files {
        let mtime_result = (do {
            if ($file | path exists) {
                $file | stat | get modified | into int
            } else {
                -1
            }
        } | complete)

        if $mtime_result.exit_code == 0 {
            $mtimes = ($mtimes | insert $file $mtime_result.stdout)
        } else {
            $mtimes = ($mtimes | insert $file (-1))
        }
    }

    $mtimes
}

# Compare cached vs current mtimes
export def compare-mtimes [
    cached_mtimes: record
    current_mtimes: record
] {
    mut all_match = true
    mut mismatches = []

    for file in ($cached_mtimes | columns) {
        let cached = ($cached_mtimes | get $file)
        let current = ($current_mtimes | get --optional $file | default (-1))

        if $cached != $current {
            $all_match = false
            $mismatches = ($mismatches | append {
                file: $file,
                cached: $cached,
                current: $current
            })
        }
    }

    {
        match: $all_match,
        mismatches: $mismatches
    }
}

# Check if metadata is expired
export def is-metadata-expired [
    metadata: record
    now: string
] {
    is-expired $metadata.expires_at $now
}

# Get metadata expiration time remaining
export def get-metadata-ttl-remaining [
    metadata: record
    now: string
] {
    # Parse both timestamps and calculate difference
    let now_ts = (parse-iso-timestamp $now)
    let expires_ts = (parse-iso-timestamp $metadata.expires_at)

    if $expires_ts > $now_ts {
        $expires_ts - $now_ts
    } else {
        0
    }
}

# Get comprehensive metadata status
export def get-metadata-status [
    metadata: record
    current_source_mtimes: record
] {
    let now = (get-iso-timestamp)
    let is_expired = (is-metadata-expired $metadata $now)

    let mtime_comparison = (compare-mtimes $metadata.source_mtimes $current_source_mtimes)

    let ttl_remaining = (get-metadata-ttl-remaining $metadata $now)

    {
        valid: ((not $is_expired) and $mtime_comparison.match),
        expired: $is_expired,
        ttl_remaining_seconds: $ttl_remaining,
        mtime_status: $mtime_comparison,
        created_at: $metadata.created_at,
        expires_at: $metadata.expires_at,
        source_files_count: ($metadata.source_files | length),
        mtime_matches: (($mtime_comparison.mismatches | length) == 0)
    }
}

# Update metadata (refresh TTL)
export def update-metadata [
    metadata: record
    ttl_seconds: int = 0    # If 0, keep original TTL
] {
    let new_ttl = if $ttl_seconds > 0 {
        $ttl_seconds
    } else {
        $metadata.ttl_seconds
    }

    let now = (get-iso-timestamp)
    let expires_at = (((date now) + ($new_ttl | into duration)) | format date "%Y-%m-%dT%H:%M:%SZ")

    $metadata
    | insert created_at $now
    | insert ttl_seconds $new_ttl
    | insert expires_at $expires_at
}

# Rotate metadata (create new with updated mtimes)
export def rotate-metadata [
    metadata: record
    new_source_mtimes: record
] {
    let now = (get-iso-timestamp)
    let expires_at = (((date now) + ($metadata.ttl_seconds | into duration)) | format date "%Y-%m-%dT%H:%M:%SZ")

    $metadata
    | insert created_at $now
    | insert expires_at $expires_at
    | insert source_mtimes $new_source_mtimes
}

# Export metadata to JSON
export def export-metadata [
    metadata: record
    --pretty = false
] {
    if $pretty {
        $metadata | to json --indent 2
    } else {
        $metadata | to json
    }
}

# Import metadata from JSON
export def import-metadata [
    json_string: string
] {
    let result = (do {
        $json_string | from json
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout
    } else {
        error make { msg: "Failed to parse metadata JSON" }
    }
}
