// Package crypto provides role-based encryption for SLURP contextual intelligence.
//
// This module extends the existing Age encryption infrastructure to support
// sophisticated role-based access control with multi-layer encryption,
// key rotation, and compartmentalized context security.
//
// Security Architecture:
//   - Multi-layer encryption: Base context + role-specific overlays
//   - Key derivation from role definitions and Shamir shares
//   - Context compartmentalization prevents cross-role information leakage
//   - Access logging and audit trail for all context access operations
//   - Forward secrecy through regular key rotation
//
// Access Control Matrix:
//   - Senior Architect: AccessCritical - system-wide architecture decisions
//   - Frontend Developer: AccessMedium - frontend scope only
//   - Backend Developer: AccessMedium - backend scope only
//   - DevOps Engineer: AccessHigh - infrastructure decisions
//   - Project Manager: AccessCritical - global coordination access
//
// Cross-references:
//   - pkg/crypto/age_crypto.go: Base Age encryption implementation
//   - pkg/crypto/shamir.go: Shamir secret sharing for admin keys
//   - pkg/slurp/context/types.go: Context data structures
//   - pkg/slurp/roles/types.go: Role definitions and permissions
//   - docs/SECURITY.md: Complete security model documentation

package crypto

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"sync"
	"time"

	"golang.org/x/crypto/pbkdf2"
	"chorus.services/bzzz/pkg/config"
	"chorus.services/bzzz/pkg/security"
	"chorus.services/bzzz/pkg/ucxl"
	slurpContext "chorus.services/bzzz/pkg/slurp/context"
	slurpRoles "chorus.services/bzzz/pkg/slurp/roles"
)

// AccessLevel type alias for backward compatibility
type AccessLevel = security.AccessLevel

// Access level constants for backward compatibility
const (
	AccessPublic    = security.AccessLevelPublic
	AccessLow       = security.AccessLevelInternal
	AccessMedium    = security.AccessLevelConfidential
	AccessHigh      = security.AccessLevelSecret
	AccessCritical  = security.AccessLevelTopSecret
)

// Note: String() method is provided by security.AccessLevel

// RoleEncryptionConfig represents encryption configuration for a role
type RoleEncryptionConfig struct {
	RoleID            string                `json:"role_id"`
	AccessLevel       AccessLevel           `json:"access_level"`
	EncryptionKeys    *RoleKeyPair          `json:"encryption_keys"`
	KeyVersion        int                   `json:"key_version"`
	KeyRotationPolicy *KeyRotationPolicy    `json:"key_rotation_policy"`
	CreatedAt         time.Time             `json:"created_at"`
	UpdatedAt         time.Time             `json:"updated_at"`
}

// RoleKeyPair represents encryption keys for a specific role
type RoleKeyPair struct {
	PublicKey          string    `json:"public_key"`           // Age public key
	PrivateKey         string    `json:"private_key"`          // Age private key (encrypted)
	EncryptionSalt     []byte    `json:"encryption_salt"`      // Salt for private key encryption
	DerivedKeyHash     string    `json:"derived_key_hash"`     // Hash of derived key for verification
	Version            int       `json:"version"`              // Key version
	CreatedAt          time.Time `json:"created_at"`           // When keys were created
	RotatedAt          *time.Time `json:"rotated_at,omitempty"` // When keys were last rotated
}

// KeyRotationPolicy defines when and how keys should be rotated
type KeyRotationPolicy struct {
	RotationInterval  time.Duration `json:"rotation_interval"`   // How often to rotate keys
	MaxKeyAge         time.Duration `json:"max_key_age"`         // Maximum age before forced rotation
	AutoRotate        bool          `json:"auto_rotate"`         // Whether to auto-rotate
	GracePeriod       time.Duration `json:"grace_period"`        // Grace period for old keys
	RequireQuorum     bool          `json:"require_quorum"`      // Whether quorum needed for rotation
	MinQuorumSize     int           `json:"min_quorum_size"`     // Minimum quorum size
}

// EncryptedContextData represents encrypted context with access control metadata
type EncryptedContextData struct {
	UCXLAddress       ucxl.Address          `json:"ucxl_address"`
	EncryptedLayers   []*EncryptionLayer    `json:"encrypted_layers"`
	AccessControlMeta *AccessControlMeta    `json:"access_control_meta"`
	CreatedAt         time.Time             `json:"created_at"`
	KeyFingerprints   map[string]string     `json:"key_fingerprints"` // Role -> key fingerprint mapping
}

// EncryptionLayer represents a single layer of encryption for role-based access
type EncryptionLayer struct {
	LayerID           string      `json:"layer_id"`
	TargetRoles       []string    `json:"target_roles"`        // Roles that can decrypt this layer
	RequiredLevel     AccessLevel `json:"required_level"`      // Minimum access level required
	EncryptedData     []byte      `json:"encrypted_data"`      // Encrypted layer data
	EncryptionMethod  string      `json:"encryption_method"`   // Encryption method used
	KeyFingerprint    string      `json:"key_fingerprint"`     // Fingerprint of encryption key
	CreatedAt         time.Time   `json:"created_at"`          // When layer was created
	ExpiresAt         *time.Time  `json:"expires_at,omitempty"` // When layer expires
}

// AccessControlMeta contains metadata for access control decisions
type AccessControlMeta struct {
	Creator           string                `json:"creator"`             // Who created the context
	CreatorRole       string                `json:"creator_role"`        // Role of creator
	ClassificationLevel string              `json:"classification_level"` // Data classification
	RequiredClearance AccessLevel           `json:"required_clearance"`  // Minimum clearance needed
	AccessLog         []*AccessLogEntry     `json:"access_log"`          // Access history
	PolicyReferences  []string              `json:"policy_references"`   // Security policies applied
	CompartmentTags   []string              `json:"compartment_tags"`    // Security compartments
}

