// cc-set-secret is an operator helper that writes an age-encrypted value
// into the command-center secrets table without going through the WebAuthn-
// gated /api/secrets HTTP endpoint. Useful when bootstrapping a fresh
// tracker / external-service credential before the operator has a session,
// or when scripting provisioning on the droplet.
//
// Usage (value read from stdin so it doesn't appear in `ps` output):
//
//   # cookie-auth tracker (MAM/TD/TL)
//   echo -n 'tlpass=…; tluid=2132130' | \
//     /usr/local/go/bin/go run ./cmd/cc-set-secret \
//       -key tracker:tl:cookie \
//       -db  /var/lib/command-center/command-center.db \
//       -age /etc/command-center/age.key
//
//   # bearer-auth tracker (LST)
//   echo -n '<api-token>' | \
//     /usr/local/go/bin/go run ./cmd/cc-set-secret \
//       -key tracker:lst:api_token \
//       -db  /var/lib/command-center/command-center.db \
//       -age /etc/command-center/age.key
//
// To DELETE a key, pass an empty value (or `-delete`).
package main

import (
	"context"
	"database/sql"
	"errors"
	"flag"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/operator/command-center/internal/secrets"
	_ "modernc.org/sqlite"
)

func main() {
	var (
		key      = flag.String("key", "", "secret key, e.g. tracker:tl:cookie")
		dbPath   = flag.String("db", "/var/lib/command-center/command-center.db", "path to command-center.db")
		ageKey   = flag.String("age", "/etc/command-center/age.key", "path to the age identity file")
		valueArg = flag.String("value", "", "value (NOT recommended — visible in ps; prefer stdin)")
		delete_  = flag.Bool("delete", false, "delete the key instead of setting it")
	)
	flag.Parse()
	if *key == "" {
		die("flag -key is required")
	}

	db, err := sql.Open("sqlite", *dbPath)
	if err != nil {
		die("open db: %v", err)
	}
	defer db.Close()
	store, err := secrets.New(db, secrets.Config{IdentityFile: *ageKey})
	if err != nil {
		die("secrets init: %v", err)
	}

	ctx := context.Background()
	if *delete_ {
		if err := store.Delete(ctx, *key); err != nil && !errors.Is(err, secrets.ErrNotFound) {
			die("delete: %v", err)
		}
		fmt.Printf("deleted %s\n", *key)
		return
	}

	var value []byte
	switch {
	case *valueArg != "":
		value = []byte(*valueArg)
	default:
		b, err := io.ReadAll(os.Stdin)
		if err != nil {
			die("read stdin: %v", err)
		}
		value = []byte(strings.TrimRight(string(b), "\n\r"))
	}
	if len(value) == 0 {
		die("empty value (pipe the value into stdin, or pass -delete to remove)")
	}

	if err := store.Set(ctx, *key, value); err != nil {
		die("set: %v", err)
	}
	fmt.Printf("set %s (%d bytes encrypted)\n", *key, len(value))
}

func die(format string, a ...any) {
	fmt.Fprintf(os.Stderr, "cc-set-secret: "+format+"\n", a...)
	os.Exit(1)
}
