package user

import (
	"context"
	"log"
	"os"
	"testing"

	"github.com/tidbcloud/account/internel/dao/entity"
	"github.com/tidbcloud/account/pkg/docker_db"
	"gorm.io/gorm"
)

var db *gorm.DB

func init() {
	var err error
	db, err = docker_db.TryInitCentralDB(true)
	if err != nil {
		log.Printf("Failed to init docker db: %s", err)
		os.Exit(-1)
		return
	}
}

func TestGetUserForLocalEnvHonorsRequestedOrg(t *testing.T) {
	email := "cp9-local-org-switch@example.com"
	homeOrgID := entity.ID(1440002)
	requestedOrgID := entity.ID(1440003)
	user := entity.User{
		TenantID:    homeOrgID,
		FirstName:   "CP9",
		LastName:    "Local",
		Email:       email,
		Status:      entity.UserStatusActive,
		Job:         "",
		PhoneNumber: "",
		Role:        entity.UserRoleMember,
	}
	if err := db.Create(&user).Error; err != nil {
		t.Fatalf("create user: %v", err)
	}
	t.Cleanup(func() {
		db.Unscoped().Delete(&user)
	})
	binding := entity.RoleBinding{
		TargetType: entity.RoleBindingTargetUser,
		TargetID:   user.ID,
		ScopeType:  entity.RoleBindingScopeOrg,
		ScopeID:    requestedOrgID,
		Role:       "org:owner",
		Status:     entity.RoleBindingStatusActive,
		RoleID:     1,
	}
	if err := db.Create(&binding).Error; err != nil {
		t.Fatalf("create role binding: %v", err)
	}
	t.Cleanup(func() {
		db.Delete(&binding)
	})

	got, found, err := getUserForLocalEnv(
		context.Background(),
		email,
		requestedOrgID.Uint64(),
		false,
	)
	if err != nil || !found {
		t.Fatalf("get requested org: found=%t err=%v", found, err)
	}
	if got.TenantID != requestedOrgID {
		t.Fatalf("tenant ID = %d, want %d", got.TenantID, requestedOrgID)
	}

	if _, _, err := getUserForLocalEnv(
		context.Background(),
		email,
		requestedOrgID.Uint64()+1,
		false,
	); err == nil {
		t.Fatal("unbound organization was accepted")
	}
}

//func TestGetUserOrg(t *testing.T) {
//	convey.Convey("GetUserOrg", t, func() {
//		ctrl := gomock.NewController(t)
//		defer ctrl.Finish()
//
//		mockHub := dao.NewMockHub(ctrl)
//
//		s := NewUserSvc()
//
//		var impersonatedOrgID uint64 = 2
//
//		convey.Convey("GetUserOrg", func() {
//			ctx := context.TODO()
//
//			tenantUser := &User{
//				IsImpersonated: false,
//				TenantID:       entity.ID(impersonatedOrgID),
//				User:           entity.User{},
//			}
//
//			ctx = context.WithValue(ctx, auth0.AuthTokenClaimKey, tenantUser)
//
//			mockHub.Mock.Org.EXPECT().GetOrgByOrgID(ctx, gomock.Any(), impersonatedOrgID)
//
//			_, err := s.GetUserOrg(ctx)
//			convey.So(err, convey.ShouldBeNil)
//		})
//	})
//}

//func TestUserSvc_GetUserByEmail(t *testing.T) {
//	ctrl := gomock.NewController(t)
//	defer ctrl.Finish()
//	ctx := context.TODO()
//	mockedHub := dao.NewDaoMockHub(ctrl).NewHub()
//	svc := NewUserSvc()
//
//	convey.Convey("GetUserByEmail", t, func() {
//		mockedHub.Mock.User.EXPECT().GetUserByEmail(ctx, gomock.Any(), "email")
//		_, err := svc.GetUserByEmail(ctx, "email")
//		convey.So(err, convey.ShouldBeNil)
//	})
//}

//func TestUserSvc_GetUserByID(t *testing.T) {
//	ctrl := gomock.NewController(t)
//	defer ctrl.Finish()
//	ctx := context.TODO()
//	mockedHub := dao.NewDaoMockHub(ctrl).NewHub()
//	svc := NewUserSvc()
//
//	convey.Convey("GetUserByID", t, func() {
//		var userID uint64 = 1
//		mockedHub.Mock.User.EXPECT().GetUserByID(ctx, gomock.Any(), userID)
//		_, err := svc.GetUserByID(ctx, userID)
//		convey.So(err, convey.ShouldBeNil)
//	})
//}

//func TestUserSvc_GetSystemUserByOrgID(t *testing.T) {
//	ctrl := gomock.NewController(t)
//	defer ctrl.Finish()
//	ctx := context.TODO()
//	mockedHub := dao.NewDaoMockHub(ctrl).NewHub()
//	svc := NewUserSvc()
//
//	convey.Convey("GetSystemuserByOrgID", t, func() {
//		var orgID uint64 = 1
//		mockedHub.Mock.User.EXPECT().GetSystemUserByOrgID(ctx, gomock.Any(), orgID)
//		_, err := svc.GetSystemUserByOrgID(ctx, orgID)
//		convey.So(err, convey.ShouldBeNil)
//	})
//}

