package pubsub

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"
	"sync"
	"time"

	"github.com/libp2p/go-libp2p/core/host"
	"github.com/libp2p/go-libp2p/core/peer"
	pubsub "github.com/libp2p/go-libp2p-pubsub"
)

// PubSub handles publish/subscribe messaging for Bzzz coordination and HMMM meta-discussion
type PubSub struct {
	ps     *pubsub.PubSub
	host   host.Host
	ctx    context.Context
	cancel context.CancelFunc
	
	// Topic subscriptions
	bzzzTopic     *pubsub.Topic
	hmmmTopic     *pubsub.Topic
	contextTopic  *pubsub.Topic
	
	// Message subscriptions
	bzzzSub     *pubsub.Subscription
	hmmmSub       *pubsub.Subscription
	contextSub  *pubsub.Subscription
	
	// Dynamic topic management
	dynamicTopics    map[string]*pubsub.Topic
	dynamicTopicsMux sync.RWMutex
	dynamicSubs      map[string]*pubsub.Subscription
	dynamicSubsMux   sync.RWMutex

	// Configuration
	bzzzTopicName     string
	hmmmTopicName     string
	contextTopicName  string

	// External message handler for HMMM messages
	HmmmMessageHandler     func(msg Message, from peer.ID)
	
	// External message handler for Context Feedback messages
	ContextFeedbackHandler func(msg Message, from peer.ID)
	
	// Hypercore-style logging
	hypercoreLog HypercoreLogger
}

// HypercoreLogger interface for dependency injection
type HypercoreLogger interface {
	AppendString(logType string, data map[string]interface{}) error
	GetStats() map[string]interface{}
}

// MessageType represents different types of messages
type MessageType string

const (
	// Bzzz coordination messages
	TaskAnnouncement MessageType = "task_announcement"
	TaskClaim        MessageType = "task_claim"
	TaskProgress     MessageType = "task_progress"
	TaskComplete     MessageType = "task_complete"
	CapabilityBcast  MessageType = "capability_broadcast"   // Only broadcast when capabilities change
	AvailabilityBcast MessageType = "availability_broadcast" // Regular availability status
	
	// HMMM meta-discussion messages
	MetaDiscussion       MessageType = "meta_discussion"        // Generic type for all discussion
	TaskHelpRequest      MessageType = "task_help_request"      // Request for assistance
	TaskHelpResponse     MessageType = "task_help_response"     // Response to a help request
	CoordinationRequest  MessageType = "coordination_request"   // Request for coordination
	CoordinationComplete MessageType = "coordination_complete"  // Coordination session completed
	DependencyAlert      MessageType = "dependency_alert"       // Dependency detected
	EscalationTrigger    MessageType = "escalation_trigger"     // Human escalation needed
	
	// Role-based collaboration messages
	RoleAnnouncement     MessageType = "role_announcement"      // Agent announces its role and capabilities
	ExpertiseRequest     MessageType = "expertise_request"      // Request for specific expertise
	ExpertiseResponse    MessageType = "expertise_response"     // Response offering expertise
	StatusUpdate         MessageType = "status_update"          // Regular status updates from agents
	WorkAllocation       MessageType = "work_allocation"        // Allocation of work to specific roles
	RoleCollaboration    MessageType = "role_collaboration"     // Cross-role collaboration message
	MentorshipRequest    MessageType = "mentorship_request"     // Junior role requesting mentorship
	MentorshipResponse   MessageType = "mentorship_response"    // Senior role providing mentorship
	ProjectUpdate        MessageType = "project_update"         // Project-level status updates
	DeliverableReady     MessageType = "deliverable_ready"      // Notification that deliverable is complete
	
	// RL Context Curator feedback messages
	FeedbackEvent        MessageType = "feedback_event"         // Context feedback for RL learning
	ContextRequest       MessageType = "context_request"        // Request context from HCFS
	ContextResponse      MessageType = "context_response"       // Response with context data
	ContextUsage         MessageType = "context_usage"          // Report context usage patterns
	ContextRelevance     MessageType = "context_relevance"      // Report context relevance scoring
	
	// SLURP event integration messages
	SlurpEventGenerated  MessageType = "slurp_event_generated"  // HMMM consensus generated SLURP event
	SlurpEventAck        MessageType = "slurp_event_ack"        // Acknowledgment of SLURP event receipt
	SlurpContextUpdate   MessageType = "slurp_context_update"   // Context update from SLURP system
)

