# Grace Period Checker - Validates cache freshness
# Prevents excessive API calls by checking grace periods

# Check if cache entry is still valid (within grace period)
export def is-cache-valid? [
    component: string       # Component name
    cache_type: string     # "infra" or "provisioning"
] {
    let cache_path = if $cache_type == "infra" {
        get-infra-cache-path
    } else {
        get-provisioning-cache-path
    }

    let cache_file = ($cache_path | path join "versions.json")

    if not ($cache_file | path exists) {
        return false
    }

    let result = (do { open $cache_file } | complete)
    if $result.exit_code != 0 {
        return false
    }

    let cache_data = ($result.stdout | from json)
    let vd_result = (do { $cache_data | get $component } | complete)
    let version_data = if $vd_result.exit_code == 0 { $vd_result.stdout } else { {} }

    if ($version_data | is-empty) {
        return false
    }

    let ca_result = (do { $version_data | get cached_at } | complete)
    let cached_at = if $ca_result.exit_code == 0 { $ca_result.stdout } else { "" }
    let gp_result = (do { $version_data | get grace_period } | complete)
    let grace_period = if $gp_result.exit_code == 0 { $gp_result.stdout } else { (get-default-grace-period) }

    if ($cached_at | is-empty) {
        return false
    }

    # Parse cached timestamp
    let parse_date = (do { $cached_at | into datetime } | complete)
    if $parse_date.exit_code != 0 {
        return false
    }

    let cached_time = $parse_date.stdout
    let current_time = (date now)
    let age_seconds = (($current_time - $cached_time) / 1sec)

    # Check if within grace period
    $age_seconds < $grace_period
}

# Get expired cache entries
export def get-expired-entries [
    cache_type: string     # "infra" or "provisioning"
] {
    let cache_path = if $cache_type == "infra" {
        get-infra-cache-path
    } else {
        get-provisioning-cache-path
    }

    let cache_file = ($cache_path | path join "versions.json")

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

    let result = (do { open $cache_file } | complete)
    if $result.exit_code != 0 {
        return []
    }

    let cache_data = ($result.stdout | from json)

    $cache_data | columns | where { |component|
        not (is-cache-valid? $component $cache_type)
    }
}

# Get components that need update check (check_latest = true and expired)
export def get-components-needing-update [] {
    let components = []

    # Check infra cache
    let infra_expired = (get-expired-entries "infra")
    let infra_check_latest = (get-check-latest-components "infra")
    let infra_needs_update = ($infra_expired | where { |comp| $comp in $infra_check_latest })

    # Check provisioning cache
    let prov_expired = (get-expired-entries "provisioning")
    let prov_check_latest = (get-check-latest-components "provisioning")
    let prov_needs_update = ($prov_expired | where { |comp| $comp in $prov_check_latest })

    # Combine and deduplicate
    ($infra_needs_update ++ $prov_needs_update) | uniq
}

# Get components with check_latest = true
def get-check-latest-components [cache_type: string] {
    let cache_path = if $cache_type == "infra" {
        get-infra-cache-path
    } else {
        get-provisioning-cache-path
    }

    let cache_file = ($cache_path | path join "versions.json")

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

    let result = (do { open $cache_file } | complete)
    if $result.exit_code != 0 {
        return []
    }

    let cache_data = ($result.stdout | from json)

    $cache_data | columns | where { |component|
        let comp_data = ($cache_data | get $component)
        let cl_result = (do { $comp_data | get check_latest } | complete)
        if $cl_result.exit_code == 0 { $cl_result.stdout } else { false }
    }
}

# Invalidate cache entry (force refresh on next access)
export def invalidate-cache-entry [
    component: string       # Component name
    cache_type: string     # "infra" or "provisioning"
] {
    let cache_path = if $cache_type == "infra" {
        get-infra-cache-path
    } else {
        get-provisioning-cache-path
    }

    let cache_file = ($cache_path | path join "versions.json")

    if ($cache_file | path exists) {
        let result = (do { open $cache_file } | complete)
        if $result.exit_code == 0 {
            let cache_data = ($result.stdout | from json)
            let updated_cache = ($cache_data | upsert $component { |entry|
                $entry | upsert cached_at "1970-01-01T00:00:00Z"  # Force expiry
            })
            $updated_cache | save -f $cache_file
        }
    }
}

# Helper functions (same as in cache_manager.nu)
def get-infra-cache-path [] {
    use ../config/accessor.nu config-get
    let infra_path = (config-get "paths.infra" "")
    let current_infra = (config-get "infra.current" "default")

    if ($infra_path | is-empty) {
        return (get-provisioning-cache-path)
    }

    $infra_path | path join $current_infra "cache"
}

def get-provisioning-cache-path [] {
    use ../config/accessor.nu config-get
    config-get "cache.path" ".cache/versions"
}

def get-default-grace-period [] {
    use ../config/accessor.nu config-get
    config-get "cache.grace_period" 86400
}