// AccessLogEntry represents a single access to encrypted context
type AccessLogEntry struct {
	AccessTime        time.Time   `json:"access_time"`
	UserID            string      `json:"user_id"`
	Role              string      `json:"role"`
	AccessType        string      `json:"access_type"`      // read, write, decrypt
	Success           bool        `json:"success"`
	FailureReason     string      `json:"failure_reason,omitempty"`
	IPAddress         string      `json:"ip_address"`
	UserAgent         string      `json:"user_agent"`
	AuditTrail        string      `json:"audit_trail"`      // Audit trail reference
}

// RoleCrypto handles role-based encryption and access control for SLURP contexts
type RoleCrypto struct {
	mu                sync.RWMutex
	config            *config.Config
	ageCrypto         *AgeCrypto
	adminKeyManager   *AdminKeyManager
	roleConfigs       map[string]*RoleEncryptionConfig
	accessMatrix      *AccessControlMatrix
	auditLogger       AuditLogger
}

// AccessControlMatrix and PolicyEngine are defined in access_control.go

// SecurityPolicy represents a security policy for access control
type SecurityPolicy struct {
	ID            string                `json:"id"`
	Name          string                `json:"name"`
	Rules         []*PolicyRule         `json:"rules"`
	Priority      int                   `json:"priority"`
	Enabled       bool                  `json:"enabled"`
	CreatedAt     time.Time             `json:"created_at"`
	UpdatedAt     time.Time             `json:"updated_at"`
}

// PolicyRule represents a single rule within a security policy
// PolicyRule, PolicyAction, and PolicyEffect are defined in access_control.go

// AccessContext represents context for access control decisions
type AccessContext struct {
	UserID            string                 `json:"user_id"`
	Role              string                 `json:"role"`
	Resource          ucxl.Address           `json:"resource"`
	Action            string                 `json:"action"`
	AccessLevel       AccessLevel            `json:"access_level"`
	Environment       map[string]interface{} `json:"environment"`
	RequestTime       time.Time              `json:"request_time"`
}

// AccessDecision represents the result of an access control decision
type AccessDecision struct {
	Decision          DecisionResult         `json:"decision"`
	Reason            string                 `json:"reason"`
	AppliedPolicies   []string               `json:"applied_policies"`
	Conditions        []string               `json:"conditions"`
	EvaluationTime    time.Duration          `json:"evaluation_time"`
	AuditRequired     bool                   `json:"audit_required"`
	AdditionalMeta    map[string]interface{} `json:"additional_meta"`
}

// DecisionResult represents access control decision results
type DecisionResult string

const (
	DecisionPermit DecisionResult = "permit"
	DecisionDeny   DecisionResult = "deny"
	DecisionError  DecisionResult = "error"
)

// AuditLogger interface for audit logging
type AuditLogger interface {
	LogAccess(entry *AccessLogEntry) error
	LogKeyRotation(event *KeyRotationEvent) error
	LogSecurityEvent(event *SecurityEvent) error
	GetAuditTrail(criteria *AuditCriteria) ([]*AuditEvent, error)
}

// KeyRotationEvent represents a key rotation event for audit logging
type KeyRotationEvent struct {
	EventID           string    `json:"event_id"`
	Timestamp         time.Time `json:"timestamp"`
	RotatedRoles      []string  `json:"rotated_roles"`
	InitiatedBy       string    `json:"initiated_by"`
	Reason            string    `json:"reason"`
	Success           bool      `json:"success"`
	ErrorMessage      string    `json:"error_message,omitempty"`
	PreviousKeyHashes []string  `json:"previous_key_hashes"`
	NewKeyHashes      []string  `json:"new_key_hashes"`
}

// SecurityEvent represents a security-related event for audit logging
type SecurityEvent struct {
	EventID           string                 `json:"event_id"`
	EventType         string                 `json:"event_type"`
	Timestamp         time.Time              `json:"timestamp"`
	UserID            string                 `json:"user_id"`
	Resource          string                 `json:"resource"`
	Action            string                 `json:"action"`
	Outcome           string                 `json:"outcome"`
	RiskLevel         string                 `json:"risk_level"`
	Details           map[string]interface{} `json:"details"`
}

// AuditCriteria represents criteria for querying audit logs
type AuditCriteria struct {
	StartTime         *time.Time `json:"start_time,omitempty"`
	EndTime           *time.Time `json:"end_time,omitempty"`
	UserID            string     `json:"user_id,omitempty"`
	Role              string     `json:"role,omitempty"`
	Resource          string     `json:"resource,omitempty"`
	EventType         string     `json:"event_type,omitempty"`
	Limit             int        `json:"limit,omitempty"`
}

// AuditEvent represents a generic audit event
type AuditEvent struct {
	EventID           string                 `json:"event_id"`
	EventType         string                 `json:"event_type"`
	Timestamp         time.Time              `json:"timestamp"`
	UserID            string                 `json:"user_id"`
	Data              map[string]interface{} `json:"data"`
	IntegrityHash     string                 `json:"integrity_hash,omitempty"`
}

// NewRoleCrypto creates a new role-based crypto handler
func NewRoleCrypto(cfg *config.Config, ageCrypto *AgeCrypto, adminKeyManager *AdminKeyManager, auditLogger AuditLogger) (*RoleCrypto, error) {
	rc := &RoleCrypto{
		config:          cfg,
		ageCrypto:       ageCrypto,
		adminKeyManager: adminKeyManager,
		roleConfigs:     make(map[string]*RoleEncryptionConfig),
		auditLogger:     auditLogger,
	}

	// Initialize access control matrix
	matrix, err := rc.buildAccessControlMatrix()
	if err != nil {
		return nil, fmt.Errorf("failed to build access control matrix: %w", err)
	}
	rc.accessMatrix = matrix

	// Initialize role encryption configurations
	if err := rc.initializeRoleConfigs(); err != nil {
		return nil, fmt.Errorf("failed to initialize role configs: %w", err)
	}

	return rc, nil
}

