use std

let nurcmd = "./../target/release/nur"

# Tests

def "nur test-env" [] {
    std assert (($env.PWD | path join ".nur" "scripts") in $env.NU_LIB_DIRS)
    std assert ($env.NUR_VERSION | is-not-empty)
    std assert ($env.NUR_TASK_NAME | is-not-empty)
    std assert ($env.NUR_TASK_CALL | is-not-empty)
}

def "nur test-config" [] {
    try {
        $env.config
    } catch {
        error make {"msg": "Config does not exist"}
    }
}

def "nur test-nu" [] {
    std assert ($nu.config-path == ($env.PWD | path join ".nur" "config.nu"))
    std assert ($nu.env-path == ($env.PWD | path join ".nur" "env.nu"))
    if (is-windows) {
        std assert (($nu.current-exe | path basename) == "nur.exe")
    } else {
        std assert (($nu.current-exe | path basename) == "nur")
    }
}

def "nur test-nur" [] {
    std assert ($nur.task-name == "test-nur")
    std assert ($nur.run-path == $env.PWD)
    std assert ($nur.project-path == $env.PWD)
    std assert ($nur.default-lib-dir == ($env.PWD | path join ".nur" "scripts"))
}

def "nur exec-stdin" [] {
    lines | each { |it| print $"BEFORE ($it) AFTER" }
}
def "nur test-stdin" [] {
    std assert ("inner" | run-nur --stdin exec-stdin | str contains "BEFORE inner AFTER")
}

def "nur do-failed-execution" [] {
    if (is-windows) {
        cmd /c "exit 1"
    } else {
        ^false
    }
}
def "nur test-failed-execution" [] {
    try {
        run-nur do-failed-execution
        error make {"msg": "Did not fail, this is an error"}
    } catch {
        # all ok
    }
}

def "nur do-invalid-executable" [] {
    ^does-not-exist-at-all-will-not-exist-ever
}
def "nur test-invalid-executable" [] {
    try {
        run-nur do-invalid-executable o+e>| ignore
        error make {"msg": "Did not fail, this is an error"}
    } catch {
        # all ok
    }
}

def "nur do-sub-task" [] { print "ok" }
def "nur do-sub-task sub" [] { print "sub-ok" }
def "nur test-sub-task" [] {
    std assert ((run-nur do-sub-task) == "ok")
    std assert ((run-nur do-sub-task sub) == "sub-ok")
}

def "nur do-sub-task-without-parent sub" [] { print "sub-ok" }
def "nur test-sub-task-without-parent" [] {
    std assert ((run-nur do-sub-task-without-parent sub) == "sub-ok")
}

def --wrapped "nur do-sub-task-with-any-args sub" [...args] { print "sub-ok" }
def "nur test-sub-task-with-any-args" [] {
    std assert ((run-nur do-sub-task-with-any-args sub) == "sub-ok")
    std assert ((run-nur do-sub-task-with-any-args sub --foo bar bla) == "sub-ok")
    std assert ((run-nur do-sub-task-with-any-args sub some random args) == "sub-ok")
}

# Utils and other commands

def is-windows [] {
    $nu.os-info.name == 'windows'
}

def --wrapped run-nur [
    ...args
] {
    ^$nurcmd --quiet ...$args
}

def "nur prepare" [] {
    cargo build --release
}

def "nur run-all" [] {
    let tests = (scope commands | filter { |it| $it.name starts-with 'nur test-' } | each { |it| $it.name | split row ' ' })

    let failed_tests = (
        $tests | each {
            |it|
            $it | str join " " | print -n
            let was_ok: bool = try {
                run-nur $it.1 o+e>| ignore
                print $'...(ansi green)ok(ansi reset)'
                true  # mark as ok
            } catch {
                print $'...(ansi red)failed(ansi reset)'
                false  # mark as failed
            }

            if $was_ok { null } else { $it.1 }
        }
    )

    if ($failed_tests | is-not-empty) {
        error make {"msg": $'Some tests did fail, please fix those: ($failed_tests | str join ", ")'}
    }
}
