package usecase

import (
	"backend/pkg/permission/domain"
	"backend/pkg/permission/domain/entity"
	"backend/pkg/permission/domain/permission"
	"testing"

	"github.com/stretchr/testify/assert"
	"go.mongodb.org/mongo-driver/v2/bson"
)

func TestPermissionTree_Build(t *testing.T) {
	permissions := []*entity.Permission{
		{ID: bson.NewObjectID(), ParentID: bson.ObjectID{}, Name: "user", State: domain.RecordActive},
		{ID: bson.NewObjectID(), ParentID: bson.NewObjectID(), Name: "user.list", State: domain.RecordActive},
		{ID: bson.NewObjectID(), ParentID: bson.NewObjectID(), Name: "user.create", State: domain.RecordActive},
		{ID: bson.NewObjectID(), ParentID: bson.NewObjectID(), Name: "user.list.detail", State: domain.RecordActive},
	}

	// 設定正確的父子關係
	permissions[1].ParentID = permissions[0].ID
	permissions[2].ParentID = permissions[0].ID
	permissions[3].ParentID = permissions[1].ID

	tree := NewPermissionTree(permissions)

	// 檢查節點數量
	assert.Equal(t, 4, len(tree.nodes))

	// 檢查根節點
	assert.Equal(t, 1, len(tree.roots))
	assert.Equal(t, "user", tree.roots[0].Permission.Name)

	// 檢查子節點
	assert.Equal(t, 2, len(tree.roots[0].Children))

	// 檢查路徑
	node := tree.GetNodeByObjectID(permissions[3].ID)
	assert.NotNil(t, node)
	assert.Equal(t, 2, len(node.PathIDs))
}

func TestPermissionTree_ExpandPermissions(t *testing.T) {
	permissions := []*entity.Permission{
		{ID: bson.NewObjectID(), ParentID: bson.ObjectID{}, Name: "user", State: domain.RecordActive},
		{ID: bson.NewObjectID(), ParentID: bson.NewObjectID(), Name: "user.list", State: domain.RecordActive},
		{ID: bson.NewObjectID(), ParentID: bson.NewObjectID(), Name: "user.create", State: domain.RecordActive},
		{ID: bson.NewObjectID(), ParentID: bson.NewObjectID(), Name: "user.list.detail", State: domain.RecordActive},
	}

	// 設定正確的父子關係
	permissions[1].ParentID = permissions[0].ID
	permissions[2].ParentID = permissions[0].ID
	permissions[3].ParentID = permissions[1].ID

	tree := NewPermissionTree(permissions)

	input := permission.Permissions{
		"user.list.detail": permission.Open,
	}

	expanded, err := tree.ExpandPermissions(input)
	assert.NoError(t, err)

	// 應該包含自己和所有父節點
	assert.True(t, expanded.HasPermission("user"))
	assert.True(t, expanded.HasPermission("user.list"))
	assert.True(t, expanded.HasPermission("user.list.detail"))
	assert.False(t, expanded.HasPermission("user.create"))
}

func TestPermissionTree_GetPermissionIDs(t *testing.T) {
	permissions := []*entity.Permission{
		{ID: bson.NewObjectID(), ParentID: bson.ObjectID{}, Name: "user", State: domain.RecordActive},
		{ID: bson.NewObjectID(), ParentID: bson.NewObjectID(), Name: "user.list", State: domain.RecordActive},
		{ID: bson.NewObjectID(), ParentID: bson.NewObjectID(), Name: "user.create", State: domain.RecordActive},
	}

	// 設定正確的父子關係
	permissions[1].ParentID = permissions[0].ID
	permissions[2].ParentID = permissions[0].ID

	tree := NewPermissionTree(permissions)

	input := permission.Permissions{
		"user.list": permission.Open,
	}

	ids, err := tree.GetPermissionIDs(input)
	assert.NoError(t, err)

	// 應該包含 user.list 和 user
	assert.Contains(t, ids, permissions[0].ID)
	assert.Contains(t, ids, permissions[1].ID)
	assert.NotContains(t, ids, permissions[2].ID)
}

func TestPermissionTree_BuildPermissionsFromIDs(t *testing.T) {
	permissions := []*entity.Permission{
		{ID: bson.NewObjectID(), ParentID: bson.ObjectID{}, Name: "user", State: domain.RecordActive},
		{ID: bson.NewObjectID(), ParentID: bson.NewObjectID(), Name: "user.list", State: domain.RecordActive},
		{ID: bson.NewObjectID(), ParentID: bson.NewObjectID(), Name: "user.create", State: domain.RecordActive},
	}

	// 設定正確的父子關係
	permissions[1].ParentID = permissions[0].ID
	permissions[2].ParentID = permissions[0].ID

	tree := NewPermissionTree(permissions)

	perms := tree.BuildPermissionsFromIDs([]bson.ObjectID{permissions[1].ID})

	// 應該包含 user 和 user.list
	assert.True(t, perms.HasPermission("user"))
	assert.True(t, perms.HasPermission("user.list"))
	assert.False(t, perms.HasPermission("user.create"))
}

func TestPermissionTree_ParentNodeWithChildren(t *testing.T) {
	permissions := []*entity.Permission{
		{ID: bson.NewObjectID(), ParentID: bson.ObjectID{}, Name: "user", State: domain.RecordActive},
		{ID: bson.NewObjectID(), ParentID: bson.NewObjectID(), Name: "user.list", State: domain.RecordActive},
		{ID: bson.NewObjectID(), ParentID: bson.NewObjectID(), Name: "user.create", State: domain.RecordActive},
	}

	// 設定正確的父子關係
	permissions[1].ParentID = permissions[0].ID
	permissions[2].ParentID = permissions[0].ID

	tree := NewPermissionTree(permissions)

	// 只開啟父節點，沒有開啟子節點
	input := permission.Permissions{
		"user": permission.Open,
	}

	expanded, err := tree.ExpandPermissions(input)
	assert.NoError(t, err)

	// 父節點沒有子節點開啟時，不應該被展開
	assert.Equal(t, 0, len(expanded))
}

func TestPermissionTree_DetectCircularDependency(t *testing.T) {
	permissions := []*entity.Permission{
		{ID: bson.NewObjectID(), ParentID: bson.ObjectID{}, Name: "user", State: domain.RecordActive},
		{ID: bson.NewObjectID(), ParentID: bson.NewObjectID(), Name: "user.list", State: domain.RecordActive},
	}

	// 設定正確的父子關係
	permissions[1].ParentID = permissions[0].ID

	tree := NewPermissionTree(permissions)

	err := tree.DetectCircularDependency()
	assert.NoError(t, err)
}
