package serializationimp

import (
	"github.com/tech/sendico/pkg/merrors"
	"github.com/tech/sendico/pkg/model"
	"go.mongodb.org/mongo-driver/v2/bson"
)

// RoleSerializer implements CasbinSerializer for Role.
type RoleSerializer struct{}

// Serialize converts a Role object into a Casbin grouping policy.
func (s *RoleSerializer) Serialize(entity *model.Role) ([]any, error) {
	// Validate required fields
	if entity.AccountRef.IsZero() || entity.DescriptionRef.IsZero() || entity.OrganizationRef.IsZero() {
		return nil, merrors.InvalidArgument("role contains invalid object references")
	}

	return []any{
		entity.AccountRef.Hex(),      // Maps to g(_, _, _) accountRef
		entity.DescriptionRef.Hex(),  // Maps to g(_, _, _) roleRef
		entity.OrganizationRef.Hex(), // Maps to g(_, _, _) organizationRef
	}, nil
}

// Deserialize converts a Casbin grouping policy into a Role object.
func (s *RoleSerializer) Deserialize(policy []string) (*model.Role, error) {
	// Ensure the policy has exactly 3 fields
	if len(policy) != 3 {
		return nil, merrors.Internal("invalid grouping policy format")
	}

	// Parse accountRef
	accountRef, err := bson.ObjectIDFromHex(policy[0])
	if err != nil {
		return nil, merrors.InvalidArgument("invalid accountRef in grouping policy")
	}

	// Parse roleDescriptionRef (roleRef)
	roleDescriptionRef, err := bson.ObjectIDFromHex(policy[1])
	if err != nil {
		return nil, merrors.InvalidArgument("invalid roleRef in grouping policy")
	}

	// Parse organizationRef
	organizationRef, err := bson.ObjectIDFromHex(policy[2])
	if err != nil {
		return nil, merrors.InvalidArgument("invalid organizationRef in grouping policy")
	}

	// Return the constructed Role object
	return &model.Role{
		AccountRef:      accountRef,
		DescriptionRef:  roleDescriptionRef,
		OrganizationRef: organizationRef,
	}, nil
}