// Message represents a Bzzz/Antennae message
type Message struct {
	Type      MessageType            `json:"type"`
	From      string                 `json:"from"`
	Timestamp time.Time              `json:"timestamp"`
	Data      map[string]interface{} `json:"data"`
	HopCount  int                    `json:"hop_count,omitempty"` // For Antennae hop limiting
	
	// Role-based collaboration fields
	FromRole        string   `json:"from_role,omitempty"`        // Role of sender
	ToRoles         []string `json:"to_roles,omitempty"`         // Target roles
	RequiredExpertise []string `json:"required_expertise,omitempty"` // Required expertise areas
	ProjectID       string   `json:"project_id,omitempty"`       // Associated project
	Priority        string   `json:"priority,omitempty"`         // Message priority (low, medium, high, urgent)
	ThreadID        string   `json:"thread_id,omitempty"`        // Conversation thread ID
}

// NewPubSub creates a new PubSub instance for Bzzz coordination and HMMM meta-discussion
func NewPubSub(ctx context.Context, h host.Host, bzzzTopic, hmmmTopic string) (*PubSub, error) {
	return NewPubSubWithLogger(ctx, h, bzzzTopic, hmmmTopic, nil)
}

// NewPubSubWithLogger creates a new PubSub instance with hypercore logging
func NewPubSubWithLogger(ctx context.Context, h host.Host, bzzzTopic, hmmmTopic string, logger HypercoreLogger) (*PubSub, error) {
	if bzzzTopic == "" {
		bzzzTopic = "bzzz/coordination/v1"
	}
	if hmmmTopic == "" {
		hmmmTopic = "hmmm/meta-discussion/v1"
	}
	contextTopic := "bzzz/context-feedback/v1"

	pubsubCtx, cancel := context.WithCancel(ctx)

	// Create gossipsub instance with message validation
	ps, err := pubsub.NewGossipSub(pubsubCtx, h,
		pubsub.WithMessageSigning(true),
		pubsub.WithStrictSignatureVerification(true),
		pubsub.WithValidateQueueSize(256),
		pubsub.WithValidateThrottle(1024),
	)
	if err != nil {
		cancel()
		return nil, fmt.Errorf("failed to create gossipsub: %w", err)
	}

	p := &PubSub{
		ps:                ps,
		host:              h,
		ctx:               pubsubCtx,
		cancel:            cancel,
		bzzzTopicName:    bzzzTopic,
		hmmmTopicName:    hmmmTopic,
		contextTopicName: contextTopic,
		dynamicTopics:     make(map[string]*pubsub.Topic),
		dynamicSubs:       make(map[string]*pubsub.Subscription),
		hypercoreLog:      logger,
	}

	// Join static topics
	if err := p.joinStaticTopics(); err != nil {
		cancel()
		return nil, err
	}

	// Start message handlers
	go p.handleBzzzMessages()
	go p.handleHmmmMessages()
	go p.handleContextFeedbackMessages()

	fmt.Printf("📡 PubSub initialized - Bzzz: %s, HMMM: %s, Context: %s\n", bzzzTopic, hmmmTopic, contextTopic)
	return p, nil
}

// SetHmmmMessageHandler sets the handler for incoming HMMM messages.
func (p *PubSub) SetHmmmMessageHandler(handler func(msg Message, from peer.ID)) {
	p.HmmmMessageHandler = handler
}

// SetContextFeedbackHandler sets the handler for incoming context feedback messages.
func (p *PubSub) SetContextFeedbackHandler(handler func(msg Message, from peer.ID)) {
	p.ContextFeedbackHandler = handler
}

