package nix

import (
	"context"
	"fmt"
	"iter"
	"os"
)

const (
	EnvAwsSharedCredentialsFile = "AWS_SHARED_CREDENTIALS_FILE"
)

// A BinaryCache holds credentials and parameters to a s3 binary cache.
type BinaryCache struct {
	// Compression is the name of the compression algorithm to use. Example: "zstd".
	Compression string `json:"compression"`
	// ParallelCompression determines whether parallel compression is enabled.
	ParallelCompression bool `json:"parallel_compression,omitempty"`

	// Bucket is the s3 bucket name.
	Bucket string `json:"bucket"`
	// Endpoint is the s3 endpoint. Example: "s3.example.org".
	Endpoint string `json:"endpoint,omitempty"`
	// Region is the s3 region. Example: "ap-northeast-1".
	Region string `json:"region"`
	// Scheme is the s3 protocol. Example: "https".
	Scheme string `json:"scheme"`
	// CredentialsPath is the path to the s3 shared credentials file.
	CredentialsPath string `json:"credentials_path"`
}

func (store *BinaryCache) String() string {
	return fmt.Sprintf(
		"s3://%s?compression=%s&parallel-compression=%t&region=%s&scheme=%s&endpoint=%s",
		store.Bucket, store.Compression, store.ParallelCompression, store.Region, store.Scheme, store.Endpoint,
	)
}

// Copy copies installables to the binary cache store, signing all paths using the key at keyPath.
func Copy(ctx Context, keyPath string, store *BinaryCache, installables iter.Seq[string]) error {
	if store == nil {
		return os.ErrInvalid
	}

	c, cancel := context.WithCancel(ctx.Unwrap())
	defer cancel()

	cmd := ctx.Nix(c, CommandCopy,
		FlagTo, store.String()+"&secret-key="+keyPath,
		FlagStdin)
	cmd.Env = append(os.Environ(), EnvAwsSharedCredentialsFile+"="+store.CredentialsPath)

	cmd.Stdout, cmd.Stderr = ctx.Streams()
	_, err := ctx.WriteStdin(cmd, installables, nil)
	return err
}
