#!/bin/bash
set -e

# Script to build and pack NuGet packages in dependency order
# Usage: ./build-and-pack-nuget.sh

# Get all packable projects from the solution filter
# Extract project paths from the solution filter and convert Windows paths to Unix paths
PROJECTS=$(jq -r '.solution.projects[]' War3NetPublish.slnf | sed 's/\\/\//g' | grep -v "Tests" | tr '\n' ';')

echo "=== Found projects to publish ==="
echo "$PROJECTS" | tr ';' '\n'
echo "=================================="

# Create a temporary file to track which projects have been built
# Using semicolon delimiters for exact matching
BUILT_PROJECTS=";"

# Function to check if all dependencies of a project are built
can_build_project() {
  local project=$1
  # Get the dependencies - dotnet list outputs them with paths like ..\ProjectName\ProjectName.csproj
  # We need to extract just the project name from the filename
  local deps=$(dotnet list "$project" reference 2>/dev/null | grep '\.csproj$' | while read -r line; do
    # Remove everything up to the last backslash, then remove .csproj extension
    echo "$line" | sed 's/.*\\//' | sed 's/\.csproj$//'
  done | tr '\n' ' ')
  
  for dep in $deps; do
    if ! echo "$BUILT_PROJECTS" | grep -q ";$dep;"; then
      return 1
    fi
  done
  return 0
}

# Build projects in dependency order
REMAINING_PROJECTS="$PROJECTS"
ITERATION=0
MAX_ITERATIONS=20

while [ -n "$REMAINING_PROJECTS" ] && [ $ITERATION -lt $MAX_ITERATIONS ]; do
  ITERATION=$((ITERATION + 1))
  
  PROJECTS_TO_BUILD=""
  STILL_REMAINING=""
  
  # Process each project using semicolon as delimiter
  while IFS= read -r project; do
    if [ -n "$project" ]; then
      if can_build_project "$project"; then
        PROJECTS_TO_BUILD="${PROJECTS_TO_BUILD}${project};"
      else
        STILL_REMAINING="${STILL_REMAINING}${project};"
      fi
    fi
  done < <(echo "$REMAINING_PROJECTS" | tr ';' '\n')
  
  if [ -z "$PROJECTS_TO_BUILD" ] && [ -n "$STILL_REMAINING" ]; then
    echo ""
    echo "ERROR: Circular dependency detected or unable to resolve dependencies"
    echo "Projects that cannot be built:"
    echo "$STILL_REMAINING" | tr ';' '\n' | while read -r p; do
      if [ -n "$p" ]; then
        echo "  - $(basename $(dirname "$p"))"
        echo "    Dependencies: $(dotnet list "$p" reference 2>/dev/null | grep -E "^\s+.*\.csproj" | sed 's/.*\///' | sed 's/\.csproj.*//' | tr '\n' ' ')"
      fi
    done
    echo "Already built: $BUILT_PROJECTS"
    exit 1
  fi
  
  echo ""
  echo "Projects to build in iteration $ITERATION:"
  if [ -n "$PROJECTS_TO_BUILD" ]; then
    OLD_IFS="$IFS"
    IFS=';'
    for p in $PROJECTS_TO_BUILD; do
      [ -n "$p" ] && echo "  - $(basename $(dirname "$p"))"
    done
    IFS="$OLD_IFS"
  else
    echo "  (none)"
  fi
  
  # Build and pack projects that are ready
  while IFS= read -r project; do
    if [ -z "$project" ]; then continue; fi
    PROJECT_NAME=$(basename $(dirname "$project"))
    echo "Building $PROJECT_NAME..."
    
    # Restore with local feed for dependencies from previous iterations
    dotnet restore "$project" -p:Configuration=Release --verbosity minimal --force --no-cache
    
    # Build the project
    dotnet build "$project" --configuration Release --no-restore --verbosity minimal
    
    # Pack directly to artifacts with project name folder structure for proper NuGet feed
    dotnet pack "$project" --configuration Release --no-build --output "./artifacts/${PROJECT_NAME}" -p:PACK=true --verbosity minimal
    
    BUILT_PROJECTS="${BUILT_PROJECTS}${PROJECT_NAME};"
  done < <(echo "$PROJECTS_TO_BUILD" | tr ';' '\n')
  
  # Clear NuGet cache for local packages to ensure newly built packages are available
  dotnet nuget locals temp -c
  
  REMAINING_PROJECTS="$STILL_REMAINING"
done

if [ $ITERATION -eq $MAX_ITERATIONS ]; then
  echo "Error: Maximum iterations reached. Possible circular dependency."
  exit 1
fi

echo ""
echo "Successfully created $(ls ./artifacts/*/*.nupkg 2>/dev/null | wc -l) packages"