package svc

import (
	"testing"

	"git.simanc.com/software/golib/v4/features/mo"
	"git.simanc.com/software/golib/v4/infra/ii"
	"git.simanc.com/software/golib/v4/log"
)

type svcTestUser mo.M

func (u svcTestUser) Name() string                    { return "" }
func (u svcTestUser) UserName() string                { return "" }
func (u svcTestUser) Flag() bool                      { return true }
func (u svcTestUser) IsSysadmin() bool                { return true }
func (u svcTestUser) Company() mo.ObjectID            { return mo.NilObjectID }
func (u svcTestUser) CompanyALL() mo.A                { return mo.A{} }
func (u svcTestUser) Group(_ string) bool             { return false }
func (u svcTestUser) Role(_ string) (string, bool)    { return "", false }
func (u svcTestUser) Perms(_ string) ([]string, bool) { return []string{}, false }

func (u svcTestUser) ID() mo.ObjectID {
	return mo.ID.New()
}
func (u svcTestUser) Get(k string) any {
	v, ok := u[k]
	if !ok {
		return nil
	}
	return v
}

var (
	testUser ii.User = &svcTestUser{}
)

func init() {
	items, err := ii.LoadItems("_test")
	if err != nil {
		panic(err)
	}
	perms, err := ii.LoadPerms("../../ii/_test/filter.json")
	if err != nil {
		panic(err)
	}
	client, err := mo.Dial("mongodb://root:abcd1234@192.168.0.224:27017/?authSource=admin&readPreference=primary&appname=goland&directConnection=true&ssl=false")
	if err != nil {
		panic(err)
	}
	InitDefault(client, items, perms, log.Console())
}

func TestInsertMany(t *testing.T) {
	row := mo.A{
		mo.M{
			"name":     "aaa",
			"age":      20,
			"gender":   "Male",
			"phone":    "13258006534",
			"company":  mo.A{111, 222, 333},
			"role":     mo.D{{Key: "TEST", Value: "TEST"}},
			"test_obj": mo.D{{Key: "test1", Value: "111"}, {Key: "test2", Value: 222}},
		},
		mo.M{"name": "bbb", "age": 22, "gender": "Female", "phone": "17615452069", "company": mo.A{444, 555, 666}, "role": mo.M{"TEST": "TEST"}},
	}
	ids, err := With(testUser).InsertMany("test.user", row)
	if err != nil {
		t.Error(err)
		return
	}
	for _, id := range ids {
		t.Log(id)
	}
}

func TestService_DeleteMany(t *testing.T) {
	filter := mo.D{{Key: "age", Value: mo.D{{Key: "$gte", Value: 20}}}}
	err := With(testUser).DeleteMany("test.user", &mo.Matcher{Filter: filter})
	if err != nil {
		t.Error(err)
	}
}

func TestInsertManyTask(t *testing.T) {
	row := mo.A{
		mo.M{"title": "task1", "content": "example content11", "name": "aaa"},
		mo.M{"title": "task2", "content": "example content22", "name": "aaa"},
		mo.M{"title": "task3", "content": "example content33", "name": "bbb"},
		mo.M{"title": "task4", "content": "example content44", "name": "ccc"},
	}
	ids, err := With(testUser).InsertMany("test.task", row)
	if err != nil {
		t.Error(err)
		return
	}
	for _, id := range ids {
		t.Log(id)
	}
}

func TestDeleteManyTask(t *testing.T) {
	match := &mo.Matcher{}
	match.Regex("title", "task")
	err := With(testUser).DeleteMany("test.task", match)
	if err != nil {
		t.Error(err)
	}
}

func TestFind(t *testing.T) {
	docs, err := With(testUser).Find("test.user", &mo.Matcher{})
	if err != nil {
		t.Error(err)
		return
	}
	for i, doc := range docs {
		t.Log(i, doc)
	}
}

func TestFindOne(t *testing.T) {
	docs, err := With(testUser).FindOne("test.user", &mo.Matcher{})
	if err != nil {
		t.Error(err)
		return
	}
	docs.Range(func(i int, e mo.E) bool {
		t.Log(e.Key, e.Value)
		return true
	})
}

func TestUpdateOne(t *testing.T) {
	filter := &mo.Matcher{}
	filter.Eq("name", "aaa")

	up := &mo.Updater{}
	up.Set("age", 666)
	// up.Unset("age")
	// up.Pull("company", mo.A{777, 888})
	// up.Upsert(mo.D{{Key: "name", Value: "aaa"}})

	err := With(testUser).UpdateOne("test.user", filter, up)
	if err != nil {
		t.Error(err)
		return
	}
}