// joinStaticTopics joins the main Bzzz, HMMM, and Context Feedback topics
func (p *PubSub) joinStaticTopics() error {
	// Join Bzzz coordination topic
	bzzzTopic, err := p.ps.Join(p.bzzzTopicName)
	if err != nil {
		return fmt.Errorf("failed to join Bzzz topic: %w", err)
	}
	p.bzzzTopic = bzzzTopic

	bzzzSub, err := bzzzTopic.Subscribe()
	if err != nil {
		return fmt.Errorf("failed to subscribe to Bzzz topic: %w", err)
	}
	p.bzzzSub = bzzzSub

	// Join HMMM meta-discussion topic
	hmmmTopic, err := p.ps.Join(p.hmmmTopicName)
	if err != nil {
		return fmt.Errorf("failed to join HMMM topic: %w", err)
	}
	p.hmmmTopic = hmmmTopic

	hmmmSub, err := hmmmTopic.Subscribe()
	if err != nil {
		return fmt.Errorf("failed to subscribe to HMMM topic: %w", err)
	}
	p.hmmmSub = hmmmSub

	// Join Context Feedback topic
	contextTopic, err := p.ps.Join(p.contextTopicName)
	if err != nil {
		return fmt.Errorf("failed to join Context Feedback topic: %w", err)
	}
	p.contextTopic = contextTopic

	contextSub, err := contextTopic.Subscribe()
	if err != nil {
		return fmt.Errorf("failed to subscribe to Context Feedback topic: %w", err)
	}
	p.contextSub = contextSub

	return nil
}

// JoinDynamicTopic joins a new topic for a specific task
func (p *PubSub) JoinDynamicTopic(topicName string) error {
	p.dynamicTopicsMux.Lock()
	defer p.dynamicTopicsMux.Unlock()
	p.dynamicSubsMux.Lock()
	defer p.dynamicSubsMux.Unlock()

	if _, exists := p.dynamicTopics[topicName]; exists {
		return nil // Already joined
	}

	topic, err := p.ps.Join(topicName)
	if err != nil {
		return fmt.Errorf("failed to join dynamic topic %s: %w", topicName, err)
	}

	sub, err := topic.Subscribe()
	if err != nil {
		topic.Close()
		return fmt.Errorf("failed to subscribe to dynamic topic %s: %w", topicName, err)
	}

	p.dynamicTopics[topicName] = topic
	p.dynamicSubs[topicName] = sub

	// Start a handler for this new subscription
	go p.handleDynamicMessages(sub)

	fmt.Printf("✅ Joined dynamic topic: %s\n", topicName)
	return nil
}

// JoinRoleBasedTopics joins topics based on role and expertise
func (p *PubSub) JoinRoleBasedTopics(role string, expertise []string, reportsTo []string) error {
	var topicsToJoin []string
	
	// Join role-specific topic
	if role != "" {
		roleTopic := fmt.Sprintf("bzzz/roles/%s/v1", strings.ToLower(strings.ReplaceAll(role, " ", "_")))
		topicsToJoin = append(topicsToJoin, roleTopic)
	}
	
	// Join expertise-specific topics
	for _, exp := range expertise {
		expertiseTopic := fmt.Sprintf("bzzz/expertise/%s/v1", strings.ToLower(strings.ReplaceAll(exp, " ", "_")))
		topicsToJoin = append(topicsToJoin, expertiseTopic)
	}
	
	// Join reporting hierarchy topics
	for _, supervisor := range reportsTo {
		supervisorTopic := fmt.Sprintf("bzzz/hierarchy/%s/v1", strings.ToLower(strings.ReplaceAll(supervisor, " ", "_")))
		topicsToJoin = append(topicsToJoin, supervisorTopic)
	}
	
	// Join all identified topics
	for _, topicName := range topicsToJoin {
		if err := p.JoinDynamicTopic(topicName); err != nil {
			fmt.Printf("⚠️ Failed to join role-based topic %s: %v\n", topicName, err)
			continue
		}
	}
	
	fmt.Printf("🎯 Joined %d role-based topics for role: %s\n", len(topicsToJoin), role)
	return nil
}

// JoinProjectTopic joins a project-specific topic
func (p *PubSub) JoinProjectTopic(projectID string) error {
	if projectID == "" {
		return fmt.Errorf("project ID cannot be empty")
	}
	
	topicName := fmt.Sprintf("bzzz/projects/%s/coordination/v1", projectID)
	return p.JoinDynamicTopic(topicName)
}

