// Approve an Ops Inbox request and wait for the run.
//
//	go run ./examples/go/devops/approve-request.go --dry-run
package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"strings"

	stackgen "github.com/appcd-dev/stackgen-sdk/clients/go"
)

func envOr(keys ...string) string {
	for _, key := range keys {
		if v := strings.TrimSpace(os.Getenv(key)); v != "" {
			return v
		}
	}
	return ""
}

func main() {
	baseURL := flag.String("base-url", "", "")
	apiToken := flag.String("api-token", "", "")
	orgID := flag.String("workspace-id", "", "Workspace UUID (sent as orgId)")
	flag.StringVar(orgID, "org-id", *orgID, "Deprecated: use -workspace-id")
	identifier := flag.String("identifier", "", "")
	requestID := flag.String("request-id", "", "")
	workflowName := flag.String("workflow-name", "", "")
	comment := flag.Bool("comment", false, "")
	dryRun := flag.Bool("dry-run", false, "")
	timeoutSeconds := flag.Int("timeout-seconds", 1800, "")
	pollInterval := flag.Int("poll-interval-seconds", 5, "")
	flag.Parse()

	base := strings.TrimSpace(*baseURL)
	if base == "" {
		base = envOr("STACKGEN_URL")
	}
	token := strings.TrimSpace(*apiToken)
	if token == "" {
		token = envOr("STACKGEN_TOKEN")
	}
	org := strings.TrimSpace(*orgID)
	if org == "" {
		org = envOr("STACKGEN_WORKSPACE_ID", "STACKGEN_ORG_ID", "STACKGEN_PROJECT", "STACKGEN_PROJECT_ID")
	}
	if base == "" || token == "" {
		fmt.Fprintln(os.Stderr, "set STACKGEN_URL and STACKGEN_TOKEN")
		os.Exit(2)
	}
	client, err := stackgen.NewClient(stackgen.Config{
		BaseURL: base, APIToken: token, WorkspaceID: org,
		TimeoutSeconds: *timeoutSeconds, PollIntervalSeconds: *pollInterval,
	})
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	ctx := context.Background()
	id := strings.TrimSpace(*requestID)
	if strings.TrimSpace(*identifier) != "" {
		req, err := client.DevOps.FetchAndWait(ctx, strings.TrimSpace(*identifier))
		if err != nil {
			fmt.Fprintln(os.Stderr, "error:", err)
			os.Exit(1)
		}
		raw, _ := json.MarshalIndent(req, "", "  ")
		fmt.Println("fetched:", string(raw))
		id = fmt.Sprint(req["id"])
	} else if id == "" {
		listed, err := client.DevOps.ListRequests(ctx, map[string]string{"status": "awaiting_approval", "page_size": "5"})
		if err != nil {
			fmt.Fprintln(os.Stderr, "error:", err)
			os.Exit(1)
		}
		raw, _ := json.MarshalIndent(listed, "", "  ")
		fmt.Println("candidates:", string(raw))
		body, _ := listed.(map[string]any)
		rows, _ := body["requests"].([]any)
		if len(rows) == 0 {
			fmt.Fprintln(os.Stderr, "error: no awaiting_approval requests")
			os.Exit(1)
		}
		first, _ := rows[0].(map[string]any)
		id = fmt.Sprint(first["id"])
	}
	if *dryRun {
		fmt.Fprintln(os.Stderr, "request_id=", id)
		return
	}
	finished, err := client.DevOps.ApproveAndWait(ctx, id, *workflowName, "")
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	raw, _ := json.MarshalIndent(finished, "", "  ")
	fmt.Println("result:", string(raw))
	if *comment {
		c, err := client.DevOps.PostSourceComment(ctx, id, "")
		if err != nil {
			fmt.Fprintln(os.Stderr, "error:", err)
			os.Exit(1)
		}
		raw, _ = json.MarshalIndent(c, "", "  ")
		fmt.Println("comment:", string(raw))
	}
}
