package model

import (
	"github.com/tech/sendico/pkg/db/storable"
	"github.com/tech/sendico/pkg/mservice"
	"go.mongodb.org/mongo-driver/v2/bson"
)

// Action represents a permissible action on a resource.
type Action string

// Common actions for resources.
const (
	ActionCreate Action = "create" // Create a resource
	ActionRead   Action = "read"   // Read or view a resource
	ActionUpdate Action = "update" // Update or modify a resource
	ActionDelete Action = "delete" // Delete a resource
)

// Effect determines whether an action is allowed or denied.
type Effect string

const (
	EffectAllow Effect = "allow" // Permit the action
	EffectDeny  Effect = "deny"  // Deny the action
)

// RoleDescription provides metadata about a role.
type RoleDescription struct {
	storable.Base   `bson:",inline" json:",inline"` // Base fields for MongoDB documents
	Describable     `bson:",inline" json:",inline"` // Name and description fields
	OrganizationRef bson.ObjectID                   `bson:"organizationRef" json:"organizationRef"` // Organization associated with the role
}

// Collection specifies the MongoDB collection for RoleDescription.
func (*RoleDescription) Collection() string {
	return mservice.Roles
}

// Role represents a role assignment for an account within an organization.
type Role struct {
	AccountRef      bson.ObjectID `bson:"accountRef" json:"accountRef"`           // Account assigned to the role
	DescriptionRef  bson.ObjectID `bson:"descriptionRef" json:"descriptionRef"`   // Reference to the role's description
	OrganizationRef bson.ObjectID `bson:"organizationRef" json:"organizationRef"` // Organization where the role is applicable
}

// ActionEffect represents a combination of an action and its effect (allow/deny).
type ActionEffect struct {
	Action Action `bson:"action" json:"action"` // The action to perform (e.g., read, write)
	Effect Effect `bson:"effect" json:"effect"` // Whether the action is allowed or denied
}

// Policy defines access control rules for a role within an organization.
type Policy struct {
	OrganizationRef bson.ObjectID  `bson:"organizationRef" json:"organizationRef"`         // Organization associated with the policy
	DescriptionRef  bson.ObjectID  `bson:"descriptionRef" json:"descriptionRef"`           // Reference to the policy's metadata
	ObjectRef       *bson.ObjectID `bson:"objectRef,omitempty" json:"objectRef,omitempty"` // Target object (NilObjectID for all objects)
	Effect          ActionEffect   `bson:"effect" json:"effect"`                           // Action and effect for the policy
}

// RolePolicy defines access control rules for a role within an organization.
type RolePolicy struct {
	Policy             `bson:",inline" json:",inline"`
	RoleDescriptionRef bson.ObjectID `bson:"roleDescriptionRef" json:"roleDescriptionRef"` // Reference to the associated role
}

// PolicyDescription provides metadata for policies.
type PolicyDescription struct {
	storable.Base   `bson:",inline" json:",inline"` // Base fields for MongoDB documents
	Describable     `bson:",inline" json:",inline"` // Name and description fields
	ResourceTypes   *[]mservice.Type                `bson:"resourceTypes,omitempty" json:"resourceTypes,omitempty"`     // nil for custom policies, non-nil for built-in permissisons
	OrganizationRef *bson.ObjectID                  `bson:"organizationRef,omitempty" json:"organizationRef,omitempty"` // nil for built-in policies, non-nil for custom
}

// Collection specifies the MongoDB collection for PolicyDescription.
func (*PolicyDescription) Collection() string {
	return mservice.Policies
}

// Permission ties a policy to a specific account.
type Permission struct {
	RolePolicy `bson:",inline" json:",inline"` // Embedded policy definition
	AccountRef bson.ObjectID                   `bson:"accountRef" json:"accountRef"` // Account assigned the permission
}
