package view

import (
	"bytes"
	"context"
	"encoding/json"
	"io/ioutil"
	"local/dndex/storage"
	"local/dndex/storage/entity"
	"net/http"
	"net/http/httptest"
	"os"
	"strings"
	"testing"
)

func TestPort(t *testing.T) {
	os.Args = os.Args[:1]
	os.Setenv("AUTH", "false")

	g := storage.NewRateLimitedGraph()
	reset := func() {
		if err := g.Delete(context.TODO(), "col", map[string]string{}); err != nil {
			t.Fatal(err)
		}
		for _, name := range []string{"A", "B", "C"} {
			if err := g.Insert(context.TODO(), "col", entity.One{ID: "id-" + name, Name: name}); err != nil {
				t.Fatal(err)
			}
		}
	}
	handler := jsonHandler(g)

	t.Run("port: wrong path", func(t *testing.T) {
		reset()
		r := httptest.NewRequest(http.MethodGet, "/port/", nil)
		w := httptest.NewRecorder()
		handler.ServeHTTP(w, r)
		if w.Code != http.StatusNotFound {
			t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
		}
	})

	t.Run("port: wrong method", func(t *testing.T) {
		reset()
		r := httptest.NewRequest(http.MethodPut, "/port", nil)
		w := httptest.NewRecorder()
		handler.ServeHTTP(w, r)
		if w.Code != http.StatusNotFound {
			t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
		}
	})

	t.Run("port: post: no namespace", func(t *testing.T) {
		reset()
		r := httptest.NewRequest(http.MethodPost, "/port", strings.NewReader(``))
		w := httptest.NewRecorder()
		handler.ServeHTTP(w, r)
		if w.Code != http.StatusBadRequest {
			t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
		}
	})

	t.Run("port: get: no namespace", func(t *testing.T) {
		reset()
		r := httptest.NewRequest(http.MethodGet, "/port", nil)
		w := httptest.NewRecorder()
		handler.ServeHTTP(w, r)
		if w.Code != http.StatusBadRequest {
			t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
		}
	})

	t.Run("port: ex => im", func(t *testing.T) {
		reset()
		r := httptest.NewRequest(http.MethodGet, "/port?namespace=col", nil)
		w := httptest.NewRecorder()
		handler.ServeHTTP(w, r)
		if w.Code != http.StatusOK {
			t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
		}

		b, err := ioutil.ReadAll(w.Body)
		if err != nil {
			t.Fatal(err)
		}

		if err := g.Delete(context.TODO(), "col", map[string]string{}); err != nil {
			t.Fatal(err)
		}

		if ones, err := g.List(context.TODO(), "col"); err != nil {
			t.Fatal(err)
		} else if len(ones) != 0 {
			t.Fatal(len(ones))
		}

		r = httptest.NewRequest(http.MethodPost, "/port?namespace=col", bytes.NewReader(b))
		w = httptest.NewRecorder()
		handler.ServeHTTP(w, r)
		if w.Code != http.StatusOK {
			t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
		}
		var resp map[string]int
		if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
			t.Fatal(err)
		}
		n := 0
		for k, v := range resp {
			if k != "col" || v == 0 {
				t.Fatal(resp)
			}
			n = v
		}
		if n == 0 {
			t.Fatal(n, resp, string(w.Body.Bytes()))
		}

		if ones, err := g.List(context.TODO(), "col"); err != nil {
			t.Fatal(err)
		} else if len(ones) != n {
			t.Fatal(len(ones))
		}
	})
}
