#!/usr/bin/env bash
set -uo pipefail

DIR="$(cd "$(dirname "$0")" && pwd)"
source "$DIR/runtime.sh"

# ============================================================
# Inline concept tests for the canonical @in / @out API
# ============================================================

@operation.git.sign() {
    @in.string key
    @out.string signature
    @note "Requires GPG key on the local machine"

    @do() {
        local key

        key=$(@in key)
        @out.string signature "signed-by-$key"
        @return.out
    }

    @undo() {
        @return "$(@string "undone:git.sign")"
    }

    @is-done() {
        return 1
    }
}

@operation.git.tag() {
    @in.string version
    @out.string tag

    @do() {
        local version

        version=$(@in version)
        @out.string tag "v$version"
        @return.out
    }

    @is-done() {
        return 1
    }
}

@type.port() {
    @is() {
        local value="$1"

        @int.is "$value" || return 1
        if (( value < 1 || value > 65535 )); then
            @throw "port must be 1-65535"
            return 1
        fi

        @return "$value"
    }

    @default() {
        @return 8080
    }
}

echo "=== Loading ==="
load_op "@operation.git.sign";  echo "  git.sign"
load_op "@operation.git.tag";   echo "  git.tag"
load_type "@type.port";         echo "  type:port"

echo ""
echo "=== Registry ==="
for k in "${!__reg_inputs[@]}"; do echo "  $k inputs: ${__reg_inputs[$k]}"; done
for k in "${!__reg_outputs[@]}"; do echo "  $k outputs: ${__reg_outputs[$k]}"; done
for k in "${!__reg_contracts[@]}"; do echo "  $k contracts: [${__reg_contracts[$k]}]"; done

echo ""
echo "=== Dispatch map ==="
for k in $(printf '%s\n' "${!__dispatch[@]}" | sort); do
    echo "  $k -> ${__dispatch[$k]}"
done

echo ""
echo "=== Collision: @do should not exist raw ==="
declare -F @do &>/dev/null && echo "  FAIL: @do leaked" || echo "  PASS: @do cleaned up"

echo ""
echo "=== Dispatch calls ==="
echo "  git.sign @do:   $(dispatch "git.sign" "do" "my-gpg-key")"
echo "  git.sign @undo: $(dispatch "git.sign" "undo")"
echo "  git.tag  @do:   $(dispatch "git.tag" "do" "1.2.3")"

echo ""
echo "=== Type constructors ==="
echo "  @port default: $(@port)"
echo "  @port 8080:    $(@port 8080)"

echo "  @port.is 443: valid?"
@port.is 443 && echo "    PASS" || echo "    FAIL"

echo "  @port.is 99999: should reject"
@port.is 99999 2>/dev/null && echo "    FAIL" || echo "    PASS"

echo "  @port.is abc: should reject"
@port.is "abc" 2>/dev/null && echo "    FAIL" || echo "    PASS"

echo ""
echo "=== No leaked inner functions ==="
ok=true
for fn in @do @undo @is-done @is @default; do
    declare -F "$fn" &>/dev/null && { echo "  LEAK: $fn"; ok=false; }
done
$ok && echo "  PASS"