// LeaveDynamicTopic leaves a specific task topic
func (p *PubSub) LeaveDynamicTopic(topicName string) {
	p.dynamicTopicsMux.Lock()
	defer p.dynamicTopicsMux.Unlock()
	p.dynamicSubsMux.Lock()
	defer p.dynamicSubsMux.Unlock()

	if sub, exists := p.dynamicSubs[topicName]; exists {
		sub.Cancel()
		delete(p.dynamicSubs, topicName)
	}

	if topic, exists := p.dynamicTopics[topicName]; exists {
		topic.Close()
		delete(p.dynamicTopics, topicName)
	}

	fmt.Printf("🗑️ Left dynamic topic: %s\n", topicName)
}

// PublishToDynamicTopic publishes a message to a specific dynamic topic
func (p *PubSub) PublishToDynamicTopic(topicName string, msgType MessageType, data map[string]interface{}) error {
	p.dynamicTopicsMux.RLock()
	topic, exists := p.dynamicTopics[topicName]
	p.dynamicTopicsMux.RUnlock()

	if !exists {
		return fmt.Errorf("not subscribed to dynamic topic: %s", topicName)
	}

	msg := Message{
		Type:      msgType,
		From:      p.host.ID().String(),
		Timestamp: time.Now(),
		Data:      data,
	}

	msgBytes, err := json.Marshal(msg)
	if err != nil {
		return fmt.Errorf("failed to marshal message for dynamic topic: %w", err)
	}

	return topic.Publish(p.ctx, msgBytes)
}

// PublishRaw publishes a raw JSON payload to the given topic name without
// wrapping it in the BZZZ Message envelope. Intended for HMMM per-issue rooms
// or other modules that maintain their own schemas.
func (p *PubSub) PublishRaw(topicName string, payload []byte) error {
    // Dynamic topic
    p.dynamicTopicsMux.RLock()
    if topic, exists := p.dynamicTopics[topicName]; exists {
        p.dynamicTopicsMux.RUnlock()
        return topic.Publish(p.ctx, payload)
    }
    p.dynamicTopicsMux.RUnlock()

    // Static topics by name
    switch topicName {
    case p.bzzzTopicName:
        return p.bzzzTopic.Publish(p.ctx, payload)
    case p.hmmmTopicName:
        return p.hmmmTopic.Publish(p.ctx, payload)
    case p.contextTopicName:
        return p.contextTopic.Publish(p.ctx, payload)
    default:
        return fmt.Errorf("not subscribed to topic: %s", topicName)
    }
}

// PublishBzzzMessage publishes a message to the Bzzz coordination topic
func (p *PubSub) PublishBzzzMessage(msgType MessageType, data map[string]interface{}) error {
	msg := Message{
		Type:      msgType,
		From:      p.host.ID().String(),
		Timestamp: time.Now(),
		Data:      data,
	}

	msgBytes, err := json.Marshal(msg)
	if err != nil {
		return fmt.Errorf("failed to marshal message: %w", err)
	}

	return p.bzzzTopic.Publish(p.ctx, msgBytes)
}

// PublishHmmmMessage publishes a message to the HMMM meta-discussion topic
func (p *PubSub) PublishHmmmMessage(msgType MessageType, data map[string]interface{}) error {
	msg := Message{
		Type:      msgType,
		From:      p.host.ID().String(),
		Timestamp: time.Now(),
		Data:      data,
	}

	msgBytes, err := json.Marshal(msg)
	if err != nil {
		return fmt.Errorf("failed to marshal message: %w", err)
	}

	return p.hmmmTopic.Publish(p.ctx, msgBytes)
}

// PublishAntennaeMessage is a compatibility alias for PublishHmmmMessage
// Deprecated: Use PublishHmmmMessage instead
func (p *PubSub) PublishAntennaeMessage(msgType MessageType, data map[string]interface{}) error {
	return p.PublishHmmmMessage(msgType, data)
}

// SetAntennaeMessageHandler is a compatibility alias for SetHmmmMessageHandler
// Deprecated: Use SetHmmmMessageHandler instead
func (p *PubSub) SetAntennaeMessageHandler(handler func(msg Message, from peer.ID)) {
	p.SetHmmmMessageHandler(handler)
}

