#!/usr/bin/env nu

# WASM Bundle Validation Script for Rustelo Project
# Validates WASM bundle generation, size, and JavaScript bindings

def main [
    --path: string = "."        # Path to project root
    --max-size: int = 5000000   # Maximum WASM size in bytes (5MB default)
    --check-bindings            # Verify JavaScript bindings exist
] {
    print "🔍 Validating WASM bundle and JavaScript bindings..."

    mut issues = []

    # Check WASM files
    let issues = ($issues | append (check_wasm_files $path $max_size))

    # Check JavaScript bindings
    if $check_bindings {
        let issues = ($issues | append (check_js_bindings $path))
    }

    # Check site output
    let issues = ($issues | append (check_site_output $path))

    # Display results
    if ($issues | is-empty) {
        print "✅ WASM bundle validation passed!"
        return 0
    } else {
        print "❌ WASM bundle validation issues found:"
        for $issue in $issues {
            print $"  ($issue.severity): ($issue.message)"
            if ($issue.fix?) {
                print $"     Fix: ($issue.fix)"
            }
        }

        let errors = ($issues | where severity == "ERROR")
        if not ($errors | is-empty) {
            return 1
        } else {
            return 0
        }
    }
}

# Check WASM files in build directories
def check_wasm_files [path: string, max_size: int] {
    mut issues = []

    print "🔍 Checking WASM files..."

    # Check target/front directory (cargo build output)
    let wasm_build_dir = $"($path)/target/front/wasm32-unknown-unknown/debug"
    if ($wasm_build_dir | path exists) {
        let wasm_files = try {
            ls $"($wasm_build_dir)/*.wasm" | get name
        } catch {
            []
        }

        if ($wasm_files | is-empty) {
            $issues = ($issues | append {
                severity: "ERROR"
                message: "No WASM files found in target/front directory"
                fix: "Run 'cargo build --target wasm32-unknown-unknown --package client'"
            })
        } else {
            for $wasm_file in $wasm_files {
                let size = ($wasm_file | path stat | get size)
                let name = ($wasm_file | path basename)

                print $"(ansi green)✅ WASM file: ($name) (($size) bytes)(ansi reset)"

                if $size > $max_size {
                    $issues = ($issues | append {
                        severity: "WARNING"
                        message: $"WASM file ($name) is large: ($size) bytes"
                        fix: "Consider optimizing WASM bundle size"
                    })
                }

                if $size < 1000 {
                    $issues = ($issues | append {
                        severity: "ERROR"
                        message: $"WASM file ($name) is suspiciously small: ($size) bytes"
                        fix: "Check if WASM build completed successfully"
                    })
                }
            }
        }
    } else {
        $issues = ($issues | append {
            severity: "ERROR"
            message: "WASM build directory not found"
            fix: "Run 'cargo build --target wasm32-unknown-unknown --package client'"
        })
    }

    $issues
}

# Check JavaScript bindings generated by wasm-bindgen
def check_js_bindings [path: string] {
    mut issues = []

    print "🔍 Checking JavaScript bindings..."

    # Check target/site/pkg directory (leptos output)
    let pkg_dir = $"($path)/target/site/pkg"
    if ($pkg_dir | path exists) {
        # Check for JS files
        let js_files = try {
            ls $"($pkg_dir)/*.js" | get name
        } catch {
            []
        }

        if ($js_files | is-empty) {
            $issues = ($issues | append {
                severity: "ERROR"
                message: "No JavaScript binding files found"
                fix: "Run 'cargo leptos build' to generate bindings"
            })
        } else {
            for $js_file in $js_files {
                let size = ($js_file | path stat | get size)
                let name = ($js_file | path basename)
                print $"(ansi green)✅ JS binding: ($name) (($size) bytes)(ansi reset)"

                # Check for essential wasm-bindgen patterns
                let content = try {
                    open $js_file
                } catch {
                    ""
                }

                let required_patterns = [
                    "wasm"
                    "init"
                    "memory"
                ]

                for $pattern in $required_patterns {
                    if not ($content | str contains $pattern) {
                        $issues = ($issues | append {
                            severity: "WARNING"
                            message: $"JS binding ($name) missing expected pattern: ($pattern)"
                            fix: "Check wasm-bindgen generation"
                        })
                    }
                }
            }
        }
    } else {
        $issues = ($issues | append {
            severity: "WARNING"
            message: "Leptos pkg directory not found"
            fix: "Run 'cargo leptos build' to generate site output"
        })
    }

    $issues
}

# Check site output directory
def check_site_output [path: string] {
    mut issues = []

    print "🔍 Checking site output..."

    let site_dir = $"($path)/target/site"
    if not ($site_dir | path exists) {
        $issues = ($issues | append {
            severity: "WARNING"
            message: "Site output directory not found"
            fix: "Run 'cargo leptos build'"
        })
        return $issues
    }

    # Check for essential files
    let essential_files = [
        "pkg"           # WASM and JS bindings
        "index.html"    # Main HTML file (might not exist for SPA)
    ]

    for $file in $essential_files {
        let file_path = $"($site_dir)/($file)"
        if ($file_path | path exists) {
            if ($file | str ends-with ".html") {
                let size = ($file_path | path stat | get size)
                print $"(ansi green)✅ Site file: ($file) (($size) bytes)(ansi reset)"
            } else {
                print $"(ansi green)✅ Site directory: ($file)(ansi reset)"
            }
        } else {
            # Only warn for missing files, not directories
            if ($file | str ends-with ".html") {
                $issues = ($issues | append {
                    severity: "INFO"
                    message: $"Optional site file not found: ($file)"
                    fix: "Normal for SPA applications"
                })
            }
        }
    }

    # Report site structure
    let site_contents = try {
        ls $site_dir | get name | path basename
    } catch {
        []
    }

    print $"(ansi blue)📁 Site contents: ($site_contents | str join ', ')(ansi reset)"

    $issues
}

# Get file size in human readable format
def human_size [bytes: int] {
    if $bytes < 1024 {
        $"($bytes) B"
    } else if $bytes < 1048576 {
        $"($bytes / 1024 | math round) KB"
    } else {
        $"($bytes / 1048576 | math round) MB"
    }
}
