package wand

import (
	"fmt"
	"strings"
	"testing"
)

func TestEnv(t *testing.T) {
	type f struct{ One, SecondVar string }
	ff := func(f f) string {
		return f.One + f.SecondVar
	}

	type i struct{ One, SecondVar int }
	fi := func(i i) string {
		return fmt.Sprintf("%d;%d", i.One, i.SecondVar)
	}

	type m struct{ One, SecondVar []string }
	fm := func(m m) string {
		return strings.Join([]string{strings.Join(m.One, ","), strings.Join(m.SecondVar, ",")}, ";")
	}

	t.Run(
		"none match app prefix",
		testExec(testCase{impl: ff, env: "ONE=foo;SECOND_VAR=bar", command: "baz"}, "", ""),
	)

	t.Run(
		"common environment var casing",
		testExec(testCase{impl: ff, env: "FOO_ONE=bar;FOO_SECOND_VAR=baz", command: "foo"}, "", "barbaz"),
	)

	t.Run(
		"camel casing",
		testExec(testCase{impl: ff, env: "fooOne=bar;fooSecondVar=baz", command: "foo"}, "", "barbaz"),
	)

	t.Run(
		"empty env var",
		testExec(testCase{impl: ff, env: "fooOne=bar;fooSecondVar=", command: "foo"}, "", "bar"),
	)

	t.Run(
		"multipart app name",
		testExec(testCase{impl: ff, env: "fooBarOne=baz;FOO_BAR_SECOND_VAR=qux", command: "foo-bar"}, "", "bazqux"),
	)

	t.Run(
		"invalid env var",
		testExec(testCase{impl: ff, env: "fooOne=bar;fooSecondVar=baz;fooQux", command: "foo"}, "", "barbaz"),
	)

	t.Run(
		"eq in value",
		testExec(testCase{impl: ff, env: "fooOne=bar=baz", command: "foo"}, "", "bar=baz"),
	)

	t.Run(
		"keeps original name",
		testExec(testCase{impl: fi, env: "FOO_ONE=bar", command: "foo"}, "FOO_ONE", ""),
	)

	t.Run(
		"keeps original name, last wins on conflict",
		testExec(testCase{impl: fi, env: "FOO_ONE=bar;fooOne=baz", command: "foo"}, "fooOne", ""),
	)

	t.Run("multiple values", func(t *testing.T) {
		t.Run(
			"2",
			testExec(testCase{impl: fm, env: "fooOne=bar:baz", command: "foo"}, "", "bar,baz;"),
		)

		t.Run(
			"3",
			testExec(testCase{impl: fm, env: "fooOne=bar:baz:qux", command: "foo"}, "", "bar,baz,qux;"),
		)

		t.Run(
			"with empty",
			testExec(testCase{impl: fm, env: "fooOne=bar:baz::qux:", command: "foo"}, "", "bar,baz,,qux,;"),
		)

		t.Run(
			"escape",
			testExec(testCase{impl: fm, env: "fooOne=bar\\:baz", command: "foo"}, "", "bar:baz;"),
		)

		t.Run(
			"escape char",
			testExec(testCase{impl: fm, env: "fooOne=bar\\\\:baz", command: "foo"}, "", "bar\\,baz;"),
		)

		t.Run(
			"escape char last",
			testExec(testCase{impl: fm, env: "fooOne=bar\\", command: "foo"}, "", "bar;"),
		)
	})
}