// PublishContextFeedbackMessage publishes a message to the Context Feedback topic
func (p *PubSub) PublishContextFeedbackMessage(msgType MessageType, data map[string]interface{}) error {
	msg := Message{
		Type:      msgType,
		From:      p.host.ID().String(),
		Timestamp: time.Now(),
		Data:      data,
	}

	msgBytes, err := json.Marshal(msg)
	if err != nil {
		return fmt.Errorf("failed to marshal context feedback message: %w", err)
	}

	return p.contextTopic.Publish(p.ctx, msgBytes)
}

// PublishRoleBasedMessage publishes a role-based collaboration message
func (p *PubSub) PublishRoleBasedMessage(msgType MessageType, data map[string]interface{}, opts MessageOptions) error {
	msg := Message{
		Type:              msgType,
		From:              p.host.ID().String(),
		Timestamp:         time.Now(),
		Data:              data,
		FromRole:          opts.FromRole,
		ToRoles:           opts.ToRoles,
		RequiredExpertise: opts.RequiredExpertise,
		ProjectID:         opts.ProjectID,
		Priority:          opts.Priority,
		ThreadID:          opts.ThreadID,
	}

	msgBytes, err := json.Marshal(msg)
	if err != nil {
		return fmt.Errorf("failed to marshal role-based message: %w", err)
	}

	// Determine which topic to use based on message type
	var topic *pubsub.Topic
	switch msgType {
	case RoleAnnouncement, ExpertiseRequest, ExpertiseResponse, StatusUpdate, 
		 WorkAllocation, RoleCollaboration, MentorshipRequest, MentorshipResponse,
		 ProjectUpdate, DeliverableReady:
		topic = p.hmmmTopic // Use HMMM topic for role-based messages
	default:
		topic = p.bzzzTopic // Default to Bzzz topic
	}

	return topic.Publish(p.ctx, msgBytes)
}

// PublishSlurpEventGenerated publishes a SLURP event generation notification
func (p *PubSub) PublishSlurpEventGenerated(data map[string]interface{}) error {
	return p.PublishHmmmMessage(SlurpEventGenerated, data)
}

// PublishSlurpEventAck publishes a SLURP event acknowledgment
func (p *PubSub) PublishSlurpEventAck(data map[string]interface{}) error {
	return p.PublishHmmmMessage(SlurpEventAck, data)
}

// PublishSlurpContextUpdate publishes a SLURP context update notification
func (p *PubSub) PublishSlurpContextUpdate(data map[string]interface{}) error {
	return p.PublishHmmmMessage(SlurpContextUpdate, data)
}

// PublishSlurpIntegrationEvent publishes a generic SLURP integration event
func (p *PubSub) PublishSlurpIntegrationEvent(eventType string, discussionID string, slurpEvent map[string]interface{}) error {
	data := map[string]interface{}{
		"event_type":     eventType,
		"discussion_id":  discussionID,
		"slurp_event":    slurpEvent,
		"timestamp":      time.Now(),
		"source":         "hmmm-slurp-integration",
		"peer_id":        p.host.ID().String(),
	}
	
	return p.PublishSlurpEventGenerated(data)
}

// GetHypercoreLog returns the hypercore logger for external access
func (p *PubSub) GetHypercoreLog() HypercoreLogger {
	return p.hypercoreLog
}

// MessageOptions holds options for role-based messages
type MessageOptions struct {
	FromRole          string
	ToRoles           []string
	RequiredExpertise []string
	ProjectID         string
	Priority          string
	ThreadID          string
}

// handleBzzzMessages processes incoming Bzzz coordination messages
func (p *PubSub) handleBzzzMessages() {
	for {
		msg, err := p.bzzzSub.Next(p.ctx)
		if err != nil {
			if p.ctx.Err() != nil {
				return // Context cancelled
			}
			fmt.Printf("❌ Error receiving Bzzz message: %v\n", err)
			continue
		}

		if msg.ReceivedFrom == p.host.ID() {
			continue
		}

		var bzzzMsg Message
		if err := json.Unmarshal(msg.Data, &bzzzMsg); err != nil {
			fmt.Printf("❌ Failed to unmarshal Bzzz message: %v\n", err)
			continue
		}

		p.processBzzzMessage(bzzzMsg, msg.ReceivedFrom)
	}
}

