# | Nickel to Nickel Migration Helper
# | Automates pattern detection and application
# | Follows: .claude/kcl_to_nickel_migration_framework.md
# | Author: Migration Framework
# | Date: 2025-12-15

# ============================================================
# Pattern Detection
# ============================================================

# Detect if Nickel file uses schema inheritance pattern
export def "detect-inheritance" [decl_file: path] -> bool {
    let content = open $decl_file | into string
    ($content | str contains "schema ") and ($content | str contains "(")
}

# Detect if Nickel file exports global instances
export def "detect-exports" [decl_file: path] -> list {
    let content = open $decl_file | into string
    $content
    | lines
    | filter { |line| ($line | str contains ": ") and not ($line | str contains "schema") }
    | filter { |line| ($line | str contains " = ") }
    | map { |line| $line | str trim }
}

# Detect if Nickel file only defines schemas (no exports)
export def "is-schema-only" [decl_file: path] -> bool {
    let exports = (detect-exports $decl_file)
    ($exports | length) == 0
}

# Get migration template type for Nickel file
export def "get-template-type" [decl_file: path] -> string {
    let has_inheritance = (detect-inheritance $decl_file)
    let is_empty_export = (is-schema-only $decl_file)
    let exports = (detect-exports $decl_file)
    let export_count = ($exports | length)

    if $is_empty_export {
        "template-1-schema-only"
    } else if $has_inheritance {
        "template-4-inheritance"
    } else if $export_count == 1 {
        "template-2-single-instance"
    } else if $export_count > 1 {
        "template-5-multiple-schemas"
    } else {
        "template-3-complex-nesting"
    }
}

# ============================================================
# Value Conversion
# ============================================================

# Convert Nickel boolean to Nickel
export def "convert-boolean" [value: string] -> string {
    match ($value | str trim) {
        "True" => "true",
        "False" => "false",
        "true" => "true",
        "false" => "false",
        _ => $value,
    }
}

# Convert Nickel None to Nickel null
export def "convert-none" [value: string] -> string {
    match ($value | str trim) {
        "None" => "null",
        "null" => "null",
        _ => $value,
    }
}

# Convert Nickel value to Nickel value
export def "convert-value" [decl_value: string] -> string {
    let trimmed = ($decl_value | str trim)
    let bool_converted = (convert-boolean $trimmed)
    (convert-none $bool_converted)
}

# ============================================================
# JSON Equivalence Validation
# ============================================================

# Export Nickel file to JSON for comparison
export def "nickel-to-json" [decl_file: path] {
    if not ($decl_file | path exists) {
        error make {msg: $"Nickel file not found: ($decl_file)"}
    }

    nickel export $decl_file --format json 2>&1
}

# Export Nickel file to JSON for comparison
export def "nickel-to-json" [nickel_file: path] {
    if not ($nickel_file | path exists) {
        error make {msg: $"Nickel file not found: ($nickel_file)"}
    }

    nickel export $nickel_file 2>&1 | from json | to json
}

# Compare Nickel and Nickel JSON outputs for equivalence
export def "compare-equivalence" [decl_file: path, nickel_file: path] -> bool {
    let source_json = (nickel-to-json $decl_file | from json)
    let nickel_json = (nickel-to-json $nickel_file | from json)

    $source_json == $nickel_json
}

# Show detailed comparison between Nickel and Nickel
export def "show-comparison" [decl_file: path, nickel_file: path] {
    print $"Comparing: ($decl_file) ⇄ ($nickel_file)\n"

    let source_json = (nickel-to-json $decl_file)
    let nickel_json = (nickel-to-json $nickel_file)

    print "=== Source Output (JSON) ==="
    print $source_json
    print ""
    print "=== Target Output (JSON) ==="
    print $nickel_json
    print ""

    let equivalent = ($source_json == $nickel_json)
    if $equivalent {
        print "✅ Outputs are EQUIVALENT"
    } else {
        print "❌ Outputs DIFFER"
        print "\nDifferences:"
        diff <(print $source_json | jq -S .) <(print $nickel_json | jq -S .)
    }
}

# ============================================================
# Migration Workflow
# ============================================================

