#!/usr/bin/env bash

export MISE_EXPERIMENTAL=1

mkdir -p bin
cat <<'SH' >bin/npm
#!/bin/sh
printf '%s' "$*" >manager-args.txt
printf '%s' "$ROOT_TASK_DEFAULT" >default.txt
printf '%s:%s\n' "$(basename "$PWD")" "$*" >>"$WORKSPACE_TASK_LOG"
printf inferred >result.txt
SH
chmod +x bin/npm
export PATH="$PWD/bin:$PATH"
export WORKSPACE_TASK_LOG="$PWD/workspace-task.log"

cat <<'TOML' >mise.toml
monorepo_root = true

[monorepo]
config_roots = ["packages/*"]

[monorepo.task_defaults.build]
env = { ROOT_TASK_DEFAULT = "from-root", TASK_PRECEDENCE = "from-root" }
depends = ["^build"]
cache = { env = ["NODE_ENV"] }
run = "printf root-default > result.txt"

[monorepo.task_defaults.template-only]
run = "printf root-default > template-result.txt"

[monorepo.task_defaults.no-deps]
depends = ["^prepare"]

[monorepo.task_defaults.lint]
env = { ROOT_TASK_DEFAULT = "from-executable-default" }

[monorepo.task_defaults.local]
env = { ROOT_TASK_DEFAULT = "must-not-apply" }

[monorepo.task_defaults."test:unit"]
dir = "{{ invalid"

[task_templates.build-override]
env = { TASK_PRECEDENCE = "from-template", TEMPLATE_PRECEDENCE = "from-template" }
run = "printf template > result.txt"

[task_templates.template-only]
run = "printf template > template-result.txt"

[tasks.local]
run = "printf local > local-result.txt; printf '%s' \"$ROOT_TASK_DEFAULT\" > local-default.txt"
TOML

mkdir -p packages/app
cat <<'JSON' >package.json
{
  "packageManager": "npm@11.0.0",
  "workspaces": ["packages/*"]
}
JSON
cat <<'JSON' >turbo.json
{
  "tasks": {
    "build": {
      "inputs": ["src/**", "package.json"],
      "outputs": ["result.txt"],
      "cache": true,
      "dependsOn": ["^prepare"]
    },
    "cache-only": {
      "cache": true
    },
    "no-deps": {
      "dependsOn": []
    }
  }
}
JSON
cat <<'JSON' >packages/app/package.json
{
  "name": "@scope/app",
  "dependencies": {
    "@scope/bridge": "workspace:*"
  },
  "scripts": {
    "build": "printf inferred > result.txt",
    "cache-only": "printf cached > cache-result.txt",
    "no-deps": "printf independent > no-deps-result.txt",
    "test:unit": "printf tested > test-result.txt"
  }
}
JSON

mkdir -p packages/bridge
cat <<'JSON' >packages/bridge/package.json
{
  "name": "@scope/bridge",
  "dependencies": {
    "@scope/core": "workspace:*"
  }
}
JSON

mkdir -p packages/core
cat <<'JSON' >packages/core/package.json
{
  "name": "@scope/core",
  "scripts": {
    "build": "printf built > result.txt",
    "prepare": "printf prepared > prepare-result.txt"
  }
}
JSON

mkdir -p packages/tool
cat <<'TOML' >packages/tool/mise.toml
[tasks.build]
run = "printf '%s' \"$ROOT_TASK_DEFAULT\" > config-root-default.txt"

[tasks.template-only]
extends = "template-only"
TOML

assert_contains "mise tasks --all" "node:@scope/app#build"
assert_not_contains "mise tasks --all" "node:@scope/app#test:unit"
assert_contains "mise task info 'node:@scope/app#build'" "packages/app/package.json"
assert_contains "mise task info 'node:@scope/app#build'" "turbo.json"
assert_contains "mise task info 'node:@scope/app#build'" "Sources: src/**, package.json"
assert_contains "mise task info 'node:@scope/app#build'" "Outputs: result.txt"
assert_contains "mise task info 'node:@scope/app#build'" "Cache: enabled"
assert "mise task info 'node:@scope/app#build' --json | jq -r '.cache.env[]'" "NODE_ENV"
assert_contains "mise task info 'node:@scope/app#cache-only'" "Cache: enabled"

: >workspace-task.log
mise -q run 'node:@scope/app#no-deps'
assert "cat workspace-task.log" "app:run no-deps --"
: >workspace-task.log

mise -q run //packages/tool:build
assert "cat packages/tool/config-root-default.txt" "from-root"

mise -q run //packages/tool:template-only
assert "cat packages/tool/template-result.txt" "template"

mise -q run 'node:@scope/app#build' -- forwarded
assert "cat packages/app/result.txt" "inferred"
assert "cat packages/app/manager-args.txt" "run build -- forwarded"
assert "cat packages/app/default.txt" "from-root"
assert "cat workspace-task.log" $'core:run prepare --\napp:run build -- forwarded'

printf stale >packages/app/result.txt
mise -q run //packages/app:build
assert "cat packages/app/result.txt" "inferred"

cat <<'TOML' >packages/app/mise.toml
[tasks.build]
extends = "build-override"
env = { TASK_PRECEDENCE = "from-local" }
run = "printf explicit > result.txt; printf '%s' \"$ROOT_TASK_DEFAULT\" > explicit-default.txt; printf '%s' \"$TASK_PRECEDENCE\" > precedence.txt; printf '%s' \"$TEMPLATE_PRECEDENCE\" > template-precedence.txt"

[tasks.deploy]
usage = 'arg "<task>"'
depends = ["^{{usage.task}}"]
run = "printf deployed > deploy-result.txt"
TOML

cat <<'TOML' >packages/core/mise.toml
[tasks.build]
run = "printf explicit-upstream > explicit-result.txt"
TOML

mkdir -p packages/app/mise-tasks
cat <<'SH' >packages/app/mise-tasks/lint
#!/bin/sh
printf '%s' "$ROOT_TASK_DEFAULT" >executable-default.txt
SH
chmod +x packages/app/mise-tasks/lint

printf stale >packages/app/result.txt
mise -q run 'node:@scope/app#build'
assert "cat packages/app/result.txt" "explicit"
assert "cat packages/app/explicit-default.txt" "from-root"
assert "cat packages/app/precedence.txt" "from-local"
assert "cat packages/app/template-precedence.txt" "from-template"
assert "cat packages/core/explicit-result.txt" "explicit-upstream"

printf stale >packages/core/explicit-result.txt
mise -q run //packages/app:deploy build
assert "cat packages/app/deploy-result.txt" "deployed"
assert "cat packages/core/explicit-result.txt" "explicit-upstream"

mise -q run //packages/app:lint
assert "cat packages/app/executable-default.txt" "from-executable-default"

assert_not_contains "MISE_EXPERIMENTAL=0 mise tasks --all" "node:@scope/app#test:unit"
assert_fail_contains "MISE_EXPERIMENTAL=0 mise run 'node:@scope/missing#build'" "no task"

mkdir -p packages/bad
printf '{' >packages/bad/package.json
mise -q run local
assert "cat local-result.txt" "local"
assert "cat local-default.txt" ""

printf stale >packages/app/executable-default.txt
mise -q run //packages/app:lint
assert "cat packages/app/executable-default.txt" "from-executable-default"
assert_fail_contains "mise run //packages/app:build" "inferred tasks and upstream task dependencies from this provider are unavailable"
assert_fail_contains "mise run //packages/app:build" "failed to resolve upstream task dependencies"