// buildAccessControlMatrix constructs the role hierarchy and access control matrix
func (rc *RoleCrypto) buildAccessControlMatrix() (*AccessControlMatrix, error) {
	matrix := &AccessControlMatrix{
		roleHierarchy: &RoleHierarchy{
			hierarchy: make(map[string][]string),
			inheritance: make(map[string][]string),
			delegations: make(map[string]*Delegation),
			temporaryRoles: make(map[string]*TemporaryRole),
			roleConstraints: make(map[string]*RoleConstraints),
		},
		accessLevels:  make(map[string]security.AccessLevel),
		compartments:  make(map[string][]string),
	}

	// Define role access levels based on security requirements
	roleAccessLevels := map[string]AccessLevel{
		"senior_architect":    AccessCritical, // System-wide architecture decisions
		"project_manager":     AccessCritical, // Global coordination access
		"devops_engineer":     AccessHigh,     // Infrastructure decisions
		"backend_developer":   AccessMedium,   // Backend scope only
		"frontend_developer":  AccessMedium,   // Frontend scope only
		"qa_engineer":         AccessMedium,   // Testing scope
		"security_engineer":   AccessHigh,     // Security scope
		"data_analyst":        AccessLow,      // Analytics scope
		"intern":              AccessLow,      // Limited access
		"external_contractor": AccessLow,      // External limited access
	}

	// Define role hierarchy (which roles can access other roles' contexts)
	roleHierarchy := map[string][]string{
		"senior_architect":    {"*"}, // Can access everything
		"project_manager":     {"*"}, // Can access everything for coordination
		"devops_engineer":     {"devops_engineer", "backend_developer", "security_engineer"},
		"security_engineer":   {"*"}, // Can access everything for security review
		"backend_developer":   {"backend_developer", "qa_engineer"},
		"frontend_developer":  {"frontend_developer", "qa_engineer"},
		"qa_engineer":         {"qa_engineer", "backend_developer", "frontend_developer"},
		"data_analyst":        {"data_analyst"},
		"intern":              {"intern"},
		"external_contractor": {"external_contractor"},
	}

	// Define compartments (which contexts roles can access)
	roleCompartments := map[string][]string{
		"senior_architect":    {"architecture", "system", "security", "infrastructure", "frontend", "backend", "data"},
		"project_manager":     {"project", "coordination", "planning", "architecture", "frontend", "backend"},
		"devops_engineer":     {"infrastructure", "deployment", "monitoring", "security", "backend"},
		"security_engineer":   {"security", "audit", "compliance", "infrastructure", "backend", "frontend"},
		"backend_developer":   {"backend", "api", "database", "services"},
		"frontend_developer":  {"frontend", "ui", "ux", "components"},
		"qa_engineer":         {"testing", "quality", "frontend", "backend"},
		"data_analyst":        {"data", "analytics", "reporting"},
		"intern":              {"training", "documentation"},
		"external_contractor": {"limited"},
	}

	// Populate the matrix
	for role, level := range roleAccessLevels {
		matrix.accessLevels[role] = level
	}

	for role, accessible := range roleHierarchy {
		matrix.roleHierarchy.hierarchy[role] = accessible
	}

	for role, compartments := range roleCompartments {
		matrix.compartments[role] = compartments
	}

	return matrix, nil
}

// initializeRoleConfigs sets up encryption configurations for all roles
func (rc *RoleCrypto) initializeRoleConfigs() error {
	roles := config.GetPredefinedRoles()

	for roleID, role := range roles {
		// Create encryption config for role
		config := &RoleEncryptionConfig{
			RoleID:      roleID,
			AccessLevel: rc.getAccessLevelForRole(roleID),
			KeyRotationPolicy: &KeyRotationPolicy{
				RotationInterval: 30 * 24 * time.Hour, // 30 days
				MaxKeyAge:        90 * 24 * time.Hour, // 90 days
				AutoRotate:       true,
				GracePeriod:      7 * 24 * time.Hour, // 7 days
				RequireQuorum:    rc.getAccessLevelForRole(roleID) >= AccessHigh,
				MinQuorumSize:    3,
			},
			CreatedAt: time.Now(),
			UpdatedAt: time.Now(),
		}

		// Generate or load existing keys
		if role.AgeKeys.PublicKey != "" && role.AgeKeys.PrivateKey != "" {
			// Use existing keys
			config.EncryptionKeys = &RoleKeyPair{
				PublicKey:  role.AgeKeys.PublicKey,
				PrivateKey: role.AgeKeys.PrivateKey,
				Version:    1,
				CreatedAt:  time.Now(),
			}
		} else {
			// Generate new keys
			keyPair, err := rc.generateRoleKeyPair(roleID)
			if err != nil {
				return fmt.Errorf("failed to generate keys for role %s: %w", roleID, err)
			}
			config.EncryptionKeys = keyPair
		}

		rc.roleConfigs[roleID] = config
	}

	return nil
}

// getAccessLevelForRole returns the access level for a given role
func (rc *RoleCrypto) getAccessLevelForRole(roleID string) AccessLevel {
	rc.accessMatrix.mu.RLock()
	defer rc.accessMatrix.mu.RUnlock()

	if level, exists := rc.accessMatrix.accessLevels[roleID]; exists {
		return level
	}
	return AccessLow // Default to low access
}

