package bindings

import (
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"

	"github.com/matryer/is"
	"github.com/wailsapp/wails/v2/pkg/templates"
)

const standardBindings = `// @ts-check
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT

export function Greet(arg1) {
  return window['go']['main']['App']['Greet'](arg1);
}
`

const obfuscatedBindings = `// @ts-check
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT

export function Greet(arg1) {
  return ObfuscatedCall(0, [arg1]);
}
`

func TestGenerateBindings(t *testing.T) {

	i := is.New(t)

	// Get the directory of this file
	_, filename, _, _ := runtime.Caller(0)
	workingDirectory := filepath.Dir(filename)

	projectDir := filepath.Join(workingDirectory, "test")

	_ = os.RemoveAll(projectDir)

	_, _, err := templates.Install(&templates.Options{
		ProjectName:  "test",
		TemplateName: "plain",
		WailsVersion: "latest",
	})
	if err != nil {
		println(err.Error())
		t.Fail()
	}

	defer func() {
		_ = os.RemoveAll(projectDir)
	}()

	// Make the go.mod point to local
	goModPath := filepath.Join(projectDir, "go.mod")
	goMod, err := os.ReadFile(goModPath)
	i.NoErr(err)
	pathToRepository := filepath.Join(workingDirectory, "..", "..", "..")
	absPathToRepo, _ := filepath.Abs(pathToRepository)
	goModString := string(goMod)
	goModSplit := strings.Split(goModString, "=>")
	goModSplit[1] = absPathToRepo
	goModString = strings.Join(goModSplit, "=> ")
	goMod = []byte(strings.ReplaceAll(goModString, "// replace", "replace"))
	// Write file back
	err = os.WriteFile(goModPath, goMod, 0755)
	i.NoErr(err)

	tests := []struct {
		name             string
		options          Options
		stdout           string
		expectedBindings string
		wantErr          bool
	}{
		{
			name: "should generate standard bindings with no user tags",
			options: Options{
				ProjectDirectory: projectDir,
				Compiler:         "go",
				GoModTidy:        true,
			},
			expectedBindings: standardBindings,
			stdout:           "",
			wantErr:          false,
		},
		{
			name: "should generate bindings when given tags",
			options: Options{
				ProjectDirectory: projectDir,
				Compiler:         "go",
				Tags:             []string{"test"},
				GoModTidy:        true,
			},
			expectedBindings: standardBindings,
			stdout:           "",
			wantErr:          false,
		},
		{
			name: "should generate obfuscated bindings",
			options: Options{
				ProjectDirectory: projectDir,
				Compiler:         "go",
				Tags:             []string{"obfuscated"},
				GoModTidy:        true,
			},
			expectedBindings: obfuscatedBindings,
			stdout:           "",
			wantErr:          false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			stdout, err := GenerateBindings(tt.options)
			i.True((err != nil) == tt.wantErr)
			i.Equal(stdout, tt.stdout)
			// Read bindings
			bindingsFile := filepath.Join(projectDir, "frontend", "wailsjs", "go", "main", "App.js")
			bindings, err := os.ReadFile(bindingsFile)
			i.NoErr(err)
			i.Equal(string(bindings), tt.expectedBindings)
		})
	}
}
