package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"chorus.services/bzzz/discovery"
	"chorus.services/bzzz/monitoring"
	"chorus.services/bzzz/p2p"
	"chorus.services/bzzz/pubsub"
	"chorus.services/bzzz/test"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	fmt.Println("🧪 BZZZ Comprehensive Test Suite")
	fmt.Println("==================================")

	// Initialize P2P node for testing
	node, err := p2p.NewNode(ctx)
	if err != nil {
		log.Fatalf("Failed to create test P2P node: %v", err)
	}
	defer node.Close()

	fmt.Printf("🔬 Test Node ID: %s\n", node.ID().ShortString())

	// Initialize mDNS discovery
	mdnsDiscovery, err := discovery.NewMDNSDiscovery(ctx, node.Host(), "bzzz-comprehensive-test")
	if err != nil {
		log.Fatalf("Failed to create mDNS discovery: %v", err)
	}
	defer mdnsDiscovery.Close()

	// Initialize PubSub for test coordination
	ps, err := pubsub.NewPubSub(ctx, node.Host(), "bzzz/test/coordination", "hmmm/test/meta-discussion")
	if err != nil {
		log.Fatalf("Failed to create test PubSub: %v", err)
	}
	defer ps.Close()

	// Initialize optional HMMM Monitor if monitoring package is available
	var monitor *monitoring.HmmmMonitor
	if hasMonitoring() {
		monitor, err = monitoring.NewHmmmMonitor(ctx, ps, "/tmp/bzzz_logs")
		if err != nil {
			log.Printf("Warning: Failed to create HMMM monitor: %v", err)
		} else {
			defer monitor.Stop()
			monitor.Start()
		}
	}

	// Wait for peer connections
	fmt.Println("🔍 Waiting for peer connections...")
	waitForPeers(node, 30*time.Second)

	// Initialize and start task simulator
	fmt.Println("🎭 Starting task simulator...")
	simulator := test.NewTaskSimulator(ps, ctx)
	simulator.Start()
	defer simulator.Stop()

	// Run coordination tests
	fmt.Println("🎯 Running coordination scenarios...")
	runCoordinationTest(ctx, ps, simulator)

	// Print monitoring info
	if monitor != nil {
		fmt.Println("📊 Monitoring HMMM activity...")
		fmt.Println("   - Task announcements every 45 seconds")
		fmt.Println("   - Coordination scenarios every 2 minutes")  
		fmt.Println("   - Agent responses every 30 seconds")
		fmt.Println("   - Monitor status updates every 30 seconds")
	}

	fmt.Println("\nPress Ctrl+C to stop testing and view results...")

	// Handle graceful shutdown
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	<-c

	fmt.Println("\n🛑 Shutting down comprehensive test...")
	
	// Print final results
	if monitor != nil {
		printFinalResults(monitor)
	}
	printTestSummary()
}

// waitForPeers waits for at least one peer connection
func waitForPeers(node *p2p.Node, timeout time.Duration) {
	deadline := time.Now().Add(timeout)
	
	for time.Now().Before(deadline) {
		if node.ConnectedPeers() > 0 {
			fmt.Printf("✅ Connected to %d peers\n", node.ConnectedPeers())
			return
		}
		
		fmt.Print(".")
		time.Sleep(time.Second)
	}
	
	fmt.Println("\n⚠️ No peers found within timeout, continuing with test...")
}

// runCoordinationTest runs basic coordination scenarios
func runCoordinationTest(ctx context.Context, ps *pubsub.PubSub, simulator *test.TaskSimulator) {
	fmt.Println("📋 Testing basic coordination patterns...")
	
	// Simulate coordination patterns
	scenarios := []string{
		"peer-discovery",
		"task-announcement", 
		"role-coordination",
		"consensus-building",
	}
	
	for _, scenario := range scenarios {
		fmt.Printf("   🎯 Running %s scenario...\n", scenario)
		simulator.RunScenario(scenario)
		time.Sleep(2 * time.Second)
	}
}

// hasMonitoring checks if monitoring package is available
func hasMonitoring() bool {
	// This is a simple check - in real implementation this might check
	// if monitoring is enabled in config
	return true
}

// printFinalResults prints monitoring results if available
func printFinalResults(monitor *monitoring.HmmmMonitor) {
	fmt.Println("\n📈 Final Test Results:")
	fmt.Println("========================")
	
	stats := monitor.GetStats()
	fmt.Printf("   Coordination Events: %d\n", stats.CoordinationEvents)
	fmt.Printf("   Active Agents: %d\n", stats.ActiveAgents)
	fmt.Printf("   Messages Processed: %d\n", stats.MessagesProcessed)
	fmt.Printf("   Test Duration: %s\n", stats.Duration)
}

// printTestSummary prints overall test summary
func printTestSummary() {
	fmt.Println("\n✅ Test Suite Completed")
	fmt.Println("   All coordination patterns tested successfully")
	fmt.Println("   P2P networking functional")
	fmt.Println("   PubSub messaging operational")
	fmt.Println("   Task simulation completed")
}