package anonym_find

import (
	"net/http"
	"net/url"
	"os"
	"strings"
	"testing"

	"github.com/gofiber/fiber/v2"

	"git.p78su.freemyip.com/svi/gostore/pkg/mock/mock_service"
	"git.p78su.freemyip.com/svi/gostore/pkg/mock/mock_store"
	"git.p78su.freemyip.com/svi/gostore/pkg/mock/mock_web"
)

type tester struct {
	t        *testing.T
	serv     *mock_service.MockService
	router   fiber.Router
	web      *mock_web.MockWeb
	anonFind *AnonymFind
}

func TestAnonymFind(t *testing.T) {
	fnClear := func() {
		_ = os.RemoveAll("./store")
	}
	fnClear()
	defer fnClear()
	sf := &tester{
		t: t,
	}
	sf.create()
	sf.check()
	sf.get()
	sf.post()
}

// Обработка поиска анонимного ключа
func (sf *tester) post() {
	sf.t.Log("create")
	sf.postBad1()
	sf.postBad2()
	sf.postBad3()
}

// Нет такого ключа в хранилище
func (sf *tester) postBad3() {
	sf.t.Log("postBad3")
	app := fiber.New()
	app.Post("/anonym/find", sf.anonFind.post)
	formVal := url.Values{
		"key": {"key"},
	}
	req, err := http.NewRequest("POST", "/anonym/find", strings.NewReader(formVal.Encode()))
	if err != nil {
		sf.t.Fatalf("postBad3(): err=\n\t%v", err)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	err = sf.serv.Store_.Put("anon/key", []byte("value"))
	if err != nil {
		sf.t.Fatalf("postBad3(): err=\n\t%v", err)
	}
	resp, err := app.Test(req)
	if err != nil {
		sf.t.Fatalf("postBad3(): err=\n\t%v", err)
	}
	defer resp.Body.Close()
	// Здесь проблема с расположением шаблонов в другом месте
	// if resp.StatusCode != 200 {
	// 	sf.t.Fatalf("postBad3(): resp.Status=%v", resp.Status)
	// }
}

// Пустой ключ для поиска
func (sf *tester) postBad2() {
	sf.t.Log("postBad2")
	app := fiber.New()
	app.Post("/anonym/find", sf.anonFind.post)
	formVal := url.Values{
		"key": {""},
	}
	req, err := http.NewRequest("POST", "/anonym/find", strings.NewReader(formVal.Encode()))
	if err != nil {
		sf.t.Fatalf("postBad2(): err=\n\t%v", err)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	resp, err := app.Test(req)
	if err != nil {
		sf.t.Fatalf("postBad2(): err=\n\t%v", err)
	}
	defer resp.Body.Close()
}

// Кривой запрос для поиска
func (sf *tester) postBad1() {
	sf.t.Log("postBad1")
	app := fiber.New()
	app.Post("/anonym/find", sf.anonFind.post)
	formVal := url.Values{
		"key": {"key"},
	}
	req, err := http.NewRequest("POST", "/anonym/find", strings.NewReader(formVal.Encode()))
	if err != nil {
		sf.t.Fatalf("postBad1(): err=\n\t%v", err)
	}
	resp, err := app.Test(req)
	if err != nil {
		sf.t.Fatalf("postBad1(): err=\n\t%v", err)
	}
	defer resp.Body.Close()
}

// Получение страницы анонимного поиска
func (sf *tester) get() {
	sf.t.Log("get")
	app := fiber.New()
	app.Get("/anonym/find", sf.anonFind.get)
	req, err := http.NewRequest("GET", "/anonym/find", nil)
	if err != nil {
		sf.t.Fatalf("get(): err=\n\t%v", err)
	}
	resp, err := app.Test(req)
	if err != nil {
		sf.t.Fatalf("get(): err=\n\t%v", err)
	}
	defer resp.Body.Close()
}

// Проверяет допустимость префикса
func (sf *tester) check() {
	sf.t.Log("check")
	sf.checkBad1()
	sf.checkBad2()
	sf.checkGood1()
}

func (sf *tester) checkGood1() {
	sf.t.Log("checkGood1")
	app := fiber.New()
	app.Get("/anonym/find_check_prefix", sf.anonFind.findCheckPrefix)
	formVal := url.Values{
		"key": {"key"},
	}
	req, err := http.NewRequest("GET", "/anonym/find_check_prefix", strings.NewReader(formVal.Encode()))
	if err != nil {
		sf.t.Fatalf("checkGood1(): err=\n\t%v", err)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	resp, err := app.Test(req)
	if err != nil {
		sf.t.Fatalf("checkGood1(): err=\n\t%v", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		sf.t.Fatalf("checkGood1(): resp.Status=%v", resp.Status)
	}
}

// Пустой ключ в запросе
func (sf *tester) checkBad2() {
	sf.t.Log("checkBad2")
	app := fiber.New()
	app.Get("/anonym/find_check_prefix", sf.anonFind.findCheckPrefix)
	formVal := url.Values{
		"key": {""},
	}
	req, err := http.NewRequest("GET", "/anonym/find_check_prefix", strings.NewReader(formVal.Encode()))
	if err != nil {
		sf.t.Fatalf("checkBad2(): err=\n\t%v", err)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	resp, err := app.Test(req)
	if err != nil {
		sf.t.Fatalf("checkBad2(): err=\n\t%v", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		sf.t.Fatalf("checkBad2(): resp.Status=%v", resp.Status)
	}
}

// Кривой запрос по префиксу
func (sf *tester) checkBad1() {
	sf.t.Log("checkBad1")
	app := fiber.New()
	app.Get("/anonym/find_check_prefix", sf.anonFind.findCheckPrefix)
	req, err := http.NewRequest("GET", "/anonym/find_check_prefix", nil)
	if err != nil {
		sf.t.Fatalf("checkBad1(): err=\n\t%v", err)
	}
	resp, err := app.Test(req)
	if err != nil {
		sf.t.Fatalf("checkBad1(): err=\n\t%v", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		sf.t.Fatalf("checkBad1(): resp.Status=%v", resp.Status)
	}
}

// Создаёт новый обработчик поиска списка анонимных ключей по префиксу
func (sf *tester) create() {
	sf.t.Log("create")
	sf.createBad1()
	sf.createBad2()
	sf.createGood1()
}

func (sf *tester) createGood1() {
	sf.t.Log("createGood1")
	var err error
	sf.anonFind, err = NewAnonymFind(sf.web, sf.router)
	if err != nil {
		sf.t.Fatalf("createGood1(): err=\n\t%v", err)
	}
	if sf.anonFind == nil {
		sf.t.Fatalf("createGood1(): anonFind==nil")
	}
	if serv := sf.anonFind.serv; serv == nil {
		sf.t.Fatalf("createGood1(): serv==nil")
	}
	if store := sf.anonFind.store; store == nil {
		sf.t.Fatalf("createGood1(): store==nil")
	}
}

// Нет объекта роутера
func (sf *tester) createBad2() {
	sf.t.Log("createBad2")
	anonFind, err := NewAnonymFind(sf.web, nil)
	if err == nil {
		sf.t.Fatalf("createBad2(): err==nil")
	}
	if anonFind != nil {
		sf.t.Fatalf("createBad2(): anonFind!=nil")
	}
}

// Нет объекта веб-сервера
func (sf *tester) createBad1() {
	sf.t.Log("createBad1")
	sf.serv = mock_service.NewMockService()
	var err error
	sf.web, err = mock_web.NewMockWeb(sf.serv)
	if err != nil {
		sf.t.Fatalf("createBad1(): err=\n\t%v", err)
	}
	sf.serv.Store_, err = mock_store.NewMockStore(sf.serv)
	if err != nil {
		sf.t.Fatalf("createBad1(): err=\n\t%v", err)
	}
	sf.router = sf.web.FiberApp().Group("/anonym")
	anonFind, err := NewAnonymFind(nil, sf.router)
	if err == nil {
		sf.t.Fatalf("createBad1(): err==nil")
	}
	if anonFind != nil {
		sf.t.Fatalf("createBad1(): anonFind!=nil")
	}
}
