package permission

import (
	"context"
	"testing"

	"github.com/tidbcloud/account/commons/database"
	"github.com/tidbcloud/account/internel/dao/entity"
	"github.com/tidbcloud/account/pkg/docker_db"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
	"gotest.tools/v3/assert"
)

func TestPermissionSupport_isImpersonatedUser(t *testing.T) {
	id, db, err := docker_db.InitDockerGormDB(false)
	if err != nil {
		t.Fatal(err)
	}
	defer docker_db.ReleaseDockerDB(id)

	database.DBConn.DB = db

	err = db.AutoMigrate(&entity.ImpersonatedUser{})
	if err != nil {
		t.Fatal(err)
	}
	db.Save(&entity.Tenant{
		Updatable: entity.Updatable{Base: entity.Base{ID: 2}},
		Email:     "test@pingcap.com",
		Status:    entity.TenantStatusActive,
	})
	db.Save(&entity.User{
		Updatable: entity.Updatable{Base: entity.Base{ID: 1}},
		Email:     "test@pingcap.com",
		TenantID:  2,
		Status:    entity.UserStatusActive,
	})
	db.Save(&entity.ImpersonatedUser{UserID: 1, TenantID: 2})

	ctx := context.TODO()
	tenantId, exists, err := isImpersonatedUser(ctx, 1, "test")
	tilog.Info(ctx, "is impersonated user result", zap.Any("tenantId", tenantId), zap.Any("exists", exists), zap.Any("err", err))
	assert.Assert(t, err == nil)
	assert.Assert(t, exists == true)
	assert.Assert(t, tenantId == 2)

}

func TestPermissionSupport_isScopeResourceMatch_OrgProjectMatched(t *testing.T) {
	id, db, err := docker_db.InitDockerGormDB(false)
	if err != nil {
		t.Fatal(err)
	}
	defer docker_db.ReleaseDockerDB(id)

	database.DBConn.DB = db

	err = db.AutoMigrate(&entity.Project{})
	if err != nil {
		t.Fatal(err)
	}
	err = db.AutoMigrate(&entity.ResourceRelation{})
	if err != nil {
		t.Fatal(err)
	}
	db.Save(&entity.Tenant{
		Updatable: entity.Updatable{Base: entity.Base{ID: 2}},
		Email:     "test@pingcap.com",
		Status:    entity.TenantStatusActive,
	})
	db.Save(&entity.Project{
		Updatable: entity.Updatable{Base: entity.Base{ID: 1}},
		TenantID:  entity.ID(2),
		Status:    entity.ProjectStatusActive,
	})

	ctx := context.TODO()
	match, _, err := isScopeResourceMatch(ctx, map[entity.ScopeType]entity.ID{
		entity.RoleBindingScopeProject: entity.ID(1),
		entity.RoleBindingScopeOrg:     entity.ID(2),
	})
	assert.Assert(t, err == nil)
	assert.Assert(t, match == true)
}

func TestPermissionSupport_isScopeResourceMatch_OrgProjectNotMatched(t *testing.T) {
	id, db, err := docker_db.InitDockerGormDB(false)
	if err != nil {
		t.Fatal(err)
	}
	defer docker_db.ReleaseDockerDB(id)

	database.DBConn.DB = db

	err = db.AutoMigrate(&entity.Project{})
	if err != nil {
		t.Fatal(err)
	}
	err = db.AutoMigrate(&entity.ResourceRelation{})
	if err != nil {
		t.Fatal(err)
	}
	db.Save(&entity.Tenant{
		Updatable: entity.Updatable{Base: entity.Base{ID: 2}},
		Email:     "test@pingcap.com",
		Status:    entity.TenantStatusActive,
	})
	db.Save(&entity.Project{
		Updatable: entity.Updatable{Base: entity.Base{ID: 1}},
		TenantID:  entity.ID(2),
		Status:    entity.ProjectStatusActive,
	})

	ctx := context.TODO()
	match, _, err := isScopeResourceMatch(ctx, map[entity.ScopeType]entity.ID{
		entity.RoleBindingScopeProject: entity.ID(1),
		entity.RoleBindingScopeOrg:     entity.ID(3),
	})
	assert.Assert(t, err == nil)
	assert.Assert(t, match == false)
}

func TestPermissionSupport_isScopeResourceMatch_OrgTiDBMatched(t *testing.T) {
	id, db, err := docker_db.InitDockerGormDB(false)
	if err != nil {
		t.Fatal(err)
	}
	defer docker_db.ReleaseDockerDB(id)

	database.DBConn.DB = db

	err = db.AutoMigrate(&entity.ResourceRelation{})
	if err != nil {
		t.Fatal(err)
	}
	db.Save(&entity.ResourceRelation{
		ParentType:   entity.RoleBindingScopeOrg.String(),
		ParentID:     1,
		ResourceType: entity.RoleBindingScopeTiDB.String(),
		ResourceID:   3,
	})

	ctx := context.TODO()
	match, _, err := isScopeResourceMatch(ctx, map[entity.ScopeType]entity.ID{
		entity.RoleBindingScopeTiDB: entity.ID(3),
		entity.RoleBindingScopeOrg:  entity.ID(1),
	})
	assert.Assert(t, err == nil)
	assert.Assert(t, match == true)
}

func TestPermissionSupport_isScopeResourceMatch_OrgTiDBNotMatched(t *testing.T) {
	id, db, err := docker_db.InitDockerGormDB(false)
	if err != nil {
		t.Fatal(err)
	}
	defer docker_db.ReleaseDockerDB(id)

	database.DBConn.DB = db

	err = db.AutoMigrate(&entity.ResourceRelation{})
	if err != nil {
		t.Fatal(err)
	}
	db.Save(&entity.ResourceRelation{
		ParentType:   entity.RoleBindingScopeOrg.String(),
		ParentID:     2,
		ResourceType: entity.RoleBindingScopeTiDB.String(),
		ResourceID:   3,
	})

	ctx := context.TODO()
	match, _, err := isScopeResourceMatch(ctx, map[entity.ScopeType]entity.ID{
		entity.RoleBindingScopeTiDB: entity.ID(1),
		entity.RoleBindingScopeOrg:  entity.ID(2),
	})
	assert.Assert(t, err == nil)
	assert.Assert(t, match == false)
}
