package main

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

	"github.com/icholy/digest"

	"github.com/tidbcloud/tidb-management-service/functional-test/pkg/byocfixture"
)

const commandTimeout = 75 * time.Minute

func main() {
	if err := run(os.Args[1:]); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func run(args []string) error {
	if len(args) != 1 || (args[0] != "create" && args[0] != "cleanup") {
		return errors.New("usage: byoc-resource-pool-fixture create|cleanup")
	}
	host := strings.TrimSpace(os.Getenv("OPEN_API_DEDICATED_HOST"))
	apiKey := strings.TrimSpace(os.Getenv("OPEN_API_DEDICATED_API_KEY"))
	username, password, ok := strings.Cut(apiKey, ":")
	if host == "" || !ok || username == "" || password == "" {
		return errors.New("OPEN_API_DEDICATED_HOST and a valid OPEN_API_DEDICATED_API_KEY are required")
	}
	httpClient := &http.Client{
		Timeout: 30 * time.Second,
		Transport: &digest.Transport{
			Username: username,
			Password: password,
		},
	}
	client, err := byocfixture.NewClient("https://"+host+"/v1beta2", httpClient)
	if err != nil {
		return err
	}
	ctx, cancel := context.WithTimeout(context.Background(), commandTimeout)
	defer cancel()

	switch args[0] {
	case "create":
		executionID := strings.TrimSpace(os.Getenv("OPEN_API_DEDICATED_EXECUTION_ID"))
		cloudProvider := strings.TrimSpace(os.Getenv("OPEN_API_DEDICATED_CLOUD_PROVIDER"))
		region := strings.TrimSpace(os.Getenv("OPEN_API_DEDICATED_REGION"))
		if region == "" {
			region = defaultRegion(cloudProvider)
		}
		poolID, err := client.Create(ctx, byocfixture.CreateOptions{
			OrganizationID: strings.TrimSpace(os.Getenv("OPEN_API_DEDICATED_TENANT_ID")),
			CloudProvider:  cloudProvider,
			Region:         region,
			DisplayName:    "sce-ng-byoc-fixture-" + executionID,
		})
		if err != nil {
			return err
		}
		return writeGitHubOutput("resource_pool_id", poolID)
	case "cleanup":
		return client.Cleanup(ctx, strings.TrimSpace(os.Getenv("OPEN_API_DEDICATED_GEN_RESOURCE_POOL_ID")))
	default:
		return errors.New("unreachable fixture action")
	}
}

func defaultRegion(cloudProvider string) string {
	switch cloudProvider {
	case "aws":
		return "us-west-2"
	case "gcp":
		return "us-west1"
	case "azure":
		return "japaneast"
	case "alicloud":
		return "ap-southeast-1"
	default:
		return ""
	}
}

func writeGitHubOutput(key, value string) error {
	path := os.Getenv("GITHUB_OUTPUT")
	if path == "" {
		return errors.New("GITHUB_OUTPUT is required")
	}
	// #nosec G703 -- GITHUB_OUTPUT is a GitHub Actions-provided environment file path.
	file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0o600)
	if err != nil {
		return fmt.Errorf("open GITHUB_OUTPUT: %w", err)
	}
	defer file.Close()
	if _, err := fmt.Fprintf(file, "%s=%s\n", key, value); err != nil {
		return fmt.Errorf("write GITHUB_OUTPUT: %w", err)
	}
	return nil
}
