package agent

import (
	"context"
	"fmt"
	"time"

	"chorus.services/bzzz/internal/common/runtime"
	"chorus.services/bzzz/logging"
)

// Runner manages the execution of the autonomous agent
type Runner struct {
	services     *runtime.RuntimeServices
	logger       logging.Logger
	taskTracker  runtime.SimpleTaskTracker
	announcer    *runtime.CapabilityAnnouncer
	statusReporter *runtime.StatusReporter
	running      bool
}

// NewRunner creates a new agent runner
func NewRunner(services *runtime.RuntimeServices, logger logging.Logger) *Runner {
	return &Runner{
		services: services,
		logger:   logger,
		running:  false,
	}
}

// Start begins the agent execution
func (r *Runner) Start(ctx context.Context) error {
	if r.running {
		return fmt.Errorf("agent runner is already running")
	}

	r.logger.Info("🤖 Starting autonomous agent runner")

	// Initialize task tracker
	r.taskTracker = runtime.NewTaskTracker(
		r.services.Config.Agent.MaxTasks,
		r.services.Node.ID().ShortString(),
		r.services.PubSub,
	)

	// Connect decision publisher to task tracker if available
	if r.services.DecisionPublisher != nil {
		r.taskTracker.SetDecisionPublisher(r.services.DecisionPublisher)
		r.logger.Info("📤 Task completion decisions will be published to DHT")
	}

	// Initialize capability announcer
	r.announcer = runtime.NewCapabilityAnnouncer(
		r.services.PubSub,
		r.services.Node.ID().ShortString(),
	)

	// Initialize status reporter
	r.statusReporter = runtime.NewStatusReporter(r.services.Node)

	// Start background services
	r.startBackgroundServices()

	r.running = true
	r.logger.Info("✅ Autonomous agent runner started successfully")

	return nil
}

// Stop gracefully stops the agent execution
func (r *Runner) Stop(ctx context.Context) error {
	if !r.running {
		return nil
	}

	r.logger.Info("🛑 Stopping autonomous agent runner")
	r.running = false
	
	// Any cleanup specific to agent execution would go here
	
	r.logger.Info("✅ Autonomous agent runner stopped")
	return nil
}

// startBackgroundServices starts all background services for the agent
func (r *Runner) startBackgroundServices() {
	// Start availability announcements
	if r.taskTracker != nil {
		// TODO: Implement availability announcements
		// r.taskTracker.AnnounceAvailability()
		r.logger.Info("📡 Task tracker initialized")
	}

	// Announce capabilities and role
	if r.announcer != nil {
		r.announcer.AnnounceCapabilitiesOnChange(r.services)
		r.announcer.AnnounceRoleOnStartup(r.services)
		r.logger.Info("📢 Capability and role announcements completed")
	}

	// Start status reporting
	if r.statusReporter != nil {
		r.statusReporter.Start()
		r.logger.Info("📊 Status reporting started")
	}

	r.logger.Info("🔍 Listening for peers on local network...")
	r.logger.Info("📡 Ready for task coordination and meta-discussion")
	r.logger.Info("🎯 HMMM collaborative reasoning enabled")
}

// GetTaskTracker returns the task tracker for external use
func (r *Runner) GetTaskTracker() runtime.SimpleTaskTracker {
	return r.taskTracker
}

// IsRunning returns whether the agent runner is currently running
func (r *Runner) IsRunning() bool {
	return r.running
}

// GetServices returns the runtime services
func (r *Runner) GetServices() *runtime.RuntimeServices {
	return r.services
}

// HandleTask would handle incoming tasks - placeholder for future implementation
func (r *Runner) HandleTask(taskID string, taskData interface{}) error {
	if !r.running {
		return fmt.Errorf("agent runner is not running")
	}

	// Add task to tracker
	r.taskTracker.AddTask(taskID)
	r.logger.Info("📋 Started task: %s", taskID)

	// Placeholder for actual task processing
	go func() {
		// Simulate task processing
		time.Sleep(5 * time.Second)
		
		// Complete task
		r.taskTracker.CompleteTaskWithDecision(
			taskID,
			true,
			"Task completed successfully",
			[]string{}, // No files modified in this example
		)
		
		r.logger.Info("✅ Completed task: %s", taskID)
	}()

	return nil
}

// GetStatus returns the current agent status
func (r *Runner) GetStatus() map[string]interface{} {
	status := map[string]interface{}{
		"running":    r.running,
		"type":       "agent",
		"timestamp":  time.Now().Unix(),
	}

	if r.taskTracker != nil {
		status["active_tasks"] = len(r.taskTracker.GetActiveTasks())
		status["max_tasks"] = r.taskTracker.GetMaxTasks()
		// TODO: Implement availability and status methods
		status["available"] = len(r.taskTracker.GetActiveTasks()) < r.taskTracker.GetMaxTasks()
		status["task_status"] = "active"
	}

	if r.services != nil && r.services.Node != nil {
		status["node_id"] = r.services.Node.ID().ShortString()
		status["connected_peers"] = r.services.Node.ConnectedPeers()
	}

	if r.services != nil && r.services.Config != nil {
		status["agent_id"] = r.services.Config.Agent.ID
		status["role"] = r.services.Config.Agent.Role
		status["specialization"] = r.services.Config.Agent.Specialization
		status["capabilities"] = r.services.Config.Agent.Capabilities
	}

	return status
}