// ABOUTME: Example demonstrating EdgeXR SDK usage for app deployment workflow
// ABOUTME: Shows app creation, querying, and cleanup using the typed SDK APIs

package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"strings"
	"time"

	v2 "edp.buildth.ing/DevFW-CICD/edge-connect-client/v2/sdk/edgeconnect/v2"
)

func main() {
	// Configure SDK client
	baseURL := getEnvOrDefault("EDGEXR_BASE_URL", "https://hub.apps.edge.platform.mg3.mdb.osc.live")

	// Support both token-based and username/password authentication
	token := getEnvOrDefault("EDGEXR_TOKEN", "")
	username := getEnvOrDefault("EDGEXR_USERNAME", "")
	password := getEnvOrDefault("EDGEXR_PASSWORD", "")

	var edgeClient *v2.Client

	if token != "" {
		// Use static token authentication
		fmt.Println("🔐 Using Bearer token authentication")
		edgeClient = v2.NewClient(baseURL,
			v2.WithHTTPClient(&http.Client{Timeout: 30 * time.Second}),
			v2.WithAuthProvider(v2.NewStaticTokenProvider(token)),
			v2.WithLogger(log.Default()),
		)
	} else if username != "" && password != "" {
		// Use username/password authentication (matches existing client pattern)
		fmt.Println("🔐 Using username/password authentication")
		edgeClient = v2.NewClientWithCredentials(baseURL, username, password,
			v2.WithHTTPClient(&http.Client{Timeout: 30 * time.Second}),
			v2.WithLogger(log.Default()),
		)
	} else {
		log.Fatal("Authentication required: Set either EDGEXR_TOKEN or both EDGEXR_USERNAME and EDGEXR_PASSWORD")
	}

	ctx := context.Background()

	// Example application to deploy
	app := &v2.NewAppInput{
		Region: "EU",
		App: v2.App{
			Key: v2.AppKey{
				Organization: "edp2",
				Name:         "my-edge-app",
				Version:      "1.0.0",
			},
			Deployment:       "docker",
			ImageType:        "ImageTypeDocker",
			ImagePath:        "https://registry-1.docker.io/library/nginx:latest",
			DefaultFlavor:    v2.Flavor{Name: "EU.small"},
			ServerlessConfig: v2.ServerlessConfig{},
			AllowServerless:  false,
		},
	}

	// Demonstrate app lifecycle
	if err := demonstrateAppLifecycle(ctx, edgeClient, app); err != nil {
		log.Fatalf("App lifecycle demonstration failed: %v", err)
	}

	fmt.Println("✅ SDK example completed successfully!")
}

func demonstrateAppLifecycle(ctx context.Context, edgeClient *v2.Client, input *v2.NewAppInput) error {
	appKey := input.App.Key
	region := input.Region

	fmt.Printf("🚀 Demonstrating EdgeXR SDK with app: %s/%s v%s\n",
		appKey.Organization, appKey.Name, appKey.Version)

	// Step 1: Create the application
	fmt.Println("\n1. Creating application...")
	if err := edgeClient.CreateApp(ctx, input); err != nil {
		return fmt.Errorf("failed to create app: %+v", err)
	}
	fmt.Printf("✅ App created: %s/%s v%s\n", appKey.Organization, appKey.Name, appKey.Version)

	// Step 2: Query the application
	fmt.Println("\n2. Querying application...")
	app, err := edgeClient.ShowApp(ctx, appKey, region)
	if err != nil {
		return fmt.Errorf("failed to show app: %w", err)
	}
	fmt.Printf("✅ App found: %s/%s v%s (deployment: %s)\n",
		app.Key.Organization, app.Key.Name, app.Key.Version, app.Deployment)

	// Step 3: List applications in the organization
	fmt.Println("\n3. Listing applications...")
	filter := v2.AppKey{Organization: appKey.Organization}
	apps, err := edgeClient.ShowApps(ctx, filter, region)
	if err != nil {
		return fmt.Errorf("failed to list apps: %w", err)
	}
	fmt.Printf("✅ Found %d applications in organization '%s'\n", len(apps), appKey.Organization)

	// Step 4: Clean up - delete the application
	fmt.Println("\n4. Cleaning up...")
	if err := edgeClient.DeleteApp(ctx, appKey, region); err != nil {
		return fmt.Errorf("failed to delete app: %w", err)
	}
	fmt.Printf("✅ App deleted: %s/%s v%s\n", appKey.Organization, appKey.Name, appKey.Version)

	// Step 5: Verify deletion
	fmt.Println("\n5. Verifying deletion...")
	_, err = edgeClient.ShowApp(ctx, appKey, region)
	if err != nil {
		if strings.Contains(fmt.Sprintf("%v", err), v2.ErrResourceNotFound.Error()) {
			fmt.Printf("✅ App successfully deleted (not found)\n")
		} else {
			return fmt.Errorf("unexpected error verifying deletion: %w", err)
		}
	} else {
		return fmt.Errorf("app still exists after deletion")
	}

	return nil
}

func getEnvOrDefault(key, defaultValue string) string {
	if value := os.Getenv(key); value != "" {
		return value
	}
	return defaultValue
}
