package mod_wui

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

	"gitp78su.ipnodns.ru/svi/kern/v2/krn/kctx"
	"gitp78su.ipnodns.ru/svi/kern/v2/wui/wbutton"
	"gitp78su.ipnodns.ru/svi/kern/v2/wui/wlabel"

	"gitp78su.ipnodns.ru/svi/kern/v2/krn/kmonolit"
	"gitp78su.ipnodns.ru/svi/kern/v2/krn/kserv_http"
	. "gitp78su.ipnodns.ru/svi/kern/v2/krn/ktypes"
	"gitp78su.ipnodns.ru/svi/kern/v2/mock/mock_env"
)

type tester struct {
	t    *testing.T
	ctx  IKernelCtx
	serv IKernelServerHttp
	mod  IKernelModule
}

func TestModKernelCtx(t *testing.T) {
	sf := &tester{
		t:   t,
		ctx: kctx.GetKernelCtx(),
	}
	sf.ctx.Set("monolitName", "test_monolit", "test")
	sf.new()
	sf.click()
	sf.done()
}

// Кто-то кликнул в сети на кнопку
func (sf *tester) click() {
	sf.t.Log("click")
	sf.clickBad1()
	sf.clickBad2()
	sf.clickGood1()
	sf.clickGood2()
	sf.clickBad3()
}

// С кривой POST-формой
func (sf *tester) clickBad3() {
	sf.t.Log("clickBad3")
	btn := wbutton.NewWuiButton("test_btn", sf.fnClick)
	fiberApp := sf.serv.Fiber()
	// Данные формы
	reader := strings.NewReader("tra-ta-ta")
	req, err := http.NewRequest("POST", "/wui/click/"+btn.Id(), reader)
	if err != nil {
		sf.t.Fatalf("clickBad3(): in net request, err=%v", err)
	}
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Add("Token-1", "123;original-1")
	req.Header.Add("Token-2", "")
	resp, err := fiberApp.Test(req)
	if err != nil {
		sf.t.Fatalf("clickBad3(): in make POST, err=%v", err)
	}
	if resp.StatusCode != 200 {
		sf.t.Fatalf("clickBad3(): status(%v)!=200", resp.StatusCode)
	}
}

// С POST-формой
func (sf *tester) clickGood2() {
	sf.t.Log("clickGood2")
	btn := wbutton.NewWuiButton("test_btn", sf.fnClick)
	fiberApp := sf.serv.Fiber()
	// Данные формы
	formData := url.Values{
		"username": {"john_doe"},
		"email":    {"john.doe@example.com"},
		"password": {"s3cr3t", "valid"},
	}
	reader := strings.NewReader(formData.Encode())
	req, err := http.NewRequest("POST", "/wui/click/"+btn.Id(), reader)
	if err != nil {
		sf.t.Fatalf("clickGood2(): in net request, err=%v", err)
	}
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Add("Token-1", "123;original-1")
	req.Header.Add("Token-2", "")
	req.Header.Clone().Add("Token-1", "555;original-2")
	resp, err := fiberApp.Test(req)
	if err != nil {
		sf.t.Fatalf("clickGood2(): in make POST, err=%v", err)
	}
	if resp.StatusCode != 200 {
		sf.t.Fatalf("clickGood2(): status(%v)!=200", resp.StatusCode)
	}
}

// Без POST-формы
func (sf *tester) clickGood1() {
	sf.t.Log("clickGood1")
	btn := wbutton.NewWuiButton("test_btn", sf.fnClick)
	fiberApp := sf.serv.Fiber()
	req, err := http.NewRequest("POST", "/wui/click/"+btn.Id(), nil)
	if err != nil {
		sf.t.Fatalf("clickGood1(): in net request, err=%v", err)
	}
	resp, err := fiberApp.Test(req)
	if err != nil {
		sf.t.Fatalf("clickGood1(): in make POST, err=%v", err)
	}
	if resp.StatusCode != 200 {
		sf.t.Fatalf("clickGood1(): status(%v)!=200", resp.StatusCode)
	}
}

// Обратный вызов клика
func (sf *tester) fnClick(dict map[string]string) string {
	sf.t.Log("fnClick")
	return "test_click"
}

// Неправильный тип объекта
func (sf *tester) clickBad2() {
	sf.t.Log("clickBad2")
	lbl := wlabel.NewWuiLabel("test_lbl")
	fiberApp := sf.serv.Fiber()
	req, err := http.NewRequest("POST", "/wui/click/"+lbl.Id(), nil)
	if err != nil {
		sf.t.Fatalf("clickBad2(): in net request, err=%v", err)
	}
	resp, err := fiberApp.Test(req)
	if err != nil {
		sf.t.Fatalf("clickBad2(): in make POST, err=%v", err)
	}
	if resp.StatusCode != 200 {
		sf.t.Fatalf("clickBad2(): status(%v)!=200", resp.StatusCode)
	}
}

// Нет такой кнопки
func (sf *tester) clickBad1() {
	sf.t.Log("clickBad1")
	fiberApp := sf.serv.Fiber()
	req, err := http.NewRequest("POST", "/wui/click/ert", nil)
	if err != nil {
		sf.t.Fatalf("clickBad1(): in net request, err=%v", err)
	}
	resp, err := fiberApp.Test(req)
	if err != nil {
		sf.t.Fatalf("clickBad1(): in make POST, err=%v", err)
	}
	if resp.StatusCode != 200 {
		sf.t.Fatalf("clickBad1(): status(%v)!=200", resp.StatusCode)
	}
}

// Завершение работы
func (sf *tester) done() {
	sf.t.Log("done")
	if log := sf.mod.Log(); log != sf.mod.(*ModuleWui).log {
		sf.t.Fatalf("done(): log is bad")
	}
	sf.ctx.Cancel()
	sf.ctx.Wg().Wait()
	if isWork := sf.mod.IsWork(); isWork {
		sf.t.Fatalf("done(): isWork==true")
	}
}

// Создание нового модуля HTTP-сервера
func (sf *tester) new() {
	sf.t.Log("new")
	sf.newBad1()
	sf.newGood1()
}

func (sf *tester) newGood1() {
	sf.t.Log("newGood1")
	_ = mock_env.MakeEnv()
	_ = os.Unsetenv("LOCAL_HTTP_URL")
	os.Setenv("LOCAL_HTTP_URL", "http://localhost:18330/")
	sf.mod = GetModuleWui()
	kCtx := kctx.GetKernelCtx()
	kCtx.Set("isLocal", true, "type msg bus")
	_ = kmonolit.GetMonolit("test_monolit")
	sf.serv = kserv_http.GetKernelServHttp()
	_ = GetModuleWui()
	if sf.mod == nil {
		sf.t.Fatalf("newGood1(): mod==nil")
	}

	go sf.mod.Run()
	for {
		time.Sleep(time.Millisecond * 1)
		if sf.mod.IsWork() {
			break
		}
	}
	go sf.serv.Run()
}

// нет ничего для создания модуля
func (sf *tester) newBad1() {
	sf.t.Log("newBad1")
	defer func() {
		if _panic := recover(); _panic == nil {
			sf.t.Fatalf("newBad1(): panic==nil")
		}
	}()
	_ = GetModuleWui()
}
