package nix_test

import (
	"errors"
	"os"
	"slices"
	"syscall"
	"testing"

	"gensokyo.uk/nix"
	"hakurei.app/command"
)

func init() {
	stubCommandInit = append(stubCommandInit, func(c command.Command) {
		var (
			flagCopyTo    string
			flagCopyStdin bool
		)
		c.NewCommand(nix.CommandCopy, "emit samples for various `nix copy` cases", func(args []string) error {
			if flagCopyTo != "s3://example?compression=none&parallel-compression=false&region=us-east-1&scheme=http&endpoint=s3.example.org&secret-key="+nonexistent || !flagCopyStdin {
				return syscall.ENOSYS
			}

			installables, err := nix.ReadStdin(os.Stdin)
			if err != nil {
				return err
			}
			if !slices.Equal(installables, instWant["pluiedev pappardelle"]) {
				return syscall.EINVAL
			}
			return nil
		}).
			Flag(&flagCopyTo, trimFlagName(nix.FlagTo), command.StringFlag(""), nix.FlagTo).
			Flag(&flagCopyStdin, trimFlagName(nix.FlagStdin), command.BoolFlag(false), nix.FlagStdin)
	})
}

func TestBinaryCache(t *testing.T) {
	testCases := []struct {
		name  string
		store *nix.BinaryCache
		want  string
	}{
		{"example", &nix.BinaryCache{
			Compression:         "none",
			ParallelCompression: false,
			Bucket:              "example",
			Endpoint:            "s3.example.org",
			Region:              "us-east-1",
			Scheme:              "http",
			CredentialsPath:     "/dev/null",
		}, "s3://example?compression=none&parallel-compression=false&region=us-east-1&scheme=http&endpoint=s3.example.org"},

		{"gensokyo", &nix.BinaryCache{
			Compression:         "zstd",
			ParallelCompression: true,
			Bucket:              "nix-cache",
			Endpoint:            "s3.gensokyo.uk",
			Region:              "ap-northeast-1",
			Scheme:              "https",
			CredentialsPath:     "/var/lib/persist/cache/s3",
		}, "s3://nix-cache?compression=zstd&parallel-compression=true&region=ap-northeast-1&scheme=https&endpoint=s3.gensokyo.uk"},
	}
	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			if got := tc.store.String(); got != tc.want {
				t.Errorf("String: %q, want %q", got, tc.want)
			}
		})
	}
}

func TestCopy(t *testing.T) {
	stubNixCommand(t)
	if err := nix.Copy(
		newStubContext(t.Context(), nil, os.Stdout, os.Stderr),
		nonexistent,
		&nix.BinaryCache{
			Compression:         "none",
			ParallelCompression: false,
			Bucket:              "example",
			Endpoint:            "s3.example.org",
			Region:              "us-east-1",
			Scheme:              "http",
			CredentialsPath:     "/dev/null",
		},
		slices.Values(instWant["pluiedev pappardelle"]),
	); err != nil {
		t.Errorf("Copy: error = %v", err)
	}

	t.Run("nil store", func(t *testing.T) {
		if err := nix.Copy(
			newStubContext(t.Context(), nil, os.Stdout, os.Stderr),
			nonexistent,
			nil,
			nil,
		); !errors.Is(err, os.ErrInvalid) {
			t.Errorf("Copy: error = %v, want %v", err, os.ErrInvalid)
		}
	})
}
