package kstore_kv

import (
	"os"
	"testing"
	"time"

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

type tester struct {
	t   *testing.T
	me  *mock_env.MockEnv
	ctx IKernelCtx
	wg  IKernelWg
}

func TestKernelStore(t *testing.T) {
	ctx := kctx.GetKernelCtx()
	sf := &tester{
		t:   t,
		me:  mock_env.MakeEnv(),
		ctx: ctx,
		wg:  ctx.Wg(),
	}
	_ = os.Unsetenv("LOCAL_STORE_PATH")
	_ = os.Setenv("LOCAL_STORE_PATH", "/store/store_kernel")
	fnClear := func() {
		pwd := sf.me.Pwd() + "/store/store_kernel"
		_ = os.RemoveAll(pwd)
	}
	fnClear()
	sf.new()
	sf.set()
	sf.get()
	sf.byPrefix()
	sf.del()
	sf.close()
	sf.workBad1()
	time.Sleep(time.Second * 2)
}

// Установка ключа после закрытия хранилища
func (sf *tester) workBad1() {
	sf.t.Log("workBad1")
	res := kernStore.Set("test_key", []byte("test_val"))
	if res.IsOk() {
		sf.t.Fatalf("workBad1(): set, err==nil")
	}
	res1 := kernStore.Get("test_key")
	if res1.IsOk() {
		sf.t.Fatalf("workBad1(): get, err==nil")
	}
	res = kernStore.Delete("test_key")
	if res.IsOk() {
		sf.t.Fatalf("workBad1(): del, err==nil")
	}
}

// Удаляет значение
func (sf *tester) del() {
	sf.t.Log("del")
	res := kernStore.Delete("test_key")
	if res.IsErr() {
		sf.t.Fatalf("del(): err=%v", res.Err())
	}
	res1 := kernStore.Get("test_key")
	if res1.IsOk() {
		sf.t.Fatalf("del(): err==nil")
	}
}

// Поиск по префиксу
func (sf *tester) byPrefix() {
	sf.t.Log("byPrefix")
	res0 := kernStore.Set("test_key2", []byte("test_key2"))
	if res0.IsErr() {
		sf.t.Fatalf("byPrefix(): err=%v", res0.Err())
	}
	res := kernStore.ByPrefix("test")
	if res.IsErr() {
		sf.t.Fatalf("byPrefix(): err=%v", res.Err())
	}
	lstKey := res.Val()
	if len(lstKey) != 2 {
		sf.t.Fatalf("byPrefix(): len(%v)!=2", len(lstKey))
	}
}

// Получение значения по ключу
func (sf *tester) get() {
	sf.t.Log("get")
	res := kernStore.Get("test_key")
	if res.IsErr() {
		sf.t.Fatalf("get(): err=%v", res.Err())
	}
	strVal := string(res.Val())
	if strVal != "test_val" {
		sf.t.Fatalf("get(): strVal(%v)!='test_val'", strVal)
	}
}

// Добавление ключа в хранилище
func (sf *tester) set() {
	sf.t.Log("set")
	res := kernStore.Set("test_key", []byte("test_val"))
	if res.IsErr() {
		sf.t.Fatalf("set(): err=%v", res.Err())
	}
}

// Закрытие хранилища
func (sf *tester) close() {
	sf.t.Log("close")
	res := sf.wg.Add("123")
	if res.IsErr() {
		sf.t.Fatalf("close(): err=%v", res.Err())
	}
	sf.ctx.Cancel()
	time.Sleep(time.Millisecond * 20)
	go sf.wg.Done("123")
	sf.wg.Wait()
	kernStore.close()
	res_ := kernStore.ByPrefix("test")
	if res_.IsOk() {
		sf.t.Fatalf("close(): err==nil")
	}
}

// Создаёт новое хранилище ядра
func (sf *tester) new() {
	sf.t.Log("new")
	sf.newGood1()
}

func (sf *tester) newGood1() {
	sf.t.Log("newGood1")
	defer func() {
		if _panic := recover(); _panic != nil {
			sf.t.Fatalf("newGood1(): panic=%v", _panic)
		}
	}()
	store := GetKernelStore()
	if store == nil {
		sf.t.Fatalf("newGood1(): KernelStore==nil")
	}
	store = GetKernelStore()
	if store == nil {
		sf.t.Fatalf("newGood1(): KernelStore==nil")
	}
	if log := store.Log(); log == nil {
		sf.t.Fatalf("newGood1(): log==nil")
	}
}
