package gotty

import (
	"context"
	"net/http"
	"net/http/httptest"
	"net/url"
	"reflect"
	"testing"
	"time"

	"github.com/tidbcloud/clusterproxy/resolve"
	"github.com/tidbcloud/clusterproxy/route"
	v1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes/fake"
)

func TestGottyProxy(t *testing.T) {
	image := "gotty:test"
	cmd := "/gotty -w /usql"
	tmpGoTTYCmd, tmpGoTTYImage := gottyCmd, gottyImage
	gottyCmd, gottyImage = &cmd, &image
	defer func() {
		gottyCmd, gottyImage = tmpGoTTYCmd, tmpGoTTYImage
	}()

	gottyWaitTimeout = 5 * time.Second
	tidbService := &v1.Service{
		ObjectMeta: metav1.ObjectMeta{Namespace: "tidb42", Name: "db-tidb"},
		Spec: v1.ServiceSpec{
			Ports: []v1.ServicePort{{
				Port: 4000,
			}},
			ClusterIP: "10.4.96.4",
		},
	}
	tidbEndpoints := &v1.Endpoints{
		ObjectMeta: metav1.ObjectMeta{Namespace: "tidb42", Name: "db-tidb"},
		Subsets: []v1.EndpointSubset{
			{
				Addresses: []v1.EndpointAddress{{IP: "10.4.96.4"}},
			},
		},
	}
	gottyService := &v1.Service{
		ObjectMeta: metav1.ObjectMeta{Namespace: "tidb42", Name: "shell-db-1-root"},
		Spec: v1.ServiceSpec{
			Ports: []v1.ServicePort{{
				Port: 8080,
			}},
			ClusterIP: "10.4.96.7",
		},
	}
	gottyEndpoints := &v1.Endpoints{
		ObjectMeta: metav1.ObjectMeta{Namespace: "tidb42", Name: "shell-db-1-root"},
		Subsets: []v1.EndpointSubset{
			{
				Addresses: []v1.EndpointAddress{{IP: "10.4.96.7"}},
			},
		},
	}

	ctx := &route.Context{
		Cli: fake.NewSimpleClientset(
			tidbService,
			tidbEndpoints,
			gottyService,
			gottyEndpoints,
		),
	}
	req := &http.Request{
		URL:    &url.URL{Path: "root"},
		Header: make(map[string][]string),
	}
	req.Header.Set("x-user-id", "1")
	recorder := httptest.NewRecorder()
	cl := resolve.Cluster{Namespace: "tidb42", Name: "db"}
	gottyGetHandler(ctx, cl).ServeHTTP(recorder, req)

	if recorder.Code != http.StatusInternalServerError {
		t.Fatalf("Response code got = %v, want = %v.", recorder.Code, http.StatusBadGateway)
	}

	job, err := ctx.Cli.BatchV1().Jobs("tidb42").Get(context.Background(), "shell-db-1-root", metav1.GetOptions{})
	if err != nil {
		t.Fatalf("gotty job is not created: %v", err)
	}

	for _, c := range job.Spec.Template.Spec.Containers {
		if c.Name != "gotty" {
			continue
		}
		if c.Image != image {
			t.Fatalf("job image is not matched, expected %v, actual %v", image, c.Image)
		}
		cmds := []string{
			"/gotty",
			"-w",
			"/usql",
			"ti://root@10.4.96.4:4000/",
		}
		if !reflect.DeepEqual(c.Command, cmds) {
			t.Fatalf("job cmd is not matched, expected %v, actual %v", cmds, c.Command)
		}
	}
}
