package test

import (
	"context"
	"fmt"
	"github.com/stretchr/testify/assert"
	"github.com/tidbcloud/account/idl/pbgen/proto/account"
	"go.uber.org/zap"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"log"
	"sync"
	"testing"
	"time"
)

// @Time    : 2022/7/25 1:32 PM
// @Author  : lvhongmeng
var (
	accountOnce sync.Once
	client      account.AccountAPIServiceClient
)

func getAccountClient() account.AccountAPIServiceClient {
	addr := "127.0.0.1:10000"
	accountOnce.Do(func() {
		logger, err := zap.NewProduction()
		if err != nil {
			log.Fatalf("failed to init zap logger")
		}
		defer logger.Sync()
		time.Sleep(time.Second * 5)
		conn, err := grpc.DialContext(
			context.Background(),
			addr,
			grpc.WithTransportCredentials(insecure.NewCredentials()),
		)
		if err != nil {
			panic(fmt.Sprintf("dial account-provider-svc: %s", err))
		}
		client = account.NewAccountAPIServiceClient(conn)
	})

	return client
}

func TestGetUserByEmail(t *testing.T) {
	client := getAccountClient()
	res, err := client.GetUserByEmail(context.Background(), &account.GetUserByEmailRequest{
		Email: "hongmeng.lv@pingcap.com",
	})
	if err != nil {
		log.Fatalf("err: %v", err)
	}
	log.Printf("TestGetUserByEmail info: %s", res.User)
	//	server check
	assert.Equalf(t, int64(0), res.BaseResp.ErrCode, "server error")

	assert.Equalf(t, "hongmeng.lv@pingcap.com", res.User.Email, "email not equal")

}

func TestGetUserByID(t *testing.T) {
	client := getAccountClient()
	res, err := client.GetUserByID(context.Background(), &account.GetUserByIDRequest{
		UserId: 1,
	})
	if err != nil {
		log.Fatalf("err: %v", err)
	}
	log.Printf("TestGetUserByID info: %s", res.User)
	//	server check
	assert.Equalf(t, int64(0), res.BaseResp.ErrCode, "server error")

	assert.Equalf(t, uint64(1), res.User.Id, "userid not equal")

}

func TestListUsers(t *testing.T) {
	client := getAccountClient()
	res, err := client.ListUsers(context.Background(), &account.UserFilter{
		UserIds: []uint64{1, 2, 3},
	})
	if err != nil {
		log.Fatalf("err: %v", err)
	}
	log.Printf("TestListUsers info: %s", res.Users)
	//	server check
	assert.Equalf(t, int64(0), res.BaseResp.ErrCode, "server error")

	assert.Equalf(t, 3, len(res.Users), "user len not equal")

}

func TestGetSystemUser(t *testing.T) {
	client := getAccountClient()
	res, err := client.GetSystemUser(context.Background(), &account.GetSystemUserRequest{
		OrgId: uint64(1),
	})
	if err != nil {
		log.Fatalf("err: %v", err)
	}
	log.Printf("TestGetSystemUser info: %s", res.User)
	//	server check
	assert.Equalf(t, int64(0), res.BaseResp.ErrCode, "server error")

	assert.Equalf(t, "system", res.User.FirstName, "system user fistname error")
	assert.Equalf(t, "user", res.User.LastName, "system user lastname error")
}

func TestGetAuthUser(t *testing.T) {
	client := getAccountClient()
	res, err := client.GetAuthUser(context.Background(), &account.GetAuthUserRequest{
		OrgId:     uint64(60059),
		UserEmail: "hongmeng.lv@pingcap.com",
	})
	if err != nil {
		log.Fatalf("err: %v", err)
	}
	log.Printf("TestGetAuthUser info: %s", res.User)
	//	server check
	assert.Equalf(t, int64(0), res.BaseResp.ErrCode, "server error")

	assert.Equalf(t, uint64(60059), res.Org.Id, "orgid not equal")
	assert.Equalf(t, false, res.IsImpersonated, "impersonated is not equal")
	assert.Equalf(t, "hongmeng.lv@pingcap.com", res.User.Email, "email is not equal")
}

func TestListProjectsByOrgsInUser(t *testing.T) {
	client := getAccountClient()
	res, err := client.ListProjectsByOrgsInUser(context.Background(), &account.ListProjectsByOrgsInUserRequest{
		UserId: uint64(70098),
		OrgIds: []uint64{60059},
	})
	if err != nil {
		log.Fatalf("err: %v", err)
	}
	log.Printf("TestListProjectsByOrgsInUser info: %s", res.Projects)
	//	server check
	assert.Equalf(t, int64(0), res.BaseResp.ErrCode, "server error")

	for _, tmp := range res.Projects {
		assert.Equalf(t, uint64(60059), tmp.OrgId, "orgid not equal")
		assert.Equalf(t, uint64(73540), tmp.Projects[0].GetId(), "projectid not equal")
	}

}

