#!/bin/bash
set -e

echo "🚀 Building .NET client with OpenAPI generation and Docker packaging..."

# Define paths
CLIENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "${CLIENT_DIR}/../.." && pwd)"
DIST_DIR="${ROOT_DIR}/dist/clients/dotnet"

# Ensure dist directory exists
mkdir -p "${DIST_DIR}"

echo "📂 Project structure:"
echo "  Root: ${ROOT_DIR}"
echo "  Client: ${CLIENT_DIR}"
echo "  Output: ${DIST_DIR}"

# Step 1: Extract OpenAPI spec from server build
echo ""
echo "🔧 Step 1: Building server and extracting OpenAPI specification..."
cd "${ROOT_DIR}"

# Build server to extract OpenAPI spec
if ! ./gradlew :server:build -x test; then
    echo "❌ Server build failed. Cannot extract OpenAPI spec."
    exit 1
fi

# Create API directory and copy OpenAPI spec
mkdir -p "${CLIENT_DIR}/api"
server_spec="${ROOT_DIR}/server/build/classes/java/main/openapi-plugin/openapi-default.json"

if [ -f "$server_spec" ]; then
    cp "$server_spec" "${CLIENT_DIR}/api/openapi.json"
    echo "✅ OpenAPI spec extracted to: ${CLIENT_DIR}/api/openapi.json"
else
    echo "❌ OpenAPI spec not found at: $server_spec"
    exit 1
fi

# Step 2: Generate .NET client using OpenAPI Generator
echo ""
echo "🔧 Step 2: Generating .NET client from OpenAPI specification..."
cd "${CLIENT_DIR}"

# Backup only custom files that shouldn't be overwritten by code generation
echo "📦 Backing up custom files..."
mkdir -p .backup
cp -f Goodmem.Client.sln .backup/ 2>/dev/null || true
cp -f Dockerfile .backup/ 2>/dev/null || true
cp -f build.sh .backup/ 2>/dev/null || true
# Backup custom streaming functionality
cp -f src/Pairsystems.Goodmem.Client/StreamingClient.cs .backup/ 2>/dev/null || true
# Note: We don't backup generated client code - we want to use the newly generated version

# Use OpenAPI Generator to generate .NET client
echo "🔄 Running OpenAPI Generator..."
docker run --rm \
  -v ${PWD}:/local \
  --user $(id -u):$(id -g) \
  openapitools/openapi-generator-cli:latest generate \
  -i /local/api/openapi.json \
  -g csharp \
  -o /local \
  --package-name Pairsystems.Goodmem.Client \
  --additional-properties=packageVersion=1.0.5,clientPackage=Pairsystems.Goodmem.Client,packageCompany="Pair Systems Inc",packageAuthors="Pair Systems Inc",packageCopyright="Copyright (c) Pair Systems Inc",packageDescription="C# client library for GoodMem API - vector-based memory storage and retrieval",packageTitle="GoodMem .NET Client",targetFramework=net8.0,library=httpclient,packageName=Pairsystems.Goodmem.Client \
  --type-mappings=binary=string

# Note: Files are created with correct permissions due to --user flag
echo "✅ Files generated with correct user permissions"

# Remove the incorrect Org.OpenAPITools directory that gets generated
echo "🔧 Removing incorrect Org.OpenAPITools namespace directory..."
rm -rf src/Org.OpenAPITools/
rm -rf src/Org.OpenAPITools.Test/
rm -f Org.OpenAPITools.sln

# Fix the incorrect nested namespace imports in test files
echo "🔧 Fixing namespace imports in test files..."
find src/Pairsystems.Goodmem.Client.Test -name "*.cs" -type f -exec sed -i 's/using Pairsystems\.Goodmem\.Client\.Pairsystems\.Goodmem\.Client;/using Pairsystems.Goodmem.Client;/g' {} \; 2>/dev/null || true

# Fix OpenAPI generator FileParameter bug for binary fields
echo "🔧 Fixing FileParameter type mappings for binary fields..."
# Replace FileParameter with string for originalContent in Memory model
sed -i 's/public FileParameter OriginalContent { get; set; }/public string OriginalContent { get; set; }/g' src/Pairsystems.Goodmem.Client/Model/Memory.cs
# Also fix the constructor parameter if it exists
sed -i 's/FileParameter originalContent = default/string originalContent = default/g' src/Pairsystems.Goodmem.Client/Model/Memory.cs
echo "✅ Fixed FileParameter to string for originalContent field in Memory.cs"