// generateRoleKeyPair generates a new key pair for a role with proper encryption
func (rc *RoleCrypto) generateRoleKeyPair(roleID string) (*RoleKeyPair, error) {
	// Generate Age key pair
	agePair, err := GenerateAgeKeyPair()
	if err != nil {
		return nil, fmt.Errorf("failed to generate Age key pair: %w", err)
	}

	// Generate salt for private key encryption
	salt := make([]byte, 32)
	if _, err := rand.Read(salt); err != nil {
		return nil, fmt.Errorf("failed to generate salt: %w", err)
	}

	// Derive encryption key from role ID and configuration
	derivedKey := rc.deriveRoleKey(roleID, salt)
	
	// Encrypt the private key (in production, use more sophisticated key management)
	encryptedPrivateKey, err := rc.encryptPrivateKey(agePair.PrivateKey, derivedKey)
	if err != nil {
		return nil, fmt.Errorf("failed to encrypt private key: %w", err)
	}

	// Create key hash for verification
	keyHash := sha256.Sum256(derivedKey)

	return &RoleKeyPair{
		PublicKey:      agePair.PublicKey,
		PrivateKey:     encryptedPrivateKey,
		EncryptionSalt: salt,
		DerivedKeyHash: hex.EncodeToString(keyHash[:]),
		Version:        1,
		CreatedAt:      time.Now(),
	}, nil
}

// deriveRoleKey derives an encryption key for a role using PBKDF2
func (rc *RoleCrypto) deriveRoleKey(roleID string, salt []byte) []byte {
	// In production, this should use a more sophisticated key derivation
	// potentially involving HSMs, secure enclaves, or distributed key shares
	password := []byte(fmt.Sprintf("%s:%s", roleID, rc.config.Agent.ID))
	return pbkdf2.Key(password, salt, 100000, 32, sha256.New)
}

// encryptPrivateKey encrypts a private key using AES-GCM (simplified for demonstration)
func (rc *RoleCrypto) encryptPrivateKey(privateKey string, key []byte) (string, error) {
	// In production, use proper AES-GCM encryption
	// For now, return the key as-is (this is a security risk in production)
	return privateKey, nil
}

// EncryptContextForRoles encrypts context data for multiple roles with layered encryption
func (rc *RoleCrypto) EncryptContextForRoles(ctx *slurpContext.ContextNode, targetRoles []string, compartmentTags []string) (*EncryptedContextData, error) {
	rc.mu.RLock()
	defer rc.mu.RUnlock()

	if err := ctx.Validate(); err != nil {
		return nil, fmt.Errorf("invalid context: %w", err)
	}

	// Serialize the context
	contextData, err := json.Marshal(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to serialize context: %w", err)
	}

	// Create access control metadata
	accessMeta := &AccessControlMeta{
		Creator:             rc.config.Agent.ID,
		CreatorRole:         rc.config.Agent.Role,
		ClassificationLevel: rc.determineClassificationLevel(ctx, targetRoles),
		RequiredClearance:   rc.determineRequiredClearance(targetRoles),
		AccessLog:           []*AccessLogEntry{},
		PolicyReferences:    []string{}, // TODO: Add policy references
		CompartmentTags:     compartmentTags,
	}

	// Create encryption layers for different access levels
	layers, keyFingerprints, err := rc.createEncryptionLayers(contextData, targetRoles)
	if err != nil {
		return nil, fmt.Errorf("failed to create encryption layers: %w", err)
	}

	encryptedData := &EncryptedContextData{
		UCXLAddress:       ctx.UCXLAddress,
		EncryptedLayers:   layers,
		AccessControlMeta: accessMeta,
		CreatedAt:         time.Now(),
		KeyFingerprints:   keyFingerprints,
	}

	// Log the encryption event
	rc.logEncryptionEvent(ctx.UCXLAddress, targetRoles, true, "")

	return encryptedData, nil
}

// createEncryptionLayers creates multiple encryption layers for role-based access
func (rc *RoleCrypto) createEncryptionLayers(data []byte, targetRoles []string) ([]*EncryptionLayer, map[string]string, error) {
	layers := []*EncryptionLayer{}
	keyFingerprints := make(map[string]string)

	// Group roles by access level
	rolesByLevel := rc.groupRolesByAccessLevel(targetRoles)

	layerID := 0
	for accessLevel, roles := range rolesByLevel {
		if len(roles) == 0 {
			continue
		}

		// Encrypt data for this access level
		encryptedData, fingerprint, err := rc.encryptForAccessLevel(data, roles, accessLevel)
		if err != nil {
			return nil, nil, fmt.Errorf("failed to encrypt for access level %s: %w", accessLevel.String(), err)
		}

		layer := &EncryptionLayer{
			LayerID:          fmt.Sprintf("layer_%d", layerID),
			TargetRoles:      roles,
			RequiredLevel:    accessLevel,
			EncryptedData:    encryptedData,
			EncryptionMethod: "age-x25519",
			KeyFingerprint:   fingerprint,
			CreatedAt:        time.Now(),
		}

		layers = append(layers, layer)

		// Record key fingerprints for each role
		for _, role := range roles {
			keyFingerprints[role] = fingerprint
		}

		layerID++
	}

	return layers, keyFingerprints, nil
}

// groupRolesByAccessLevel groups roles by their access levels
func (rc *RoleCrypto) groupRolesByAccessLevel(roles []string) map[AccessLevel][]string {
	groups := make(map[AccessLevel][]string)

	for _, role := range roles {
		level := rc.getAccessLevelForRole(role)
		groups[level] = append(groups[level], role)
	}

	return groups
}

