package typescript_test

import (
	"strings"
	"testing"

	"code.justin.tv/spade/code-generator/internal"
	"code.justin.tv/spade/code-generator/internal/typescript"
	"github.com/stretchr/testify/assert"
)

func Test_SchemaFieldToProperty(t *testing.T) {
	tests := []struct {
		Description        string
		InputField         internal.Field
		ExpectedType       string
		ExpectedIdentifier string
	}{
		{
			Description: "require field",
			InputField: internal.Field{
				Name:         internal.String("hello"),
				Type:         &internal.FieldType{Name: "bool"},
				Expectations: []internal.FieldExpectation{{Name: internal.ValuesToNotBeNull}},
			},
			ExpectedType:       "boolean",
			ExpectedIdentifier: "hello",
		},
		{
			Description: "optional boolean",
			InputField: internal.Field{
				Name: internal.String("hello"),
				Type: &internal.FieldType{Name: "bool"},
			},
			ExpectedType:       "boolean",
			ExpectedIdentifier: "hello?",
		},
		{
			Description: "optional long",
			InputField: internal.Field{
				Name: internal.String("hello"),
				Type: &internal.FieldType{Name: "long"},
			},
			ExpectedType:       "number",
			ExpectedIdentifier: "hello?",
		},
		{
			Description: "optional float",
			InputField: internal.Field{
				Name: internal.String("hello"),
				Type: &internal.FieldType{Name: "float"},
			},
			ExpectedType:       "number",
			ExpectedIdentifier: "hello?",
		},
		{
			Description: "optional timestamp",
			InputField: internal.Field{
				Name: internal.String("hello"),
				Type: &internal.FieldType{Name: "timestamp"},
			},
			ExpectedType:       "number",
			ExpectedIdentifier: "hello?",
		},
		{
			Description: "optional string",
			InputField: internal.Field{
				Name: internal.String("hello"),
				Type: &internal.FieldType{Name: "string"},
			},
			ExpectedType:       "string",
			ExpectedIdentifier: "hello?",
		},
		{
			Description: "optional enum",
			InputField: internal.Field{
				Name: internal.String("hello"),
				Type: &internal.FieldType{
					Name:   "enum",
					Values: internal.StringSlice([]string{"a", "b", "c"}),
				},
			},
			ExpectedType:       `"a" | "b" | "c"`,
			ExpectedIdentifier: "hello?",
		},
		{
			Description: "unsupported type",
			InputField: internal.Field{
				Name: internal.String("hello"),
				Type: &internal.FieldType{
					Name: "weird",
				},
			},
			ExpectedType:       "any",
			ExpectedIdentifier: "hello?",
		},
	}

	for _, test := range tests {
		t.Run(test.Description, func(t *testing.T) {
			r := typescript.SchemaFieldToProperty(test.InputField)

			assert.Equal(t, test.ExpectedType, r.Type)
			assert.Equal(t, test.ExpectedIdentifier, r.Identifier)
		})
	}
}

func Test_StringsToRegexes(t *testing.T) {
	assert.Equal(t, "[]", typescript.StringsToRegexes([]string{}))
	assert.Equal(t, "[/abc/,/def/]", typescript.StringsToRegexes([]string{"abc", "def"}))
}

func Test_WriteComment(t *testing.T) {
	o := &strings.Builder{}
	typescript.WriteComment(o, 0, "some comment")
	assert.Equal(t, "/** some comment */\n", o.String())
}

func Test_WriteComment_Multiline(t *testing.T) {
	o := &strings.Builder{}
	typescript.WriteComment(o, 0, "a\nb")
	assert.Equal(t, "/**\n* a\n* b\n*/\n", o.String())
}
