package files

import (
	"context"
	"testing"
	"text/template"

	"git.perx.ru/perxis/perxis-go/pkg/expr"
	"github.com/stretchr/testify/require"
)

func TestFile_SetURLWithTemplate(t *testing.T) {
	tests := []struct {
		name     string
		file     *File
		template *template.Template
		wantErr  bool
		wantURL  string
	}{
		{
			name: "template is nil",
			file: &File{
				URL: "https://cloud.com/",
			},
			template: nil,
			wantErr:  false,
			wantURL:  "https://cloud.com/",
		},
		{
			name:     "template with non-existent field",
			file:     &File{},
			template: template.Must(template.New("url").Parse("{{.NonExistentField}}")),
			wantErr:  true,
		},
		{
			name: "success",
			file: &File{
				Size:     1024,
				MimeType: "image/png",
				Key:      "file-key",
			},
			template: template.Must(template.New("url").Parse("https://cloud-proxy.com/{{.Key}}?size={{.Size}}#{{.MimeType}}")),
			wantErr:  false,
			wantURL:  "https://cloud-proxy.com/file-key?size=1024#image/png",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := tt.file.SetURLWithTemplate(tt.template)
			if tt.wantErr {
				require.Error(t, err)
			} else {
				require.NoError(t, err)
				require.Equal(t, tt.wantURL, tt.file.URL)
			}
		})
	}
}

func TestFile_InExpr(t *testing.T) {
	ctx := context.Background()

	tests := []struct {
		exp        string
		env        map[string]interface{}
		wantResult interface{}
		wantErr    bool
	}{
		{"f.id", map[string]interface{}{"f": &File{ID: "some_id"}}, "some_id", false},
		{"f.name", map[string]interface{}{"f": &File{Name: "some_name"}}, "some_name", false},
		{"f.size", map[string]interface{}{"f": &File{Size: 1}}, 1, false},
		{"f.mime_type", map[string]interface{}{"f": &File{MimeType: "some_mime_type"}}, "some_mime_type", false},
		{"f.url", map[string]interface{}{"f": &File{URL: "some_url"}}, "some_url", false},
		{"f.key", map[string]interface{}{"f": &File{Key: "some_key"}}, "some_key", false},
		{"f.not_exists", map[string]interface{}{"f": &File{}}, "", true},
	}

	for _, tt := range tests {
		t.Run(tt.exp, func(t *testing.T) {
			result, err := expr.Eval(ctx, tt.exp, tt.env)
			if tt.wantErr {
				require.Error(t, err)
				return
			}

			require.NoError(t, err)
			require.Equal(t, tt.wantResult, result)
		})
	}
}