package view

import (
	"fmt"
	"io/ioutil"
	"local/dndex/storage"
	"net/http"
	"net/http/httptest"
	"os"
	"strings"
	"testing"

	"github.com/google/uuid"
)

func TestRegister(t *testing.T) {
	os.Args = os.Args[:1]
	f, err := ioutil.TempFile(os.TempDir(), "pattern*")
	if err != nil {
		t.Fatal(err)
	}
	f.Close()
	defer os.Remove(f.Name())
	os.Setenv("DBURI", f.Name())

	os.Setenv("AUTH", "true")
	defer os.Setenv("AUTH", "false")

	g := storage.NewGraph()
	handler := jsonHandler(g)

	t.Run("register: wrong method", func(t *testing.T) {
		r := httptest.NewRequest(http.MethodGet, "/register", nil)
		r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		w := httptest.NewRecorder()
		handler.ServeHTTP(w, r)
		if w.Code != http.StatusNotFound {
			t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
		}
	})

	t.Run("register: no namespace", func(t *testing.T) {
		r := httptest.NewRequest(http.MethodPost, "/register", strings.NewReader(""))
		r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		w := httptest.NewRecorder()
		handler.ServeHTTP(w, r)
		if w.Code != http.StatusBadRequest {
			t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
		}
	})

	t.Run("register: no password", func(t *testing.T) {
		r := httptest.NewRequest(http.MethodPost, "/register?namespace="+uuid.New().String(), strings.NewReader(""))
		r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		w := httptest.NewRecorder()
		handler.ServeHTTP(w, r)
		if w.Code != http.StatusBadRequest {
			t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
		}
	})

	t.Run("register", func(t *testing.T) {
		ns := uuid.New().String()

		r := httptest.NewRequest(http.MethodPost, "/register?namespace="+ns, strings.NewReader(`password=123`))
		r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		w := httptest.NewRecorder()
		handler.ServeHTTP(w, r)
		if w.Code != http.StatusOK {
			t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
		}
		t.Logf("/register: %s", w.Body.Bytes())

		r = httptest.NewRequest(http.MethodTrace, "/who?namespace="+ns, nil)
		w = httptest.NewRecorder()
		handler.ServeHTTP(w, r)
		if w.Code != http.StatusSeeOther {
			t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
		}
		t.Logf("noauth /who: %s", w.Body.Bytes())

		rawtoken := getCookie(NewAuthKey, w.Header())
		token, err := aesDec("123", rawtoken)
		if err != nil {
			t.Fatal(err)
		}

		r = httptest.NewRequest(http.MethodTrace, "/who?namespace="+ns, nil)
		r.Header.Set("Cookie", fmt.Sprintf("%s=%s", AuthKey, token))
		w = httptest.NewRecorder()
		handler.ServeHTTP(w, r)
		if w.Code != http.StatusOK {
			t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
		}
		t.Logf("auth /who: %s", w.Body.Bytes())
	})
}

func getCookie(key string, header http.Header) string {
	cookies, _ := header["Set-Cookie"]
	if len(cookies) == 0 {
		cookies, _ = header["Cookie"]
	}
	for i := range cookies {
		value := strings.Split(cookies[i], ";")[0]
		k := value[:strings.Index(value, "=")]
		v := value[strings.Index(value, "=")+1:]
		if k == key {
			return v
		}
	}
	return ""
}
