# Shared Initialization Functions

## Ensure dotnet ef Available (Platform-Aware)

**CRITICAL:** On Windows (Git Bash, MSYS2), `dotnet ef` may not be on the shell PATH
even though it's installed. This function fixes PATH before any EF Core command.

```bash
ensure_dotnet_ef() {
  # Quick check: already available?
  if dotnet ef --version &>/dev/null; then
    DOTNET_EF_VERSION=$(dotnet ef --version 2>/dev/null)
    echo "dotnet-ef: $DOTNET_EF_VERSION"
    return 0
  fi

  echo "dotnet-ef not on PATH, attempting platform-aware fix..."

  # Try all known .NET global tools locations
  # - $USERPROFILE/.dotnet/tools  → Windows via Git Bash (USERPROFILE=C:\Users\xxx)
  # - $HOME/.dotnet/tools         → Linux/macOS or Git Bash fallback
  # - $LOCALAPPDATA/Microsoft/dotnet/tools → Windows alternate location
  for TOOLS_DIR in \
    "$USERPROFILE/.dotnet/tools" \
    "$HOME/.dotnet/tools" \
    "$LOCALAPPDATA/Microsoft/dotnet/tools"; do
    if [ -n "$TOOLS_DIR" ] && [ -d "$TOOLS_DIR" ]; then
      export PATH="$TOOLS_DIR:$PATH"
      echo "  PATH += $TOOLS_DIR"
    fi
  done

  # Verify after PATH fix
  if dotnet ef --version &>/dev/null; then
    DOTNET_EF_VERSION=$(dotnet ef --version 2>/dev/null)
    echo "dotnet-ef: $DOTNET_EF_VERSION (found after PATH fix)"
    return 0
  fi

  echo "ERROR: dotnet-ef not available"
  echo "Install with: dotnet tool install --global dotnet-ef"
  echo ""
  echo "If installed but not found, check:"
  echo "  Windows: %USERPROFILE%\\.dotnet\\tools must be in PATH"
  echo "  Linux:   ~/.dotnet/tools must be in PATH"
  exit 1
}

ensure_dotnet_ef
```

**IMPORTANT — WSL pitfall:**
If the shell resolves `$HOME` to `/home/{user}` (WSL path) instead of `/c/Users/{user}` (Git Bash),
the .NET SDK may not be found even if `dotnet-ef` is. Use `$USERPROFILE` first on Windows.

## Detect EF Core Project

```bash
detect_efcore_project() {
  # Find project with EF Core reference
  CSPROJ=$(find src-name "*.csproj" -exec grep -l "Microsoft.EntityFrameworkCore" {} \; | head -1)

  if [ -z "$CSPROJ" ]; then
    echo "ERROR: No EF Core project found"
    exit 1
  fi

  PROJECT_DIR=$(dirname "$CSPROJ")
  PROJECT_NAME=$(basename "$CSPROJ" .csproj)
  MIGRATIONS_DIR="$PROJECT_DIR/Persistence/Migrations"

  # Find startup and infrastructure projects
  STARTUP_PROJECT=$(find src-name "*.Api.csproj" -o -name "*Web.csproj" | head -1)
  INFRA_PROJECT=$(find src-name "*Infrastructure.csproj" | head -1)
  [ -z "$INFRA_PROJECT" ] && INFRA_PROJECT="$CSPROJ"

  echo "Project: $PROJECT_NAME"
  echo "Migrations: $MIGRATIONS_DIR"
}
```

## Detect DbContext (Core vs Extensions)

```bash
detect_dbcontext() {
  # Priority 1: SmartStack.Domain exists → SmartStack source project (Core only)
  if find src-type d -name "SmartStack.Domain" | grep -q .; then
    DBCONTEXT="CoreDbContext"
    DBCONTEXT_TYPE="core"
    SCHEMA="core"
    RUN_BOTH=false
    echo "DbContext: CoreDbContext (SmartStack.Domain found)"
    return
  fi

  # Priority 2: Client project with SmartStack NuGet → BOTH contexts
  if find src-name "*.csproj" -exec grep -ql "PackageReference.*SmartStack" {} \; 2>/dev/null; then
    DBCONTEXT="CoreDbContext"
    DBCONTEXT_TYPE="both"
    SCHEMA="core"
    RUN_BOTH=true
    echo "DbContext: Both (Core from SmartStack NuGet + Extensions local)"
    echo "  Deploy order: CoreDbContext → ExtensionsDbContext"
    return
  fi

  # Priority 3: Scan for DbContext in code
  CORE_CTX=$(find src-name "*.cs" -exec grep -l "CoreDbContext" {} \; 2>/dev/null | head -1)
  EXT_CTX=$(find src-name "*.cs" -exec grep -l "ExtensionsDbContext" {} \; 2>/dev/null | head -1)

  if [ -n "$CORE_CTX" ] && [ -n "$EXT_CTX" ]; then
    DBCONTEXT="CoreDbContext"
    DBCONTEXT_TYPE="both"
    SCHEMA="core"
    RUN_BOTH=true
    echo "DbContext: Both (CoreDbContext + ExtensionsDbContext found)"
  elif [ -n "$CORE_CTX" ] && [ -z "$EXT_CTX" ]; then
    DBCONTEXT="CoreDbContext"
    DBCONTEXT_TYPE="core"
    SCHEMA="core"
    RUN_BOTH=false
  elif [ -z "$CORE_CTX" ] && [ -n "$EXT_CTX" ]; then
    DBCONTEXT="ExtensionsDbContext"
    DBCONTEXT_TYPE="extensions"
    SCHEMA="extensions"
    RUN_BOTH=false
  else
    DBCONTEXT=""
    DBCONTEXT_TYPE=""
    SCHEMA=""
    RUN_BOTH=false
  fi
}
```

