// Create a webhook that answers HTTP 200 with ack headers, then trigger it.
//
// Documented at https://appcd-dev.github.io/stackgen-sdk/code-samples/webhook-ack-headers/
//
//	go run ./examples/go/automation/webhook-ack-headers.go --agent my-oncall-agent
package main

import (
	"bytes"
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"strings"

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

// envOr returns the first non-empty environment variable among keys.
func envOr(keys ...string) string {
	for _, key := range keys {
		if v := strings.TrimSpace(os.Getenv(key)); v != "" {
			return v
		}
	}
	return ""
}

func main() {
	agent := flag.String("agent", "", "Existing agent name")
	workflow := flag.String("workflow", "", "Existing workflow name")
	flag.Parse()
	if (*agent == "") == (*workflow == "") {
		fmt.Fprintln(os.Stderr, "pass exactly one of --agent or --workflow")
		os.Exit(2)
	}
	base, token, org := envOr("STACKGEN_URL"), envOr("STACKGEN_TOKEN"), envOr("STACKGEN_WORKSPACE_ID", "STACKGEN_PROJECT")
	if base == "" || token == "" || org == "" {
		fmt.Fprintln(os.Stderr, "set STACKGEN_URL, STACKGEN_TOKEN, and STACKGEN_WORKSPACE_ID")
		os.Exit(2)
	}
	targetType, targetName := "agent", *agent
	if *workflow != "" {
		targetType, targetName = "workflow", *workflow
	}
	client, err := stackgen.NewClient(stackgen.Config{BaseURL: base, APIToken: token, WorkspaceID: org})
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	ctx := context.Background()
	wh, err := client.Aiden.CreateWebhook(ctx, map[string]any{
		"name":            "linear-issues",
		"target_type":     targetType,
		"target_name":     targetName,
		"action":          "Summarize the Linear issue and reply Done",
		"enabled":         true,
		"response_status": 200,
		"response_headers": map[string]string{
			"X-Ack-Source":    "aiden",
			"X-Provider-Hint": "linear-style",
		},
	})
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	webhookID, _ := wh["id"].(string)
	webhookToken, _ := wh["token"].(string)
	fmt.Printf("created webhook id=%s response_status=%v\n", webhookID, wh["response_status"])
	defer func() {
		if webhookID != "" {
			_, _ = client.Aiden.DeleteWebhook(context.Background(), webhookID)
			fmt.Printf("deleted webhook id=%s\n", webhookID)
		}
	}()
	if webhookToken == "" {
		fmt.Fprintln(os.Stderr, "create webhook did not return a token")
		os.Exit(1)
	}
	body, _ := json.Marshal(map[string]string{"action": "issue.create", "source": "sdk-ack"})
	endpoint := strings.TrimRight(base, "/") + "/guild/api/v1/webhooks/trigger?" + url.Values{"orgId": {org}}.Encode()
	req, err := http.NewRequest(http.MethodPost, endpoint, bytes.NewReader(body))
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	req.Header.Set("Authorization", "Bearer "+webhookToken)
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Linear-Signature", "sdk-demo-sig")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error:", err)
		os.Exit(1)
	}
	defer resp.Body.Close()
	raw, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
	fmt.Printf("trigger status=%d\n", resp.StatusCode)
	fmt.Printf("trigger ack X-Ack-Source=%s\n", resp.Header.Get("X-Ack-Source"))
	fmt.Printf("trigger ack X-Provider-Hint=%s\n", resp.Header.Get("X-Provider-Hint"))
	fmt.Printf("trigger body=%s\n", raw)
	if resp.StatusCode != 200 {
		os.Exit(1)
	}
}