# Fix EmitDefaultValue for originalContentB64 field to prevent null serialization
echo "🔧 Fixing EmitDefaultValue for originalContentB64 field..."
sed -i 's/\[DataMember(Name = "originalContentB64", EmitDefaultValue = true)\]/[DataMember(Name = "originalContentB64", EmitDefaultValue = false)]/g' src/Pairsystems.Goodmem.Client/Model/MemoryCreationRequest.cs

# Restore only custom files (not generated code)
echo "📦 Restoring custom files..."
cp -f .backup/Goodmem.Client.sln . 2>/dev/null || true
cp -f .backup/Dockerfile . 2>/dev/null || true
cp -f .backup/build.sh . 2>/dev/null || true
# Restore custom streaming functionality
cp -f .backup/StreamingClient.cs src/Pairsystems.Goodmem.Client/ 2>/dev/null || true
# Note: We don't restore generated client code - we want to use the newly generated version
rm -rf .backup

# Fix documentation to add StreamingClient examples
echo "🔧 Fixing documentation..."
if [ -f "fix_docs.sh" ]; then
  chmod +x fix_docs.sh
  ./fix_docs.sh
else
  echo "⚠️  fix_docs.sh not found, skipping documentation fixes"
fi

# Fix README to add StreamingClient usage examples
echo "🔧 Fixing README..."
if [ -f "fix_readme.sh" ]; then
  chmod +x fix_readme.sh
  ./fix_readme.sh
else
  echo "⚠️  fix_readme.sh not found, skipping README fixes"
fi

echo "✅ .NET client generated successfully"

# Note: README authentication and streaming documentation is handled by fix_readme.sh above

# Step 3: Test the generated client
echo ""
echo "🔧 Step 3: Testing generated .NET client..."

# Build the main client library
echo "🔨 Building main client library..."
dotnet build src/Pairsystems.Goodmem.Client/Pairsystems.Goodmem.Client.csproj --configuration Release

# Build the test project
echo "🔨 Building test project..."
dotnet build src/Pairsystems.Goodmem.Client.Test/Pairsystems.Goodmem.Client.Test.csproj --configuration Release

# Run the tests
echo "🧪 Running .NET client tests..."
dotnet test src/Pairsystems.Goodmem.Client.Test/Pairsystems.Goodmem.Client.Test.csproj --configuration Release --verbosity normal

echo "✅ .NET client library built and tested successfully"

# Step 4: Build using Docker for packaging
echo ""
echo "🔧 Step 4: Building .NET client with Docker for reproducible packaging..."

# Build the Docker image
docker build -t goodmem-dotnet-client-builder "${CLIENT_DIR}"

# Run container to extract built artifacts
CONTAINER_ID=$(docker create goodmem-dotnet-client-builder)

# Extract built artifacts from the correct path (Docker container has files at /app, not /app/src)
docker cp "${CONTAINER_ID}:/app/Pairsystems.Goodmem.Client/bin/Release/net8.0/." "${DIST_DIR}/" || true

# Clean up container
docker rm "${CONTAINER_ID}" > /dev/null

# Check if build produced the DLLs
if ls "${DIST_DIR}"/*.dll &>/dev/null; then
    echo "✅ .NET client built and packaged successfully!"
    echo "📂 Output files available in: ${DIST_DIR}/"
    echo ""
    echo "📋 Generated files:"
    ls -la "${DIST_DIR}/" | head -10
else
    echo "⚠️ No build artifacts found. Build may have failed."
    exit 1
fi

echo ""
echo "🎉 .NET client build completed successfully!"
echo "   1. ✅ OpenAPI spec extracted from server"
echo "   2. ✅ .NET client code generated"  
echo "   3. ✅ Client library compiled"
echo "   4. ✅ Docker packaging completed"
echo ""
echo "Next steps:"
echo "  - Test the client locally"
echo "  - Push to GitHub to trigger publish-dotnet-nuget.yml workflow"