package om

import (
	"os"
	"testing"

	"git.simanc.com/software/golib/v4/features/sdb"
	"git.simanc.com/software/golib/v4/pkg/tuid"
)

var (
	tbl *ORM
)

func TestORM_InsertOne(t *testing.T) {
	row := sdb.M{
		"name":      "XiaoMing",
		"username":  "littleMin",
		"age":       10,
		"role":      "user",
		"available": true,
		"sn":        tuid.New(),
	}
	err := tbl.InsertOne(row)
	if err != nil {
		t.Error(err)
		return
	}
}

func TestORM_InsertMany(t *testing.T) {
	rows := []sdb.M{
		{
			"name":      "LiHua",
			"username":  "lihua",
			"age":       13,
			"role":      "admin",
			"available": true,
			"sn":        tuid.New(),
		},
		{
			"name":      "amy",
			"username":  "amy",
			"age":       12,
			"role":      "user",
			"available": true,
			"sn":        tuid.New(),
		},
		{
			"name":      "Mr. Liu",
			"username":  "liu",
			"age":       33,
			"role":      "sysadmin",
			"available": true,
			"sn":        tuid.New(),
		},
	}
	err := tbl.InsertMany(rows)
	if err != nil {
		t.Error(err)
		return
	}
}

func TestORM_InsertAny(t *testing.T) {
	type test struct {
		Name      string `json:"name"`
		UserName  string `json:"username"`
		Age       int64  `json:"age"`
		Role      string `json:"role"`
		Available bool   `json:"available"`
		Sn        string `json:"sn"`
		Test111   string `json:"test111,none"`
		Test222   int64  `json:"test222,none"`
	}
	t1 := test{
		Name:      "test1",
		UserName:  "test1",
		Age:       1,
		Role:      "tester",
		Available: true,
		Sn:        tuid.New(),
		Test111:   "xxx",
		Test222:   666,
	}
	err := tbl.InsertAny(t1)
	if err != nil {
		t.Error(err)
		return
	}
	ts := []test{
		{
			Name:      "test2",
			UserName:  "test2",
			Age:       2,
			Role:      "tester",
			Available: true,
			Sn:        tuid.New(),
			Test111:   "xxx",
			Test222:   777,
		},
		{
			Name:      "test3",
			UserName:  "test3",
			Age:       3,
			Role:      "tester",
			Available: true,
			Sn:        tuid.New(),
			Test111:   "xxx",
			Test222:   888,
		},
	}
	err = tbl.InsertAny(ts)
	if err != nil {
		t.Error(err)
		return
	}
}

func TestORM_FindOne(t *testing.T) {
	// row, err := tbl.FindOne(Params{"name": "XiaoMing"})
	row, err := tbl.FindOne(Params{"!name": []string{"XiaoMing"}})
	if err != nil {
		t.Error(err)
		return
	}
	t.Log(row)
}

func TestORM_Find(t *testing.T) {
	// row, err := tbl.Find(Params{"!name": []string{"XiaoMing"}}, LimitParams{Offset: 1}, OrderBy{"username": OrderASC})
	row, err := tbl.Find(Params{"|name": []string{"XiaoMing", "amy"}, ">age": 10}, LimitParams{}, OrderBy{})
	if err != nil {
		t.Error(err)
		return
	}
	for _, m := range row {
		t.Log(m)
	}
}

func TestORM_Count(t *testing.T) {
	count, err := tbl.Count(Params{"role": "user"})
	if err != nil {
		t.Error(err)
		return
	}
	t.Log(count)
}

func TestORM_Update(t *testing.T) {
	err := tbl.Update(Params{"name": "LiHua"}, sdb.M{"age": 13})
	if err != nil {
		t.Error(err)
		return
	}
}

func TestORM_UpdateBySn(t *testing.T) {
	row, err := tbl.FindOne(Params{})
	if err != nil {
		t.Error(err)
		return
	}
	sn := row.String("sn")
	err = tbl.UpdateBySn(sn, sdb.M{"available": false})
	if err != nil {
		t.Error(err)
		return
	}
}

func TestORM_Delete(t *testing.T) {
	err := tbl.Delete(Params{"name": "XiaoMing"})
	if err != nil {
		t.Error(err)
		return
	}
}

func TestCreateTableSQL(t *testing.T) {
	cols := []TableColumn{
		{Key: "name", Type: sdb.TypeTEXT},
		{Key: "username", Type: sdb.TypeTEXT},
		{Key: "age", Type: sdb.TypeINTEGER},
		{Key: "role", Type: sdb.TypeTEXT},
		{Key: "available", Type: sdb.TypeBOOLEAN, Default: true},
	}
	sql := CreateTableSQL("test", cols)
	t.Log(sql)
}

func init() {
	const dbName = "om_test.db"
	if _, err := os.Stat(dbName); err != nil {
		if os.IsNotExist(err) {
			fi, err := os.Create(dbName)
			if err != nil {
				panic(err)
			}
			_ = fi.Close()
			db, err := sdb.Open(dbName)
			if err != nil {
				panic(err)
			}
			col := []TableColumn{
				{Key: "name", Type: sdb.TypeTEXT},
				{Key: "username", Type: sdb.TypeTEXT},
				{Key: "age", Type: sdb.TypeINTEGER},
				{Key: "role", Type: sdb.TypeTEXT},
				{Key: "available", Type: sdb.TypeBOOLEAN},
				{Key: "account", Type: "OBJECT"},
			}
			err = db.Exec(CreateTableSQL("test", col))
			if err != nil {
				panic(err)
			}
			_ = db.Close()
		} else {
			panic(err)
		}
	}
	if err := Open(dbName); err != nil {
		panic(err)
	}
	tbl = Table("test")
}
