package peachy_test

import (
	"os"
	"path/filepath"
	"testing"

	"git.codemonkeysoftware.net/b/peachy-go"
	"github.com/shoenig/test/must"
	"zombiezen.com/go/sqlite"
)

func pending(t *testing.T) {
	t.Fatalf("test not implemented")
}

func closeIfExists(db *peachy.DB) {
	if db != nil {
		db.Close()
	}
}

func TestOpen(t *testing.T) {
	t.Run("Open succeeds on DB created by Create", func(t *testing.T) {
		dir := t.TempDir()
		dbPath := filepath.Join(dir, "test.db")
		db, err := peachy.Create(dbPath)
		must.NoError(t, err)
		db.Close()

		db, err = peachy.Open(dbPath)
		defer closeIfExists(db)
		must.NotNil(t, db)
		must.NoError(t, err)

		// TODO Make sure the DB works once it has any methods.
	})
	t.Run("Open fails on alien SQLite DB", func(t *testing.T) {
		dir := t.TempDir()
		dbPath := filepath.Join(dir, "test.db")
		conn, err := sqlite.OpenConn(dbPath)
		must.NoError(t, err)
		conn.Close()

		db, err := peachy.Open(dbPath)
		defer closeIfExists(db)
		must.Nil(t, db)
		must.ErrorIs(t, err, peachy.ErrInvalidDB)
	})
	t.Run("Open fails on nonexistent file", func(t *testing.T) {
		dir := t.TempDir()
		dbPath := filepath.Join(dir, "test.db")
		db, err := peachy.Open(dbPath)
		defer closeIfExists(db)
		must.Nil(t, db)
		must.ErrorIs(t, err, peachy.ErrFileNotExist)
		must.FileNotExists(t, dbPath)
	})
	t.Run("Open fails on non-SQLite file", func(t *testing.T) {
		path := filepath.Join(t.TempDir(), "test.db")
		err := os.WriteFile(path, []byte("I'm not a database."), os.ModePerm)
		must.NoError(t, err)

		db, err := peachy.Open(path)
		defer closeIfExists(db)
		must.Nil(t, db)
		must.ErrorIs(t, err, peachy.ErrInvalidDB, must.Sprint(sqlite.ErrCode(err)))
	})
}

func TestCompositeTypes(t *testing.T) {
	db, err := peachy.Create(":memory:")
	must.NoError(t, err)
	defer db.Close()

	addedTypes := []peachy.CompositeType{
		{Name: "alpha", Kind: peachy.Record},
		{Name: `"bravo`, Kind: peachy.Variant},
		{Name: " charl!e"},
	}
	for _, ty := range addedTypes {
		err := db.AddCompositeType(ty.Name, ty.Kind)
		must.NoError(t, err)
	}

	gotTypes, err := db.GetCompositeTypes()
	must.NoError(t, err)
	must.SliceContainsAllOp(t, addedTypes, gotTypes)
}