# Analyze Nickel file and recommend migration approach
export def "analyze-nickel" [decl_file: path] {
    if not ($decl_file | path exists) {
        error make {msg: $"File not found: ($decl_file)"}
    }

    let template = (get-template-type $decl_file)
    let has_inheritance = (detect-inheritance $decl_file)
    let exports = (detect-exports $decl_file)
    let is_empty = (is-schema-only $decl_file)

    print $"File: ($decl_file)"
    print $"Template Type: ($template)"
    print $"Has Schema Inheritance: ($has_inheritance)"
    print $"Is Schema-Only (no exports): ($is_empty)"
    print $"Exported Instances: ($exports | length)"

    if ($exports | length) > 0 {
        print "\nExported instances:"
        $exports | each { |exp| print $"  - ($exp)" }
    }
}

# Generate skeleton Nickel file from Nickel template
export def "generate-nickel-skeleton" [decl_file: path, output_file: path] {
    let template = (get-template-type $decl_file)
    let source_name = ($decl_file | path basename | str replace ".ncl" "")

    let skeleton = match $template {
        "template-1-schema-only" => {
            $"# | Schema definitions migrated from ($source_name).ncl\n# | Migrated: 2025-12-15\n\n{{}}"
        },
        "template-2-single-instance" => {
            let exports = (detect-exports $decl_file)
            let instance = ($exports | get 0 | str split " " | get 0)
            $"# | Configuration migrated from ($source_name).ncl\n\n{\n  ($instance) = {\n    # TODO: Fill in fields\n  },\n}"
        },
        _ => {
            $"# | Migrated from ($source_name).ncl\n# | Template: ($template)\n\n{\n  # TODO: Implement\n}"
        },
    }

    print $skeleton
    print $"\nTo save: print output to ($output_file)"
}

# ============================================================
# Batch Migration
# ============================================================

# Migrate multiple Nickel files to Nickel using templates
export def "batch-migrate" [
    source_dir: path,
    nickel_dir: path,
    --pattern: string = "*.ncl",
    --dry-run: bool = false,
] {
    let source_files = (glob $"($source_dir)/($pattern)")

    print $"Found ($source_files | length) Nickel files matching pattern: ($pattern)"
    print ""

    $source_files | each { |source_file|
        let relative_path = ($source_file | str replace $"($source_dir)/" "")
        let nickel_file = $"($nickel_dir)/($relative_path | str replace ".ncl" ".ncl")"

        print $"[$relative_path]"
        let template = (get-template-type $source_file)
        print $"  Template: ($template)"

        if not $dry_run {
            if ($nickel_file | path exists) {
                print $"  ⚠️  Already exists: ($nickel_file)"
            } else {
                print $"  → Would migrate to: ($nickel_file)"
            }
        }
    }
}

# ============================================================
# Validation
# ============================================================

# Validate Nickel file syntax
export def "validate-nickel" [nickel_file: path] -> bool {
    # Validate Nickel syntax (no try-catch)
    let result = (do { nickel export $nickel_file | null } | complete)
    ($result.exit_code == 0)
}

# Full migration validation for a file pair
export def "validate-migration" [decl_file: path, nickel_file: path] -> record {
    let source_exists = ($decl_file | path exists)
    let nickel_exists = ($nickel_file | path exists)
    let nickel_valid = if $nickel_exists { (validate-nickel $nickel_file) } else { false }
    let equivalent = if ($source_exists and $nickel_valid) {
        (compare-equivalence $decl_file $nickel_file)
    } else {
        false
    }

    {
        source_exists: $source_exists,
        nickel_exists: $nickel_exists,
        nickel_valid: $nickel_valid,
        outputs_equivalent: $equivalent,
        status: if $equivalent { "✅ PASS" } else { "❌ FAIL" },
    }
}

# Validation report for all migrated files
export def "validation-report" [source_dir: path, nickel_dir: path] {
    let nickel_files = (glob $"($nickel_dir)/**/*.ncl")

    print $"Validation Report: ($nickel_files | length) Nickel files\n"

    let results = $nickel_files | map { |nickel_file|
        let relative = ($nickel_file | str replace $"($nickel_dir)/" "")
        let source_file = $"($source_dir)/($relative | str replace ".ncl" ".ncl")"
        let validation = (validate-migration $source_file $nickel_file)

        print $"($validation.status) $relative"
        if not $validation.nickel_valid {
            print "  ⚠️  Nickel syntax error"
        }
        if not $validation.outputs_equivalent {
            print "  ⚠️  JSON outputs differ"
        }

        $validation
    }

    let passed = ($results | where {|r| $r.outputs_equivalent} | length)
    let total = ($results | length)
    print $"\nSummary: ($passed)/($total) files PASS equivalence check"
}
