#!/usr/bin/env nu
# Taskserv version extraction and management utilities
# Handles Nickel taskserv files and version configuration

# Selective imports (ADR-025 Phase 3 Layer 2).
# version/core.nu and version/loader.nu star-imports were dead — dropped.
use lib_provisioning/utils/interface.nu [_print]

# Extract version field from Nickel taskserv files
export def extract-nickel-version [
    file_path: string
] {
    if not ($file_path | path exists) { return "" }

    let content = (open $file_path --raw)

    # Look for version assignment in taskserv configuration files
    let version_matches = ($content | lines | each { |line|
        let trimmed_line = ($line | str trim)
        # Match "version = " pattern (but not major_version, cni_version, etc.)
        if ($trimmed_line | str starts-with "version") and ($trimmed_line | str contains "=") {
            # Split on equals and take the right side
            let parts = ($trimmed_line | split row "=")
            if ($parts | length) >= 2 {
                let version_value = ($parts | get 1 | str trim)
                if ($version_value | str starts-with '"') {
                    # Remove quotes and get the value
                    ($version_value | parse -r '"([^"]*)"' | get 0? | default {} | get capture0? | default "")
                } else if ($version_value | str starts-with "'") {
                    # Handle single quotes
                    ($version_value | parse -r "'([^']*)'" | get 0? | default {} | get capture0? | default "")
                } else {
                    # Handle unquoted values (remove any trailing comments)
                    ($version_value | str replace "\\s*#.*$" "" | str trim)
                }
            } else {
                ""
            }
        } else if ($trimmed_line | str starts-with "version:") and not ($trimmed_line | str contains "str") {
            # Handle schema-style "version: value" (not type declarations)
            let version_part = ($trimmed_line | str replace "version:\\s*" "")
            if ($version_part | str starts-with '"') {
                ($version_part | parse -r '"([^"]*)"' | get 0? | default {} | get capture0? | default "")
            } else if ($version_part | str starts-with "'") {
                ($version_part | parse -r "'([^']*)'" | get 0? | default {} | get capture0? | default "")
            } else {
                ($version_part | str replace "\\s*#.*$" "" | str trim)
            }
        } else {
            ""
        }
    } | where { |v| $v != "" })

    if ($version_matches | length) > 0 {
        $version_matches | get 0
    } else {
        ""
    }
}

# Discover all taskserv Nickel files and their versions
export def discover-taskserv-configurations [
    --base-path: string = ""
] {
    let taskservs_path = if ($base_path | is-not-empty) {
        $base_path
    } else {
        (get-taskservs-path)
    }

    if not ($taskservs_path | path exists) {
        _print $"⚠️ Taskservs path not found: ($taskservs_path)"
        return []
    }

    # Find all .ncl files recursively in the taskservs directory
    let all_k_files = (glob $"($taskservs_path)/**/*.ncl")

    let nickel_configs = ($all_k_files | each { |decl_file|
        let version = (extract-nickel-version $decl_file)
        if ($version | is-not-empty) {
            let relative_path = ($decl_file | str replace $"($taskservs_path)/" "")
            let path_parts = ($relative_path | split row "/" | where { |p| $p != "" })

            # Determine ID from the path structure
            let id = if ($path_parts | length) >= 2 {
                # If it's a server-specific file like "wuji-strg-1/kubernetes.ncl"
                let filename = ($decl_file | path basename | str replace ".ncl" "")
                $"($path_parts.0)::($filename)"
            } else {
                # If it's a general file like "proxy.ncl"
                ($decl_file | path basename | str replace ".ncl" "")
            }

            {
                id: $id
                type: "taskserv"
                nickel_file: $decl_file
                version: $version
                metadata: {
                    source_file: $decl_file
                    category: "taskserv"
                    path_structure: $path_parts
                }
            }
        } else {
            null
        }
    } | where { |item| $item != null })

    $nickel_configs
}

