#!/usr/bin/env nu

# Decide whether the workspace needs a wasm32 build for the Leptos hydration profile.
#
# Used by the `build-auto` justfile recipe (and any CI driver) to choose between:
#   cargo leptos build --release            (any route declares leptos-hydration)
#   cargo build --release --no-default-features --features ssr,htmx-ssr
#                                           (all routes are htmx-ssr)
#
# Decision sources, in precedence order:
#   1. A `rendering_profile = "leptos-hydration"` override on any per-route TOML.
#   2. `[rendering] default_profile = "leptos-hydration"` in the workspace config.
#   3. Absence of a workspace `[rendering]` table (Rustelo default is hydration).
#
# Exit codes (suited for shell `if`):
#   0 — wasm build needed (run cargo leptos)
#   1 — wasm build NOT needed (run cargo build with htmx-ssr features)
#   2 — argument or filesystem error
#
# Usage:
#   nu scripts/check-wasm-needed.nu --routes-dir site/config/routes \
#     --workspace-config site/config/rendering.toml
#
#   nu scripts/check-wasm-needed.nu --verbose ...   # also print the reason

def main [
    --routes-dir: string        # directory containing per-language route TOMLs; scanned recursively
    --workspace-config: string  # path to the workspace config TOML carrying the [rendering] table
    --verbose                   # print one-line reason to stderr
] {
    let routes_dir = if $routes_dir == null { null } else { $routes_dir }
    let workspace_config = if $workspace_config == null { null } else { $workspace_config }

    # 1. Any route-level override forces the decision.
    if $routes_dir != null and ($routes_dir | path exists) {
        let hits = (try { route_overrides $routes_dir } catch { |e|
            print --stderr $"check-wasm-needed: failed to scan routes dir: ($e)"
            exit 2
        })
        if ($hits | length) > 0 {
            if $verbose {
                let first = ($hits | first)
                print --stderr $"wasm needed: route override (($first.file)) declares leptos-hydration"
            }
            exit 0
        }
    }

    # 2. Workspace default.
    let workspace_says_hydrate = if $workspace_config != null and ($workspace_config | path exists) {
        workspace_default_is_hydration $workspace_config
    } else {
        true   # 3. Absent table → Rustelo default is hydration.
    }

    if $workspace_says_hydrate {
        if $verbose {
            print --stderr "wasm needed: workspace default is leptos-hydration (explicit or implicit)"
        }
        exit 0
    } else {
        if $verbose {
            print --stderr "wasm skipped: workspace default is htmx-ssr and no route opts back into leptos-hydration"
        }
        exit 1
    }
}

# Returns rows {file, line} for every route TOML under `dir` whose
# `rendering_profile` field is `"leptos-hydration"`.
def route_overrides [dir: string] {
    glob $"($dir)/**/*.toml" | each {|file|
        let content = (open --raw $file)
        $content | lines | enumerate | each {|row|
            let line = $row.item
            if ($line | str replace --all ' ' '' | str contains 'rendering_profile="leptos-hydration"') {
                { file: $file, line: ($row.index + 1) }
            } else {
                null
            }
        } | where { |it| $it != null }
    } | flatten
}

# Parses the workspace config (TOML or NCL) and returns true when the
# rendering.default_profile field is missing or set to "leptos-hydration".
#
# NCL workspaces are read as text and the field is grepped (avoids requiring
# the nickel CLI in PATH for this dispatch decision). The grep is intentionally
# strict — only single-line `default_profile = "<value>"` syntax is recognised.
def workspace_default_is_hydration [config_path: string] {
    let extension = ($config_path | path parse | get extension)
    if $extension == "ncl" {
        let content = (try { open --raw $config_path } catch { return true })
        # Look for a single-line `default_profile = "..."` assignment.
        let htmx_line = (
            $content
            | lines
            | each { |l| $l | str replace --all ' ' '' }
            | where { |l| $l | str contains 'default_profile="htmx-ssr"' }
        )
        ($htmx_line | length) == 0
    } else {
        let parsed = (try { open $config_path } catch { return true })
        let table = ($parsed.rendering? | default null)
        if $table == null {
            true
        } else {
            let value = ($table.default_profile? | default "leptos-hydration")
            $value == "leptos-hydration"
        }
    }
}