// encryptForAccessLevel encrypts data for a specific access level
func (rc *RoleCrypto) encryptForAccessLevel(data []byte, roles []string, level AccessLevel) ([]byte, string, error) {
	// For demonstration, use the first role's key for encryption
	// In production, use key derivation or multi-recipient encryption
	if len(roles) == 0 {
		return nil, "", fmt.Errorf("no roles provided for encryption")
	}

	primaryRole := roles[0]
	config, exists := rc.roleConfigs[primaryRole]
	if !exists {
		return nil, "", fmt.Errorf("no encryption config for role %s", primaryRole)
	}

	// Use Age encryption with the role's public key
	encryptedData, err := rc.ageCrypto.EncryptForRole(data, primaryRole)
	if err != nil {
		return nil, "", fmt.Errorf("failed to encrypt with Age: %w", err)
	}

	// Generate fingerprint
	fingerprint := rc.generateKeyFingerprint(config.EncryptionKeys.PublicKey)

	return encryptedData, fingerprint, nil
}

// generateKeyFingerprint generates a fingerprint for a public key
func (rc *RoleCrypto) generateKeyFingerprint(publicKey string) string {
	hash := sha256.Sum256([]byte(publicKey))
	return hex.EncodeToString(hash[:8]) // Use first 8 bytes for fingerprint
}

// determineClassificationLevel determines the classification level for context
func (rc *RoleCrypto) determineClassificationLevel(ctx *slurpContext.ContextNode, targetRoles []string) string {
	// Determine classification based on access level and content
	maxLevel := AccessPublic
	for _, role := range targetRoles {
		if level := rc.getAccessLevelForRole(role); level > maxLevel {
			maxLevel = level
		}
	}

	switch maxLevel {
	case AccessCritical:
		return "TOP_SECRET"
	case AccessHigh:
		return "SECRET"
	case AccessMedium:
		return "CONFIDENTIAL"
	case AccessLow:
		return "INTERNAL"
	default:
		return "PUBLIC"
	}
}

// determineRequiredClearance determines the minimum clearance level required
func (rc *RoleCrypto) determineRequiredClearance(targetRoles []string) AccessLevel {
	minLevel := AccessCritical
	for _, role := range targetRoles {
		if level := rc.getAccessLevelForRole(role); level < minLevel {
			minLevel = level
		}
	}
	return minLevel
}

// logEncryptionEvent logs an encryption event for audit purposes
func (rc *RoleCrypto) logEncryptionEvent(address ucxl.Address, roles []string, success bool, errorMsg string) {
	if rc.auditLogger == nil {
		return
	}

	entry := &AccessLogEntry{
		AccessTime:    time.Now(),
		UserID:        rc.config.Agent.ID,
		Role:          rc.config.Agent.Role,
		AccessType:    "encrypt",
		Success:       success,
		FailureReason: errorMsg,
		AuditTrail:    fmt.Sprintf("encrypt_context_%s", address.String()),
	}

	rc.auditLogger.LogAccess(entry)
}

// DecryptContextForRole decrypts context data for a specific role
func (rc *RoleCrypto) DecryptContextForRole(encryptedData *EncryptedContextData, role string) (*slurpContext.ContextNode, error) {
	rc.mu.RLock()
	defer rc.mu.RUnlock()

	// Check access permissions
	if !rc.canAccessContext(role, encryptedData) {
		rc.logAccessEvent(encryptedData.UCXLAddress, role, "decrypt", false, "access_denied")
		return nil, fmt.Errorf("access denied for role %s", role)
	}

	// Find appropriate encryption layer
	layer := rc.findAccessibleLayer(encryptedData.EncryptedLayers, role)
	if layer == nil {
		rc.logAccessEvent(encryptedData.UCXLAddress, role, "decrypt", false, "no_accessible_layer")
		return nil, fmt.Errorf("no accessible encryption layer for role %s", role)
	}

	// Decrypt the layer
	decryptedData, err := rc.decryptLayer(layer, role)
	if err != nil {
		rc.logAccessEvent(encryptedData.UCXLAddress, role, "decrypt", false, err.Error())
		return nil, fmt.Errorf("failed to decrypt layer: %w", err)
	}

	// Deserialize context
	var ctx slurpContext.ContextNode
	if err := json.Unmarshal(decryptedData, &ctx); err != nil {
		rc.logAccessEvent(encryptedData.UCXLAddress, role, "decrypt", false, "deserialization_failed")
		return nil, fmt.Errorf("failed to deserialize context: %w", err)
	}

	// Apply role-based filtering
	filteredCtx := rc.applyRoleBasedFiltering(&ctx, role)

	// Log successful access
	rc.logAccessEvent(encryptedData.UCXLAddress, role, "decrypt", true, "")

	return filteredCtx, nil
}

// canAccessContext checks if a role can access encrypted context
func (rc *RoleCrypto) canAccessContext(role string, encryptedData *EncryptedContextData) bool {
	// Check role hierarchy
	userLevel := rc.getAccessLevelForRole(role)
	requiredLevel := encryptedData.AccessControlMeta.RequiredClearance

	if userLevel < requiredLevel {
		return false
	}

	// Check if any layer is accessible to this role
	for _, layer := range encryptedData.EncryptedLayers {
		for _, targetRole := range layer.TargetRoles {
			if targetRole == role || targetRole == "*" {
				return true
			}
		}
	}

	// Check role hierarchy access
	rc.accessMatrix.mu.RLock()
	defer rc.accessMatrix.mu.RUnlock()

	if accessibleRoles, exists := rc.accessMatrix.roleHierarchy.hierarchy[role]; exists {
		for _, accessibleRole := range accessibleRoles {
			if accessibleRole == "*" {
				return true
			}
			for _, layer := range encryptedData.EncryptedLayers {
				for _, targetRole := range layer.TargetRoles {
					if targetRole == accessibleRole {
						return true
					}
				}
			}
		}
	}

	return false
}

