package main

import (
	"context"
	"flag"
	"fmt"
	"os"
	"time"
)

func runDeploy(args []string) error {
	fs := flag.NewFlagSet("deploy", flag.ExitOnError)
	g := addGlobalFlags(fs)
	ref := fs.String("ref", "", "image tag / git ref / source-specific deploy target")
	note := fs.String("note", "", "free-text note recorded with the deploy")
	timeout := fs.Duration("timeout", 15*time.Minute, "max time to wait for the deploy to finish")
	fs.Usage = func() {
		fmt.Fprint(os.Stderr, "Usage: tinyforge deploy <app> [--ref TAG] [--note TEXT] [--timeout DUR]\n\n"+
			"Trigger a deploy and wait for it to finish. Requires an admin token.\n")
		fs.PrintDefaults()
	}
	if err := fs.Parse(args); err != nil {
		return err
	}
	if fs.NArg() != 1 {
		fs.Usage()
		return fmt.Errorf("expected exactly one app (name or id)")
	}

	sess, err := newSession(g)
	if err != nil {
		return err
	}

	// Resolve the app on a short deadline; the deploy itself gets the full one.
	resolveCtx, cancelResolve := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancelResolve()
	app, err := resolveApp(resolveCtx, sess.client, fs.Arg(0))
	if err != nil {
		return err
	}

	body := map[string]string{}
	if *ref != "" {
		body["reference"] = *ref
	}
	if *note != "" {
		body["note"] = *note
	}

	fmt.Printf("Deploying %s%s…\n", app.Name, refSuffix(*ref))

	// The endpoint returns 202 but blocks until the deploy completes, so a
	// success here means it finished; allow plenty of time for pull/build.
	ctx, cancel := context.WithTimeout(context.Background(), *timeout)
	defer cancel()

	var result DeployResult
	if err := sess.client.doJSON(ctx, "POST", "/api/workloads/"+app.ID+"/deploy", body, &result); err != nil {
		return err
	}

	fmt.Printf("Deploy of %s completed (triggered by %s).\n", app.Name, result.TriggeredBy)
	fmt.Printf("Follow with: tinyforge logs %s -f\n", app.Name)
	return nil
}

func refSuffix(ref string) string {
	if ref == "" {
		return ""
	}
	return fmt.Sprintf(" @ %s", ref)
}