# Update version in Nickel file
export def update-nickel-version [
    file_path: string
    new_version: string
] {
    if not ($file_path | path exists) {
        _print $"❌ File not found: ($file_path)"
        return
    }

    let content = (open $file_path --raw)

    # Replace version field while preserving formatting
    let updated_content = ($content | lines | each { |line|
        if ($line | str trim | str starts-with "version:") {
            # Preserve indentation and update version
            let indent = ($line | str replace "^(\\s*).*" '$1')
            let line_trimmed = ($line | str trim)
            if ($line_trimmed | str contains '"') {
                $"($indent)version: \"($new_version)\""
            } else if ($line_trimmed | str contains "'") {
                $"($indent)version: '($new_version)'"
            } else {
                $"($indent)version: str = \"($new_version)\""
            }
        } else {
            $line
        }
    } | str join "\n")

    $updated_content | save -f $file_path
    _print $"✅ Updated version in ($file_path) to ($new_version)"
}

# Check taskserv versions against available versions
export def check-taskserv-versions [
    --fetch-latest = false
] {
    let configs = (discover-taskserv-configurations)

    if ($configs | is-empty) {
        _print "No taskserv configurations found"
        return []
    }

    $configs | each { |config|
        # For now, return basic info - can be extended with version checking logic
        {
            id: $config.id
            type: $config.type
            configured: $config.version
            nickel_file: $config.nickel_file
            status: "configured"
        }
    }
}

# Update taskserv version in Nickel file
export def update-taskserv-version [
    taskserv_id: string
    new_version: string
    --dry-run = false
] {
    let configs = (discover-taskserv-configurations)
    let config = ($configs | where id == $taskserv_id | first | default null)

    if ($config | is-empty) {
        _print $"❌ Taskserv '($taskserv_id)' not found"
        return
    }

    if $dry_run {
        _print $"🔍 Would update ($taskserv_id) from ($config.version) to ($new_version) in ($config.nickel_file)"
        return
    }

    update-nickel-version $config.nickel_file $new_version
}

# Bulk update multiple taskservs
export def bulk-update-taskservs [
    updates: list  # List of {id: string, version: string}
    --dry-run = false
] {
    if ($updates | is-empty) {
        _print "No updates provided"
        return
    }

    _print $"Updating ($updates | length) taskservs..."

    for update in $updates {
        let taskserv_id = ($update | get id? | default "")
        let new_version = ($update | get version? | default "")

        if ($taskserv_id | is-empty) or ($new_version | is-empty) {
            _print $"⚠️ Invalid update entry: ($update)"
            continue
        }

        update-taskserv-version $taskserv_id $new_version --dry-run=$dry_run
    }

    if not $dry_run {
        _print "✅ Bulk update completed"
    }
}

# Sync taskserv versions with registry
export def taskserv-sync-versions [
    --taskservs-path: string = ""
    --component: string = ""  # Specific component to sync
    --dry-run = false
] {
    let registry = (load-version-registry)
    let comparisons = (compare-registry-with-taskservs --taskservs-path=$taskservs_path)

    if ($comparisons | is-empty) {
        _print "❌ No taskserv configurations found"
        return
    }

    # Filter to out-of-sync components
    mut out_of_sync = ($comparisons | where status == "out_of_sync")

    if ($component | is-not-empty) {
        let filtered = ($out_of_sync | where component == $component)
        if ($filtered | is-empty) {
            _print $"✅ Component '($component)' is already in sync or not found"
            return
        }
        $out_of_sync = $filtered
    }

    if ($out_of_sync | is-empty) {
        _print "✅ All taskservs are in sync with registry"
        return
    }

    _print $"Found ($out_of_sync | length) components with version mismatches:"

    for comp in $out_of_sync {
        _print $"\n🔧 ($comp.component) [Registry: ($comp.registry_version)]"

        # Find taskservs that need updating
        let outdated_taskservs = ($comp.taskserv_configs | where not matches_registry)

        for taskserv in $outdated_taskservs {
            if $dry_run {
                _print $"🔍 Would update ($taskserv.id): ($taskserv.version) -> ($comp.registry_version)"
            } else {
                _print $"🔄 Updating ($taskserv.id): ($taskserv.version) -> ($comp.registry_version)"
                update-nickel-version $taskserv.file $comp.registry_version
            }
        }
    }

    if $dry_run {
        _print "\n🔍 Dry run completed - no changes made"
    } else {
        _print "\n✅ Sync completed"
    }
}
