// Copyright (C) 2023 Marius Schellenberger

package store

import (
	"bytes"
	"errors"
	"os"
	"path/filepath"
	"testing"
)

type testData struct {
	Data string
}

func TestBoltStore(t *testing.T) {
	data := []testData{
		{"123"},
		{"hello"},
	}
	dir, err := os.MkdirTemp("", "")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(dir)
	bs, err := NewBoltStore(filepath.Join(dir, "bolt.db"), nil)
	if err != nil {
		t.Fatal(err)
	}

	err = bs.Set("key0", data[0])
	if err != nil {
		t.Fatal(err)
	}
	err = bs.Set("key1", data[1])
	if err != nil {
		t.Fatal(err)
	}

	t.Run("GetKey0", func(t *testing.T) {
		var d testData
		err := bs.Get("key0", &d)
		if err != nil {
			t.Fatal(err)
		}
		if d != data[0] {
			t.Error("d is not data[0]")
		}
	})
	t.Run("ForEach", func(t *testing.T) {
		err := bs.ForEach(func(k string, v []byte) error {
			if k == "key0" || k == "key1" {
				return nil
			}
			return errors.New("key0 or key1 not found")
		})
		if err != nil {
			t.Fatal(err)
		}
	})
	t.Run("DumpRestore", func(t *testing.T) {
		buf := new(bytes.Buffer)
		err := bs.Dump(buf)
		if err != nil {
			t.Fatal(err)
		}
		if buf.Len() == 0 {
			t.Error("no dump written")
		}
		err = bs.Restore(buf)
		if err != nil {
			t.Fatal(err)
		}
	})
	t.Run("DeleteKey1", func(t *testing.T) {
		err := bs.Delete("key1")
		if err != nil {
			t.Fatal(err)
		}
	})
	t.Run("GetKey1", func(t *testing.T) {
		var d testData
		err := bs.Get("key1", &d)
		if err == nil {
			t.Error("key1 should be deleted")
		}
		if d == data[1] {
			t.Error("d is not data[1]")
		}
	})
	t.Run("Close", func(t *testing.T) {
		err := bs.Close()
		if err != nil {
			t.Fatal(err)
		}
	})
}