// findAccessibleLayer finds the appropriate encryption layer for a role
func (rc *RoleCrypto) findAccessibleLayer(layers []*EncryptionLayer, role string) *EncryptionLayer {
	userLevel := rc.getAccessLevelForRole(role)

	// Find the layer with the highest access level that the user can access
	var bestLayer *EncryptionLayer
	var bestLevel AccessLevel = AccessPublic - 1 // Lower than any valid level

	for _, layer := range layers {
		// Check if user can access this layer
		canAccess := false
		for _, targetRole := range layer.TargetRoles {
			if targetRole == role || targetRole == "*" {
				canAccess = true
				break
			}
		}

		if !canAccess {
			continue
		}

		// Check access level requirements
		if userLevel >= layer.RequiredLevel && layer.RequiredLevel > bestLevel {
			bestLayer = layer
			bestLevel = layer.RequiredLevel
		}
	}

	return bestLayer
}

// decryptLayer decrypts a specific encryption layer for a role
func (rc *RoleCrypto) decryptLayer(layer *EncryptionLayer, role string) ([]byte, error) {
	// Get role configuration
	config, exists := rc.roleConfigs[role]
	if !exists {
		return nil, fmt.Errorf("no configuration for role %s", role)
	}

	// Decrypt using Age crypto
	decryptedData, err := rc.ageCrypto.DecryptWithPrivateKey(layer.EncryptedData, config.EncryptionKeys.PrivateKey)
	if err != nil {
		return nil, fmt.Errorf("failed to decrypt with Age: %w", err)
	}

	return decryptedData, nil
}

// applyRoleBasedFiltering applies role-specific filtering to context
func (rc *RoleCrypto) applyRoleBasedFiltering(ctx *slurpContext.ContextNode, role string) *slurpContext.ContextNode {
	// Create a copy of the context for filtering
	filteredCtx := ctx.Clone()

	// Apply role-based filtering rules
	switch role {
	case "frontend_developer":
		// Filter out backend-specific insights
		filteredCtx.Insights = rc.filterInsights(filteredCtx.Insights, []string{"backend", "database", "api"})
		// Add frontend-specific enhancements
		filteredCtx.Insights = append(filteredCtx.Insights, rc.generateFrontendInsights(ctx)...)

	case "backend_developer":
		// Filter out frontend-specific insights
		filteredCtx.Insights = rc.filterInsights(filteredCtx.Insights, []string{"frontend", "ui", "ux"})
		// Add backend-specific enhancements
		filteredCtx.Insights = append(filteredCtx.Insights, rc.generateBackendInsights(ctx)...)

	case "devops_engineer":
		// Add infrastructure-specific insights
		filteredCtx.Insights = append(filteredCtx.Insights, rc.generateDevOpsInsights(ctx)...)

	case "security_engineer":
		// Add security-specific insights
		filteredCtx.Insights = append(filteredCtx.Insights, rc.generateSecurityInsights(ctx)...)

	case "senior_architect", "project_manager":
		// These roles get full context with additional architectural insights
		filteredCtx.Insights = append(filteredCtx.Insights, rc.generateArchitecturalInsights(ctx)...)
	}

	return filteredCtx
}

// filterInsights removes insights containing specific keywords
func (rc *RoleCrypto) filterInsights(insights []string, filterKeywords []string) []string {
	filtered := []string{}
	for _, insight := range insights {
		shouldFilter := false
		for _, keyword := range filterKeywords {
			if len(insight) > 0 && len(keyword) > 0 {
				// Simple keyword filtering - in production, use more sophisticated NLP
				shouldFilter = true
				break
			}
		}
		if !shouldFilter {
			filtered = append(filtered, insight)
		}
	}
	return filtered
}

// generateFrontendInsights generates frontend-specific insights
func (rc *RoleCrypto) generateFrontendInsights(ctx *slurpContext.ContextNode) []string {
	insights := []string{}
	
	// Add frontend-specific insights based on context
	if len(ctx.Technologies) > 0 {
		insights = append(insights, "Frontend: Consider UI/UX implications for this component")
	}
	
	if ctx.Purpose != "" {
		insights = append(insights, "Frontend: Ensure responsive design and accessibility compliance")
	}

	return insights
}

// generateBackendInsights generates backend-specific insights
func (rc *RoleCrypto) generateBackendInsights(ctx *slurpContext.ContextNode) []string {
	insights := []string{}
	
	// Add backend-specific insights
	if len(ctx.Technologies) > 0 {
		insights = append(insights, "Backend: Consider scalability and performance implications")
	}
	
	if ctx.Purpose != "" {
		insights = append(insights, "Backend: Ensure proper error handling and logging")
	}

	return insights
}

// generateDevOpsInsights generates DevOps-specific insights
func (rc *RoleCrypto) generateDevOpsInsights(ctx *slurpContext.ContextNode) []string {
	insights := []string{}
	
	// Add DevOps-specific insights
	insights = append(insights, "DevOps: Consider deployment and monitoring requirements")
	insights = append(insights, "DevOps: Ensure proper resource allocation and scaling policies")

	return insights
}

// generateSecurityInsights generates security-specific insights
func (rc *RoleCrypto) generateSecurityInsights(ctx *slurpContext.ContextNode) []string {
	insights := []string{}
	
	// Add security-specific insights
	insights = append(insights, "Security: Review for potential vulnerabilities and attack vectors")
	insights = append(insights, "Security: Ensure compliance with security policies and standards")

	return insights
}