// handleHmmmMessages processes incoming HMMM meta-discussion messages
func (p *PubSub) handleHmmmMessages() {
	for {
		msg, err := p.hmmmSub.Next(p.ctx)
		if err != nil {
			if p.ctx.Err() != nil {
				return // Context cancelled
			}
			fmt.Printf("❌ Error receiving HMMM message: %v\n", err)
			continue
		}

		if msg.ReceivedFrom == p.host.ID() {
			continue
		}

		var hmmmMsg Message
		if err := json.Unmarshal(msg.Data, &hmmmMsg); err != nil {
			fmt.Printf("❌ Failed to unmarshal HMMM message: %v\n", err)
			continue
		}

		if p.HmmmMessageHandler != nil {
			p.HmmmMessageHandler(hmmmMsg, msg.ReceivedFrom)
		} else {
			p.processHmmmMessage(hmmmMsg, msg.ReceivedFrom)
		}
	}
}

// handleContextFeedbackMessages processes incoming context feedback messages
func (p *PubSub) handleContextFeedbackMessages() {
	for {
		msg, err := p.contextSub.Next(p.ctx)
		if err != nil {
			if p.ctx.Err() != nil {
				return // Context cancelled
			}
			fmt.Printf("❌ Error receiving Context Feedback message: %v\n", err)
			continue
		}

		if msg.ReceivedFrom == p.host.ID() {
			continue
		}

		var contextMsg Message
		if err := json.Unmarshal(msg.Data, &contextMsg); err != nil {
			fmt.Printf("❌ Failed to unmarshal Context Feedback message: %v\n", err)
			continue
		}

		if p.ContextFeedbackHandler != nil {
			p.ContextFeedbackHandler(contextMsg, msg.ReceivedFrom)
		} else {
			p.processContextFeedbackMessage(contextMsg, msg.ReceivedFrom)
		}
	}
}

// handleDynamicMessages processes messages from a dynamic topic subscription
func (p *PubSub) handleDynamicMessages(sub *pubsub.Subscription) {
	for {
		msg, err := sub.Next(p.ctx)
		if err != nil {
			if p.ctx.Err() != nil || err.Error() == "subscription cancelled" {
				return // Subscription was cancelled, exit handler
			}
			fmt.Printf("❌ Error receiving dynamic message: %v\n", err)
			continue
		}

		if msg.ReceivedFrom == p.host.ID() {
			continue
		}

		var dynamicMsg Message
		if err := json.Unmarshal(msg.Data, &dynamicMsg); err != nil {
			fmt.Printf("❌ Failed to unmarshal dynamic message: %v\n", err)
			continue
		}

		// Use the main HMMM handler for all dynamic messages
		if p.HmmmMessageHandler != nil {
			p.HmmmMessageHandler(dynamicMsg, msg.ReceivedFrom)
		}
	}
}

// processBzzzMessage handles different types of Bzzz coordination messages
func (p *PubSub) processBzzzMessage(msg Message, from peer.ID) {
	fmt.Printf("🐝 Bzzz [%s] from %s: %v\n", msg.Type, from.ShortString(), msg.Data)
	
	// Log to hypercore if logger is available
	if p.hypercoreLog != nil {
		logData := map[string]interface{}{
			"message_type": string(msg.Type),
			"from_peer":    from.String(),
			"from_short":   from.ShortString(),
			"timestamp":    msg.Timestamp,
			"data":         msg.Data,
			"topic":        "bzzz",
		}
		
		// Map pubsub message types to hypercore log types
		var logType string
		switch msg.Type {
		case TaskAnnouncement:
			logType = "task_announced"
		case TaskClaim:
			logType = "task_claimed"
		case TaskProgress:
			logType = "task_progress"
		case TaskComplete:
			logType = "task_completed"
		case CapabilityBcast:
			logType = "capability_broadcast"
		case AvailabilityBcast:
			logType = "network_event"
		default:
			logType = "network_event"
		}
		
		if err := p.hypercoreLog.AppendString(logType, logData); err != nil {
			fmt.Printf("❌ Failed to log Bzzz message to hypercore: %v\n", err)
		}
	}
}