## Detect Environment

```bash
detect_environment() {
  API_DIR=$(find src-type d -name "*.Api" | head -1)
  [ -z "$API_DIR" ] && API_DIR="src/SmartStack.Api"

  # Priority: --env flag > appsettings.Local.json > error
  if [ -n "$ENV_FLAG" ]; then
    CONFIG_FILE="$API_DIR/appsettings.${ENV_FLAG}.json"
  elif [ -f "$API_DIR/appsettings.Local.json" ]; then
    CONFIG_FILE="$API_DIR/appsettings.Local.json"
    SELECTED_ENV="Local"
  else
    echo "ERROR: No appsettings.Local.json found"
    echo "Create one or use --env flag"
    exit 1
  fi

  echo "Environment: $SELECTED_ENV"
  echo "Config: $CONFIG_FILE"
}
```

## Determine Base Branch

```bash
determine_base_branch() {
  CURRENT_BRANCH=$(git branch --show-current)

  case "$CURRENT_BRANCH" in
    feature/*)
      BASE_BRANCH="develop"
      BRANCH_TYPE="feature"
      ;;
    release/*)
      BASE_BRANCH="main"
      BRANCH_TYPE="release"
      ;;
    hotfix/*)
      BASE_BRANCH="main"
      BRANCH_TYPE="hotfix"
      ;;
    develop)
      BASE_BRANCH="main"
      BRANCH_TYPE="develop"
      ;;
    main|master)
      echo "ERROR: Cannot run on main/master branch"
      exit 1
      ;;
    *)
      BASE_BRANCH="develop"
      BRANCH_TYPE="unknown"
      ;;
  esac

  echo "Branch: $CURRENT_BRANCH ($BRANCH_TYPE)"
  echo "Base: $BASE_BRANCH"
}
```

## Block Production

```bash
block_production() {
  # Check for production indicators (case-insensitive)
  if grep -qi '"Production"' "$CONFIG_FILE" 2>/dev/null; then
    echo "BLOCKED: Production environment detected in $CONFIG_FILE"
    exit 1
  fi

  # Case-insensitive database name check
  DB_LOWER=$(echo "$DATABASE_NAME" | tr '[:upper:]' '[:lower:]')
  if [[ "$DB_LOWER" == *"prod"* ]] || [[ "$DB_LOWER" == *"production"* ]]; then
    echo "BLOCKED: Production database detected ($DATABASE_NAME)"
    exit 1
  fi

  # Environment name check (case-insensitive)
  ENV_LOWER=$(echo "$SELECTED_ENV" | tr '[:upper:]' '[:lower:]')
  if [[ "$ENV_LOWER" == "production" ]] || [[ "$ENV_LOWER" == "prod" ]]; then
    echo "BLOCKED: Production environment selected ($SELECTED_ENV)"
    exit 1
  fi
}
```

## Dual Context Helper

```bash
# Helper for steps that need to run for both contexts when RUN_BOTH=true
# Usage: run_for_contexts "command_or_function"
# Executes with CoreDbContext first, then ExtensionsDbContext
# Maintains deploy order constraint: Core MUST run first

run_for_contexts() {
  if [ "$RUN_BOTH" = "true" ]; then
    echo "=== Running for CoreDbContext (core schema) ==="
    DBCONTEXT="CoreDbContext"
    DBCONTEXT_TYPE="core"
    SCHEMA="core"
    eval "$1"

    echo ""
    echo "=== Running for ExtensionsDbContext (extensions schema) ==="
    DBCONTEXT="ExtensionsDbContext"
    DBCONTEXT_TYPE="extensions"
    SCHEMA="extensions"
    eval "$1"
  else
    eval "$1"
  fi
}
```