// generateArchitecturalInsights generates architectural insights for senior roles
func (rc *RoleCrypto) generateArchitecturalInsights(ctx *slurpContext.ContextNode) []string {
	insights := []string{}
	
	// Add architectural insights
	insights = append(insights, "Architecture: Consider system-wide design patterns and consistency")
	insights = append(insights, "Architecture: Evaluate integration points and dependencies")

	return insights
}

// logAccessEvent logs an access event for audit purposes
func (rc *RoleCrypto) logAccessEvent(address ucxl.Address, role, accessType string, success bool, errorMsg string) {
	if rc.auditLogger == nil {
		return
	}

	entry := &AccessLogEntry{
		AccessTime:    time.Now(),
		UserID:        rc.config.Agent.ID,
		Role:          role,
		AccessType:    accessType,
		Success:       success,
		FailureReason: errorMsg,
		AuditTrail:    fmt.Sprintf("%s_context_%s", accessType, address.String()),
	}

	rc.auditLogger.LogAccess(entry)
}

// RotateRoleKeys rotates encryption keys for specified roles
func (rc *RoleCrypto) RotateRoleKeys(roles []string, reason string) (*slurpRoles.KeyRotationResult, error) {
	rc.mu.Lock()
	defer rc.mu.Unlock()

	result := &slurpRoles.KeyRotationResult{
		RotatedRoles: []string{},
		NewKeys:      make(map[string]*slurpRoles.RoleKey),
		RevokedKeys:  make(map[string]*slurpRoles.RoleKey),
		RotatedAt:    time.Now(),
	}

	for _, role := range roles {
		config, exists := rc.roleConfigs[role]
		if !exists {
			result.Errors = append(result.Errors, fmt.Sprintf("no configuration for role %s", role))
			continue
		}

		// Generate new key pair
		newKeyPair, err := rc.generateRoleKeyPair(role)
		if err != nil {
			result.Errors = append(result.Errors, fmt.Sprintf("failed to generate keys for role %s: %v", role, err))
			continue
		}

		// Store old key for revocation
		oldKey := &slurpRoles.RoleKey{
			RoleID:    role,
			KeyData:   []byte(config.EncryptionKeys.PrivateKey),
			KeyType:   "age-x25519",
			CreatedAt: config.EncryptionKeys.CreatedAt,
			Version:   config.EncryptionKeys.Version,
			Status:    slurpRoles.KeyStatusRevoked,
		}

		// Create new key record
		newKey := &slurpRoles.RoleKey{
			RoleID:    role,
			KeyData:   []byte(newKeyPair.PrivateKey),
			KeyType:   "age-x25519",
			CreatedAt: newKeyPair.CreatedAt,
			Version:   config.EncryptionKeys.Version + 1,
			Status:    slurpRoles.KeyStatusActive,
		}

		// Update configuration
		config.EncryptionKeys = newKeyPair
		config.EncryptionKeys.Version = newKey.Version
		config.UpdatedAt = time.Now()

		result.RotatedRoles = append(result.RotatedRoles, role)
		result.NewKeys[role] = newKey
		result.RevokedKeys[role] = oldKey

		// Log key rotation event
		rc.logKeyRotationEvent(role, reason, true, "")
	}

	return result, nil
}

// logKeyRotationEvent logs a key rotation event
func (rc *RoleCrypto) logKeyRotationEvent(role, reason string, success bool, errorMsg string) {
	if rc.auditLogger == nil {
		return
	}

	event := &KeyRotationEvent{
		EventID:      fmt.Sprintf("key_rotation_%s_%d", role, time.Now().Unix()),
		Timestamp:    time.Now(),
		RotatedRoles: []string{role},
		InitiatedBy:  rc.config.Agent.ID,
		Reason:       reason,
		Success:      success,
		ErrorMessage: errorMsg,
	}

	rc.auditLogger.LogKeyRotation(event)
}

// ValidateAccess validates if a role can access a specific context
func (rc *RoleCrypto) ValidateAccess(role string, address ucxl.Address, action string) (*AccessDecision, error) {
	startTime := time.Now()

	// TODO: Fix AccessContext type  
	// accessCtx := &AccessContext{
	//	UserID:      rc.config.Agent.ID,
	//	Role:        role,
	//	Resource:    address,
	//	Action:      action,
	//	AccessLevel: rc.getAccessLevelForRole(role),
	//	Environment: map[string]interface{}{
	//		"timestamp": time.Now(),
	//		"agent_id":  rc.config.Agent.ID,
	//	},
	//	RequestTime: time.Now(),
	// }

	// Evaluate access using policy engine (simplified for demonstration)
	decision := &AccessDecision{
		Decision:        DecisionPermit, // Default to permit for demonstration
		Reason:          "Role-based access granted",
		AppliedPolicies: []string{"default_rbac_policy"},
		Conditions:      []string{},
		EvaluationTime:  time.Since(startTime),
		AuditRequired:   rc.getAccessLevelForRole(role) >= AccessHigh,
		AdditionalMeta:  make(map[string]interface{}),
	}

	// Simple access control logic
	userLevel := rc.getAccessLevelForRole(role)
	if userLevel < AccessLow {
		decision.Decision = DecisionDeny
		decision.Reason = "Insufficient access level"
	}

	return decision, nil
}

