#!/usr/bin/env nu
# audit-nu-scripts.nu - Automated Nushell script auditor for 0.109+ compatibility
# Usage: nu .claude/guidelines/nushell/audit-nu-scripts.nu [--fix] [--verbose]

def main [
    --fix                       # Automatically fix simple issues
    --verbose                   # Show detailed output
    --output: string = ""       # Output report to file
] {
    print_header

    # Find all Nushell scripts
    let scripts = glob **/*.nu | where {|path| not ($path | str starts-with "target/")}

    print $"Found ($scripts | length) Nushell script(s) to audit\n"

    mut issues = []
    mut summary = {
        total_scripts: ($scripts | length)
        scripts_with_issues: 0
        total_issues: 0
        critical: 0
        warning: 0
        info: 0
    }

    # Audit each script
    for script_path in $scripts {
        let script_issues = audit_script $script_path $verbose

        if ($script_issues | length) > 0 {
            $summary.scripts_with_issues = $summary.scripts_with_issues + 1
            $summary.total_issues = $summary.total_issues + ($script_issues | length)

            # Count by severity
            for issue in $script_issues {
                match $issue.severity {
                    "critical" => { $summary.critical = $summary.critical + 1 }
                    "warning" => { $summary.warning = $summary.warning + 1 }
                    "info" => { $summary.info = $summary.info + 1 }
                    _ => {}
                }
            }

            # Add to issues list
            $issues = ($issues | append {
                script: $script_path
                issues: $script_issues
            })
        }
    }

    # Print results
    print_divider
    print_summary $summary
    print_divider

    if ($issues | length) > 0 {
        print "\n📋 DETAILED FINDINGS:\n"
        for script_result in $issues {
            print_script_issues $script_result.script $script_result.issues
        }
    }

    # Generate report if requested
    if $output != "" {
        generate_report $issues $summary $output
        print $"\n✓ Report saved to: ($output)"
    }

    # Exit code based on critical issues
    if $summary.critical > 0 {
        exit 1
    }
}

# Audit a single script
def audit_script [path: string, verbose: bool] -> list {
    if $verbose {
        print $"Auditing: ($path)"
    }

    mut issues = []

    # Read script content
    let content = try {
        open --raw $path
    } catch {
        return [{
            line: 0
            severity: "critical"
            category: "file_access"
            message: $"Cannot read file: ($path)"
            suggestion: "Check file permissions"
        }]
    }

    let lines = $content | lines

    # Check 1: Missing shebang
    if (($lines | first) !~ "#!/usr/bin/env nu") {
        $issues = ($issues | append {
            line: 1
            severity: "warning"
            category: "shebang"
            message: "Missing or incorrect shebang"
            suggestion: "Add: #!/usr/bin/env nu"
        })
    }

    # Check 2: Old closure syntax (using $in in where/each)
    for (idx, line) in ($lines | enumerate) {
        let line_num = $idx + 1

        # Check for old-style closures
        if ($line =~ '\| where \{ \$in') or ($line =~ '\| each \{ \$in') {
            $issues = ($issues | append {
                line: $line_num
                severity: "warning"
                category: "closure_syntax"
                message: "Old-style closure using $in"
                suggestion: "Use explicit parameter: {|x| $x ...} instead of { $in ... }"
            })
        }

        # Check for missing type annotations on exported functions
        if ($line =~ 'export def .+\[') and not ($line =~ ': \w+') {
            $issues = ($issues | append {
                line: $line_num
                severity: "info"
                category: "type_annotations"
                message: "Function parameters missing type annotations"
                suggestion: "Add type annotations: [param: type]"
            })
        }

        # Check for unwrap-like patterns (get without -i)
        if ($line =~ '\| get [a-zA-Z_]') and not ($line =~ 'get -i') {
            if not ($line =~ '\| get \w+ \|') {
                # Potentially unsafe get (not in pipeline continuation)
                $issues = ($issues | append {
                    line: $line_num
                    severity: "info"
                    category: "null_safety"
                    message: "Potentially unsafe 'get' without -i flag"
                    suggestion: "Use 'get -i' for safe access or add error handling"
                })
            }
        }

        # Check for hardcoded paths (common anti-pattern)
        if ($line =~ '/Users/[^/]+/') or ($line =~ 'C:\\\\') {
            $issues = ($issues | append {
                line: $line_num
                severity: "warning"
                category: "hardcoded_paths"
                message: "Hardcoded absolute path detected"
                suggestion: "Use $env.HOME or relative paths"
            })
        }

        # Check for missing error handling in external commands
        if ($line =~ '\^[a-zA-Z_-]+') and not ($line =~ 'try \{') {
            # External command not wrapped in try-catch
            # Check if previous or next line has try
            let has_try = if $idx > 0 {
                ($lines | get ($idx - 1) | str contains "try")
            } else {
                false
            }

            if not $has_try {
                $issues = ($issues | append {
                    line: $line_num
                    severity: "info"
                    category: "error_handling"
                    message: "External command without error handling"
                    suggestion: "Wrap in try-catch block"
                })
            }
        }

        # Check for deprecated mut syntax
        if ($line =~ 'let mut ') {
            # This is actually fine in 0.109, just noting it
            # $issues = append with info if we want to track mutable usage
        }

        # Check for missing return type annotations
        if ($line =~ 'export def .+\]') and not ($line =~ '-> \w+') and not ($line =~ '\{$') {
            $issues = ($issues | append {
                line: $line_num
                severity: "info"
                category: "type_annotations"
                message: "Function missing return type annotation"
                suggestion: "Add return type: ] -> type {"
            })
        }
    }

    # Check 3: No error handling in main functions
    let has_try = $content | str contains "try"
    let has_catch = $content | str contains "catch"
    if not ($has_try and $has_catch) {
        $issues = ($issues | append {
            line: 0
            severity: "info"
            category: "error_handling"
            message: "Script may lack error handling (no try-catch found)"
            suggestion: "Add try-catch blocks for robust error handling"
        })
    }

    $issues
}

# Print header
def print_header [] {
    print ""
    print "╔════════════════════════════════════════════════════════╗"
    print "║  Nushell 0.109+ Compatibility Audit Tool              ║"
    print "║  syntaxis Project - Script Quality Checker            ║"
    print "╚════════════════════════════════════════════════════════╝"
    print ""
}

# Print divider
def print_divider [] {
    print "─────────────────────────────────────────────────────────"
}

# Print summary
def print_summary [summary: record] {
    print "\n📊 AUDIT SUMMARY:\n"
    print $"  Total scripts: ($summary.total_scripts)"
    print $"  Scripts with issues: ($summary.scripts_with_issues)"
    print $"  Total issues: ($summary.total_issues)"
    print ""
    print "  By Severity:"
    print $"    (ansi red)● Critical: ($summary.critical)(ansi reset)"
    print $"    (ansi yellow)● Warnings: ($summary.warning)(ansi reset)"
    print $"    (ansi cyan)● Info: ($summary.info)(ansi reset)"
}

# Print issues for a script
def print_script_issues [script: string, issues: list] {
    print $"\n(ansi cyan)📄 ($script)(ansi reset)"

    for issue in $issues {
        let severity_icon = match $issue.severity {
            "critical" => $"(ansi red)✗(ansi reset)"
            "warning" => $"(ansi yellow)⚠(ansi reset)"
            "info" => $"(ansi cyan)ℹ(ansi reset)"
            _ => "•"
        }

        let line_info = if $issue.line > 0 {
            $" (Line ($issue.line))"
        } else {
            ""
        }

        print $"  ($severity_icon) [($issue.category)]($line_info): ($issue.message)"
        print $"      → ($issue.suggestion)"
    }
}

# Generate markdown report
def generate_report [issues: list, summary: record, output_path: string] {
    let timestamp = date now | format date "%Y-%m-%d %H:%M:%S"

    mut report = $"# Nushell Script Audit Report
Generated: ($timestamp)

## Summary

- **Total Scripts**: ($summary.total_scripts)
- **Scripts with Issues**: ($summary.scripts_with_issues)
- **Total Issues**: ($summary.total_issues)
  - Critical: ($summary.critical)
  - Warnings: ($summary.warning)
  - Info: ($summary.info)

## Detailed Findings

"

    for script_result in $issues {
        $report = $report + $"\n### ($script_result.script)\n\n"

        for issue in $script_result.issues {
            let line_ref = if $issue.line > 0 {
                $" (Line ($issue.line))"
            } else {
                ""
            }

            $report = $report + $"- **[($issue.severity | str upcase)] ($issue.category)**($line_ref)
  - Issue: ($issue.message)
  - Suggestion: ($issue.suggestion)

"
        }
    }

    $report = $report + $"\n## Recommendations

1. Review all **critical** issues immediately
2. Address **warnings** before next release
3. Consider **info** items for code quality improvements
4. Follow guidelines in `.claude/guidelines/nushell/NUSHELL_0.109_GUIDELINES.md`

---
*Generated by syntaxis Nushell Audit Tool*
"

    $report | save --force $output_path
}

# Run main if executed directly
main
