#!/bin/bash
# Detect which SDKs changed in this commit/PR
# Output: JSON array of changed languages

set -e

# Manual triggers for full matrix:
# 1. CI variable: TEST_ALL_SDKS=true
# 2. Tag push (releases test everything)

if [ "$TEST_ALL_SDKS" = "true" ]; then
    echo '{"changed_langs": ["all"], "reason": "TEST_ALL_SDKS variable set", "test_all": true}'
    exit 0
fi

if [ -n "$CI_COMMIT_TAG" ]; then
    echo '{"changed_langs": ["all"], "reason": "Tag release - testing all SDKs", "test_all": true}'
    exit 0
fi

# Get the base branch for comparison
if [ -n "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
    # MR context
    BASE="origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
elif [ "$CI_COMMIT_BRANCH" = "main" ]; then
    # Push to main - compare with previous commit
    BASE="HEAD~1"
else
    # Fallback
    BASE="origin/main"
fi

# Get all changed files in this commit
CHANGED_FILES=$(git diff --name-only "$BASE...HEAD" 2>/dev/null || echo "")

# Extract unique languages from TWO sources:
# 1. Root-level files (un.py, un.go, un.c, etc.)
# 2. Client directory files (clients/python/*, clients/go/*, clients/c/*, etc.)

CHANGED_LANGS=$(
  {
    # Root-level implementations (un.py, un.c, etc.)
    echo "$CHANGED_FILES" | grep -E '^un\.' | sed 's/un\.\([^.]*\).*/\1/'
    # Client directory implementations (clients/python/, clients/c/, etc.)
    echo "$CHANGED_FILES" | grep -E '^clients/([^/]+)/' | sed 's|^clients/\([^/]*\)/.*|\1|'
  } | sort -u || echo ""
)

# Map file extensions to language names (for root-level un.* files)
declare -A LANG_MAP=(
    [py]="python"
    [js]="javascript"
    [ts]="typescript"
    [go]="go"
    [rb]="ruby"
    [php]="php"
    [pl]="perl"
    [lua]="lua"
    [sh]="bash"
    [rs]="rust"
    [java]="java"
    [cs]="csharp"
    [cpp]="cpp"
    [c]="c"
    [hs]="haskell"
    [kt]="kotlin"
    [ex]="elixir"
    [erl]="erlang"
    [cr]="crystal"
    [dart]="dart"
    [nim]="nim"
    [jl]="julia"
    [r]="r"
    [groovy]="groovy"
    [clj]="clojure"
    [fs]="fsharp"
    [ml]="ocaml"
    [m]="objc"
    [d]="d"
    [v]="vlang"
    [zig]="zig"
    [f90]="fortran"
    [cob]="cobol"
    [scm]="scheme"
    [lisp]="lisp"
    [tcl]="tcl"
    [awk]="awk"
    [pro]="prolog"
    [forth]="forth"
    [ps1]="powershell"
    [raku]="raku"
)

# Map directory names from clients/ to language names (clients/ already has language names)
declare -A DIR_MAP=(
    [python]="python"
    [javascript]="javascript"
    [typescript]="typescript"
    [go]="go"
    [ruby]="ruby"
    [php]="php"
    [perl]="perl"
    [lua]="lua"
    [bash]="bash"
    [rust]="rust"
    [java]="java"
    [csharp]="csharp"
    [cpp]="cpp"
    [c]="c"
    [haskell]="haskell"
    [kotlin]="kotlin"
    [elixir]="elixir"
    [erlang]="erlang"
    [crystal]="crystal"
    [dart]="dart"
    [nim]="nim"
    [julia]="julia"
    [r]="r"
    [groovy]="groovy"
    [clojure]="clojure"
    [fsharp]="fsharp"
    [ocaml]="ocaml"
    [objc]="objc"
    [d]="d"
    [vlang]="vlang"
    [zig]="zig"
    [fortran]="fortran"
    [cobol]="cobol"
    [scheme]="scheme"
    [lisp]="lisp"
    [tcl]="tcl"
    [awk]="awk"
    [prolog]="prolog"
    [forth]="forth"
    [powershell]="powershell"
    [raku]="raku"
)

# Also check for changes in test files, scripts, or core infra
if echo "$CHANGED_FILES" | grep -qE '^(tests/|scripts/|\.gitlab-ci\.yml|clients/\{.*\}/)'; then
    # If tests, scripts, or multi-language client templates changed, test ALL SDKs
    echo '{"changed_langs": ["all"], "reason": "Core infrastructure changed", "test_all": true}'
    exit 0
fi

# Convert file extensions and directory names to language names
LANGS_JSON="["
FIRST=true
for ITEM in $CHANGED_LANGS; do
    # Try directory map first (for clients/python/, etc.)
    LANG="${DIR_MAP[$ITEM]}"
    # Fallback to extension map (for un.py, etc.)
    LANG="${LANG:-${LANG_MAP[$ITEM]}}"
    # Fallback to item as-is if not in any map
    LANG="${LANG:-$ITEM}"

    if [ "$FIRST" = true ]; then
        LANGS_JSON="$LANGS_JSON\"$LANG\""
        FIRST=false
    else
        LANGS_JSON="$LANGS_JSON,\"$LANG\""
    fi
done
LANGS_JSON="$LANGS_JSON]"

# If no changes detected, test nothing (skip tests)
if [ "$LANGS_JSON" = "[]" ]; then
    echo '{"changed_langs": [], "reason": "No SDK files changed", "test_all": false}'
    exit 0
fi

echo "{\"changed_langs\": $LANGS_JSON, \"test_all\": false}"
