//go:build ignore

package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"sync"
)

type Platform struct {
	GOOS      string
	GOARCH    string
	BuildTags string
}

// All supported platforms (except freebsd)
var platforms = []Platform{
	{GOOS: "linux", GOARCH: "amd64"},
	{GOOS: "linux", GOARCH: "386"},
	{GOOS: "linux", GOARCH: "arm64"},
	{GOOS: "linux", GOARCH: "riscv64"},
	{GOOS: "linux", GOARCH: "ppc64le", BuildTags: "exp.linuxppc64le"},
	{GOOS: "darwin", GOARCH: "amd64"},
	{GOOS: "darwin", GOARCH: "arm64"},
	{GOOS: "windows", GOARCH: "amd64"},
	{GOOS: "windows", GOARCH: "arm64", BuildTags: "exp.winarm64"},
}

const (
	colorRed    = "\033[0;31m"
	colorGreen  = "\033[0;32m"
	colorYellow = "\033[1;33m"
	colorReset  = "\033[0m"
)

func main() {
	// Find the project root by looking for go.mod
	projectRoot := findProjectRoot()
	if projectRoot == "" {
		log.Fatal("Could not find project root (no go.mod found)")
	}

	// Change to project root
	if err := os.Chdir(projectRoot); err != nil {
		log.Fatalf("Failed to change to project root: %v", err)
	}

	fmt.Println("Generating capslock output files for all supported platforms...")
	fmt.Println("==================================================")

	successCount := 0
	failureCount := 0
	var failedPlatforms []string

	var wg sync.WaitGroup

	for _, platform := range platforms {
		wg.Add(1)
		go func() {
			defer wg.Done()
			if err := generateCapslock(platform); err != nil {
				failureCount++
				failedPlatforms = append(failedPlatforms, fmt.Sprintf("%s/%s", platform.GOOS, platform.GOARCH))
				fmt.Printf("Generating for %s/%s... %sFAILED%s\n", platform.GOOS, platform.GOARCH, colorRed, colorReset)
				fmt.Printf("  Error: %v\n", err)
			} else {
				successCount++
				fmt.Printf("Generating for %s/%s... %sSUCCESS%s\n",
					platform.GOOS, platform.GOARCH, colorGreen, colorReset)
			}
		}()
	}
	wg.Wait()

	fmt.Println("==================================================")
	fmt.Println("Generation complete!")
	fmt.Printf("  %sSuccessful: %d%s\n", colorGreen, successCount, colorReset)
	fmt.Printf("  %sFailed: %d%s\n", colorRed, failureCount, colorReset)

	if len(failedPlatforms) > 0 {
		fmt.Println("\nFailed platforms:")
		for _, platform := range failedPlatforms {
			fmt.Printf("  - %s\n", platform)
		}
		fmt.Println("\nCheck the output files for error details.")
	}

	fmt.Println("\nGenerated files:")
	matches, _ := filepath.Glob("_scripts/capslock*.txt")
	for _, match := range matches {
		info, err := os.Stat(match)
		if err == nil {
			fmt.Printf("  %s (%d bytes)\n", match, info.Size())
		}
	}

	if failureCount > 0 {
		os.Exit(1)
	}
}

func generateCapslock(platform Platform) error {
	outputFile := fmt.Sprintf("_scripts/capslock_%s_%s-output.txt", platform.GOOS, platform.GOARCH)

	args := []string{"run", "github.com/google/capslock/cmd/capslock@latest"}
	if platform.BuildTags != "" {
		args = append(args, "-buildtags", platform.BuildTags)
	}
	args = append(args, "-packages", "./cmd/dlv")

	cmd := exec.Command("go", args...)
	cmd.Env = append(os.Environ(),
		fmt.Sprintf("GOOS=%s", platform.GOOS),
		fmt.Sprintf("GOARCH=%s", platform.GOARCH),
	)

	output, err := cmd.CombinedOutput()

	if writeErr := os.WriteFile(outputFile, output, 0644); writeErr != nil {
		return fmt.Errorf("failed to write output file: %w", writeErr)
	}

	if err != nil {
		return fmt.Errorf("capslock failed: %w", err)
	}

	return nil
}

func findProjectRoot() string {
	dir, err := os.Getwd()
	if err != nil {
		return ""
	}

	for {
		if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
			return dir
		}

		parent := filepath.Dir(dir)
		if parent == dir {
			break
		}
		dir = parent
	}

	return ""
}