//func TestUserSvc_IsImpersonatedUserInOrg(t *testing.T) {
//	ctrl := gomock.NewController(t)
//	defer ctrl.Finish()
//	ctx := context.TODO()
//	mockedHub := dao.NewDaoMockHub(ctrl).NewHub()
//	svc := NewUserSvc()
//
//	convey.Convey("IsImpersonatedUserInOrg", t, func() {
//		var (
//			userID uint64 = 1
//			orgID  uint64 = 2
//		)
//
//		mockedHub.Mock.User.EXPECT().IsImpersonatedUserInOrg(ctx, gomock.Any(), userID, orgID)
//		_, _, err := svc.IsImpersonatedUserInOrg(ctx, userID, orgID)
//		convey.So(err, convey.ShouldBeNil)
//	})
//}

//func TestUserSvc_GetAuthUserByEmail(t *testing.T) {
//	ctrl := gomock.NewController(t)
//	defer ctrl.Finish()
//	ctx := context.TODO()
//	mockedHub := dao.NewDaoMockHub(ctrl).NewHub()
//	svc := NewUserSvc(db, mockedHub)
//	user := entity.User{}
//	orgs := []entity.Tenant{}
//
//	convey.Convey("GetAuthUserByEmail", t, func() {
//		convey.Convey("user not found", func() {
//			mockedHub.Mock.User.EXPECT().GetUserByEmail(ctx, gomock.Any(), "email").Return(nil, gorm.ErrRecordNotFound)
//
//			user, err := svc.GetAuthUserByEmail(ctx, "email", 1, false)
//			convey.So(err, convey.ShouldNotBeNil)
//			convey.So(user, convey.ShouldBeNil)
//		})
//
//		convey.Convey("is impersonated error", func() {
//			mockedHub.Mock.User.EXPECT().GetUserByEmail(ctx, gomock.Any(), "email").Return(&user, nil)
//			mockedHub.Mock.User.EXPECT().GetImpersonatedUser(ctx, gomock.Any(), gomock.Any()).Return(nil, false, gorm.ErrRecordNotFound)
//
//			user, err := svc.GetAuthUserByEmail(ctx, "email", 1, false)
//			convey.So(err, convey.ShouldNotBeNil)
//			convey.So(user, convey.ShouldBeNil)
//		})
//
//		convey.Convey("user does not belong to org", func() {
//			mockedHub.Mock.User.EXPECT().GetUserByEmail(ctx, gomock.Any(), "email").Return(&user, nil)
//			mockedHub.Mock.User.EXPECT().GetImpersonatedUser(ctx, gomock.Any(), gomock.Any()).Return(nil, false, nil)
//			mockedHub.Mock.Cross.EXPECT().IsUserInOrg(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(false, nil)
//
//			user, err := svc.GetAuthUserByEmail(ctx, "email", 2, false)
//			convey.So(err, convey.ShouldNotBeNil)
//			convey.So(user, convey.ShouldBeNil)
//		})
//
//		convey.Convey("get org failed", func() {
//			mockedHub.Mock.User.EXPECT().GetUserByEmail(ctx, gomock.Any(), "email").Return(&user, nil)
//			mockedHub.Mock.User.EXPECT().GetImpersonatedUser(ctx, gomock.Any(), gomock.Any()).Return(nil, false, nil)
//			mockedHub.Mock.Cross.EXPECT().IsUserInOrg(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil)
//			mockedHub.Mock.Org.EXPECT().GetOrgByOrgID(ctx, gomock.Any(), gomock.Any()).Return(nil, gorm.ErrRecordNotFound)
//
//			user, err := svc.GetAuthUserByEmail(ctx, "email", 0, false)
//			convey.So(err, convey.ShouldNotBeNil)
//			convey.So(user, convey.ShouldBeNil)
//		})
//
//		convey.Convey("skip check org failed", func() {
//			mockedHub.Mock.User.EXPECT().GetUserByEmail(ctx, gomock.Any(), "email").Return(&user, nil)
//			mockedHub.Mock.User.EXPECT().GetImpersonatedUser(ctx, gomock.Any(), gomock.Any()).Return(nil, false, nil)
//			mockedHub.Mock.Cross.EXPECT().ListOrgsByUserID(ctx, gomock.Any(), gomock.Any(), nil).Return(orgs, nil)
//
//			user, err := svc.GetAuthUserByEmail(ctx, "email", 0, true)
//			convey.So(err, convey.ShouldNotBeNil)
//			convey.So(user, convey.ShouldBeNil)
//		})
//
//		convey.Convey("list available projects failed", func() {
//			mockedHub.Mock.User.EXPECT().GetUserByEmail(ctx, gomock.Any(), "email").Return(&user, nil)
//			mockedHub.Mock.User.EXPECT().GetImpersonatedUser(ctx, gomock.Any(), gomock.Any()).Return(nil, false, nil)
//			mockedHub.Mock.Cross.EXPECT().IsUserInOrg(ctx, gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil)
//			mockedHub.Mock.Org.EXPECT().GetOrgByOrgID(ctx, gomock.Any(), gomock.Any()).Return(nil, nil)
//			mockedHub.Mock.Cross.EXPECT().ListActiveProjects(ctx, gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, gorm.ErrRecordNotFound)
//
//			user, err := svc.GetAuthUserByEmail(ctx, "email", 1, false)
//			convey.So(err, convey.ShouldNotBeNil)
//			convey.So(user, convey.ShouldBeNil)
//		})
//	})
//}