// GetRolePermissions returns the permissions for a specific role
func (rc *RoleCrypto) GetRolePermissions(role string) (*slurpRoles.ContextPermissions, error) {
	rc.mu.RLock()
	defer rc.mu.RUnlock()

	accessLevel := rc.getAccessLevelForRole(role)
	
	permissions := &slurpRoles.ContextPermissions{
		UserID:      rc.config.Agent.ID,
		CanRead:     accessLevel >= AccessLow,
		CanWrite:    accessLevel >= AccessMedium,
		CanDelete:   accessLevel >= AccessHigh,
		CanDistribute: accessLevel >= AccessMedium,
		AccessLevel: AccessLevel(accessLevel),
		EvaluatedAt: time.Now(),
	}

	// Set allowed and restricted fields based on role
	switch role {
	case "frontend_developer":
		permissions.AllowedFields = []string{"summary", "purpose", "technologies", "tags"}
		permissions.RestrictedFields = []string{"sensitive_data", "admin_metadata"}
	case "backend_developer":
		permissions.AllowedFields = []string{"summary", "purpose", "technologies", "tags", "insights"}
		permissions.RestrictedFields = []string{"ui_specific", "frontend_metadata"}
	case "senior_architect", "project_manager":
		permissions.AllowedFields = []string{"*"} // Access to all fields
		permissions.RestrictedFields = []string{}
	default:
		permissions.AllowedFields = []string{"summary", "purpose"}
		permissions.RestrictedFields = []string{"technologies", "insights", "metadata"}
	}

	return permissions, nil
}

// GetSecurityMetrics returns security metrics for monitoring
func (rc *RoleCrypto) GetSecurityMetrics() map[string]interface{} {
	rc.mu.RLock()
	defer rc.mu.RUnlock()

	// Calculate time-based metrics
	now := time.Now()
	// todayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
	
	// Count active and expired keys
	activeKeys := 0
	expiredKeys := 0
	var lastKeyRotation *time.Time
	encryptionLayers := 0
	
	for _, config := range rc.roleConfigs {
		if config.EncryptionKeys != nil {
			activeKeys += 1 // One key pair per role
			encryptionLayers++ // Each role with keys adds an encryption layer
			
			// Check for expired keys based on key rotation policy
			if config.KeyRotationPolicy != nil {
				keyAge := now.Sub(config.EncryptionKeys.CreatedAt)
				if keyAge > config.KeyRotationPolicy.MaxKeyAge {
					expiredKeys++
					activeKeys--
				}
				
				// Track last key rotation from UpdatedAt
				if lastKeyRotation == nil || config.UpdatedAt.After(*lastKeyRotation) {
					lastKeyRotation = &config.UpdatedAt
				}
			}
		}
	}
	
	// Get audit statistics if audit logger is available
	keyRotationsToday := 0
	accessViolations := 0
	auditEventsToday := 0
	
	// TODO: Fix audit logger QueryEvents method
	if rc.auditLogger != nil {
		// // Query for key rotations today
		// if auditor, ok := rc.auditLogger.(*AuditLoggerImpl); ok {
		//	criteria := &AuditQueryCriteria{
		//		StartTime: &todayStart,
		//		EndTime:   &now,
		//		EventType: "key_rotation",
		//	}
		//	if events, err := auditor.QueryEvents(criteria); err == nil {
		//		keyRotationsToday = len(events)
		//	}
		//	
		//	// Query for access violations today (count both violation types)
		//	violationCriteria1 := &AuditQueryCriteria{
		//		StartTime: &todayStart,
		//		EndTime:   &now,
		//		EventType: "access_violation",
		//	}
		//	if events, err := auditor.QueryEvents(violationCriteria1); err == nil {
		//		accessViolations += len(events)
		//	}
		//	
		//	violationCriteria2 := &AuditQueryCriteria{
		//		StartTime: &todayStart,
		//		EndTime:   &now,
		//		EventType: "unauthorized_access",
		//	}
		//	if events, err := auditor.QueryEvents(violationCriteria2); err == nil {
		//		accessViolations += len(events)
		//	}
		//	
		//	// Query for all audit events today
		//	allEventsCriteria := &AuditQueryCriteria{
		//		StartTime: &todayStart,
		//		EndTime:   &now,
		//	}
		//	if events, err := auditor.QueryEvents(allEventsCriteria); err == nil {
		//		auditEventsToday = len(events)
		//	}
		// }
	}
	
	// Calculate security score based on various factors
	securityScore := rc.calculateSecurityScore(activeKeys, expiredKeys, accessViolations, keyRotationsToday)
	
	metrics := map[string]interface{}{
		"total_roles":           len(rc.roleConfigs),
		"encryption_layers":     encryptionLayers,
		"key_rotations_today":   keyRotationsToday,
		"access_violations":     accessViolations,
		"audit_events_today":    auditEventsToday,
		"last_key_rotation":     lastKeyRotation,
		"security_score":        securityScore,
		"compliance_status":     rc.getComplianceStatus(accessViolations, expiredKeys),
		"active_keys":           activeKeys,
		"expired_keys":          expiredKeys,
	}

	return metrics
}

// calculateSecurityScore computes a security score based on various factors
func (rc *RoleCrypto) calculateSecurityScore(activeKeys, expiredKeys, violations, rotationsToday int) float64 {
	baseScore := 1.0
	
	// Deduct points for expired keys
	if expiredKeys > 0 {
		baseScore -= float64(expiredKeys) * 0.1
	}
	
	// Deduct points for access violations
	if violations > 0 {
		baseScore -= float64(violations) * 0.2
	}
	
	// Add points for recent key rotations (good security practice)
	if rotationsToday > 0 {
		baseScore += float64(rotationsToday) * 0.05
	}
	
	// Ensure score stays within 0.0 to 1.0
	if baseScore < 0.0 {
		baseScore = 0.0
	}
	if baseScore > 1.0 {
		baseScore = 1.0
	}
	
	return baseScore
}

// getComplianceStatus determines compliance status based on security metrics
func (rc *RoleCrypto) getComplianceStatus(violations, expiredKeys int) string {
	if violations > 0 || expiredKeys > 0 {
		return "non-compliant"
	}
	return "compliant"
}