// processHmmmMessage provides default handling for HMMM messages if no external handler is set
func (p *PubSub) processHmmmMessage(msg Message, from peer.ID) {
	fmt.Printf("🎯 Default HMMM Handler [%s] from %s: %v\n", 
		msg.Type, from.ShortString(), msg.Data)
	
	// Log to hypercore if logger is available
	if p.hypercoreLog != nil {
		logData := map[string]interface{}{
			"message_type":       string(msg.Type),
			"from_peer":          from.String(),
			"from_short":         from.ShortString(),
			"timestamp":          msg.Timestamp,
			"data":               msg.Data,
			"topic":              "hmmm",
			"from_role":          msg.FromRole,
			"to_roles":           msg.ToRoles,
			"required_expertise": msg.RequiredExpertise,
			"project_id":         msg.ProjectID,
			"priority":           msg.Priority,
			"thread_id":          msg.ThreadID,
		}
		
		// Map pubsub message types to hypercore log types
		var logType string
		switch msg.Type {
		case MetaDiscussion, TaskHelpRequest, TaskHelpResponse:
			logType = "collaboration"
		case CoordinationRequest, CoordinationComplete:
			logType = "collaboration"
		case DependencyAlert:
			logType = "collaboration"
		case EscalationTrigger:
			logType = "escalation"
		case RoleAnnouncement, ExpertiseRequest, ExpertiseResponse:
			logType = "collaboration"
		case StatusUpdate, WorkAllocation, RoleCollaboration:
			logType = "collaboration"
		case MentorshipRequest, MentorshipResponse:
			logType = "collaboration"
		case ProjectUpdate, DeliverableReady:
			logType = "collaboration"
		default:
			logType = "collaboration"
		}
		
		if err := p.hypercoreLog.AppendString(logType, logData); err != nil {
			fmt.Printf("❌ Failed to log HMMM message to hypercore: %v\n", err)
		}
	}
}

// processContextFeedbackMessage provides default handling for context feedback messages if no external handler is set
func (p *PubSub) processContextFeedbackMessage(msg Message, from peer.ID) {
	fmt.Printf("🧠 Context Feedback [%s] from %s: %v\n", 
		msg.Type, from.ShortString(), msg.Data)
	
	// Log to hypercore if logger is available
	if p.hypercoreLog != nil {
		logData := map[string]interface{}{
			"message_type":       string(msg.Type),
			"from_peer":          from.String(),
			"from_short":         from.ShortString(),
			"timestamp":          msg.Timestamp,
			"data":               msg.Data,
			"topic":              "context_feedback",
			"from_role":          msg.FromRole,
			"to_roles":           msg.ToRoles,
			"project_id":         msg.ProjectID,
			"priority":           msg.Priority,
			"thread_id":          msg.ThreadID,
		}
		
		// Map context feedback message types to hypercore log types
		var logType string
		switch msg.Type {
		case FeedbackEvent:
			logType = "context_feedback"
		case ContextRequest, ContextResponse:
			logType = "context_request"
		case ContextUsage, ContextRelevance:
			logType = "context_usage"
		default:
			logType = "context_feedback"
		}
		
		if err := p.hypercoreLog.AppendString(logType, logData); err != nil {
			fmt.Printf("❌ Failed to log Context Feedback message to hypercore: %v\n", err)
		}
	}
}

// Close shuts down the PubSub instance
func (p *PubSub) Close() error {
	p.cancel()
	
	if p.bzzzSub != nil {
		p.bzzzSub.Cancel()
	}
	if p.hmmmSub != nil {
		p.hmmmSub.Cancel()
	}
	if p.contextSub != nil {
		p.contextSub.Cancel()
	}
	
	if p.bzzzTopic != nil {
		p.bzzzTopic.Close()
	}
	if p.hmmmTopic != nil {
		p.hmmmTopic.Close()
	}
	if p.contextTopic != nil {
		p.contextTopic.Close()
	}
	
	p.dynamicTopicsMux.Lock()
	for _, topic := range p.dynamicTopics {
		topic.Close()
	}
	p.dynamicTopicsMux.Unlock()

	return nil
}