func TestGetProjectByID(t *testing.T) {
	client := getAccountClient()
	res, err := client.GetProjectByID(context.Background(), &account.GetProjectByIDRequest{
		Id: 1,
	})
	if err != nil {
		log.Fatalf("err: %v", err)
	}
	log.Printf("TestGetProjectByID info: %s", res.Project)
	//	server check
	assert.Equalf(t, int64(0), res.BaseResp.ErrCode, "server error")

	assert.Equalf(t, uint64(1), res.Project.Id, "projectid not equal")
}

func TestListProjects(t *testing.T) {
	client := getAccountClient()
	res, err := client.ListProjects(context.Background(), &account.ProjectFilter{
		OrgIds: []uint64{1},
		Status: []string{"active"},
	})
	if err != nil {
		log.Fatalf("err: %v", err)
	}
	log.Printf("TestListProjects info: %s", res.Projects)
	//	server check
	assert.Equalf(t, int64(0), res.BaseResp.ErrCode, "server error")

	for _, tmp := range res.Projects {
		assert.Equalf(t, uint64(1), tmp.TenantId, "orgid not equal")
		assert.Equalf(t, "active", tmp.Status, "status not equal")
	}

}

func TestGetOrgByID(t *testing.T) {
	client := getAccountClient()
	res, err := client.GetOrgByID(context.Background(), &account.GetOrgByIDRequest{
		Id: 1,
	})
	if err != nil {
		log.Fatalf("err: %v", err)
	}
	log.Printf("TestGetOrgByID info: %s", res.Org)
	//	server check
	assert.Equalf(t, int64(0), res.BaseResp.ErrCode, "server error")

	assert.Equalf(t, uint64(1), res.Org.Id, "orgid not equal")
}

func TestListOrgs(t *testing.T) {
	client := getAccountClient()
	res, err := client.ListOrgs(context.Background(), &account.OrgFilter{
		Ids:    []uint64{1},
		Status: []string{"active"},
	})
	if err != nil {
		log.Fatalf("err: %v", err)
	}
	log.Printf("TestGetOrgByID info: %s", res.Orgs)
	//	server check
	assert.Equalf(t, int64(0), res.BaseResp.ErrCode, "server error")

	for _, tmp := range res.Orgs {
		assert.Equalf(t, uint64(1), tmp.Id, "orgid not equal")
		assert.Equalf(t, "active", tmp.Status, "status not equal")
	}

}

func TestListOrgsByUser(t *testing.T) {
	client := getAccountClient()
	res, err := client.ListOrgsByUser(context.Background(), &account.ListOrgsByUserRequest{UserId: uint64(70098)})
	if err != nil {
		log.Fatalf("err: %v", err)
	}
	log.Printf("TestListOrgsByUser info: %s", res.Orgs)
	//	server check
	assert.Equalf(t, int64(0), res.BaseResp.ErrCode, "server error")

	assert.Equalf(t, uint64(60059), res.Orgs[0].GetId(), "orgid not equal")
}

func TestListTrials(t *testing.T) {
	client := getAccountClient()
	res, err := client.ListTrials(context.Background(), &account.TrialFilter{OrgId: uint64(1)})
	if err != nil {
		log.Fatalf("err: %v", err)
	}
	log.Printf("TestListTrials info: %s", res.Trials)
	//	server check
	assert.Equalf(t, int64(0), res.BaseResp.ErrCode, "server error")

	for _, tmp := range res.Trials {
		assert.Equalf(t, uint64(1), tmp.OrgId, "orgid not equal")
	}

}

// delete audit_logs rpc not found,so run this ,remember delete manually
//func TestCreateAuditLog(t *testing.T) {
//	client := getAccountClient()
//	res, err := client.CreateAuditLog(context.Background(), &account.CreateAuditLogRequest{
//		AuditLog: &account.AuditLog{
//			OrgId:   1,
//			User:    "test",
//			Content: "test",
//		},
//	})
//	if err != nil {
//		log.Fatalf("err: %v", err)
//	}
//	log.Printf("TestListTrials info: %s", res.AuditLog)
//	//	server check
//	assert.Equalf(t, int64(0), res.BaseResp.ErrCode, "server error")
//}

//delete users rpc not found,so run this ,remember delete manually
//func TestGetOrCreateSystemUser(t *testing.T) {
//	client := getAccountClient()
//	res, err := client.GetOrCreateSystemUser(context.Background(), &account.GetOrCreateSystemUserRequest{
//		OrgId: uint64(33333),
//	})
//	if err != nil {
//		log.Fatalf("err: %v", err)
//	}
//	log.Printf("TestGetOrCreateSystemUser info: %s", res.User)
//	//	server check
//	assert.Equalf(t, int64(0), res.BaseResp.ErrCode, "server error")
//}
