package hap

import (
	"bufio"
	"context"
	"fmt"
	"os"
	"strings"
	"time"

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

// TerminalInterface provides a terminal-based interface for human agents
type TerminalInterface struct {
	services *runtime.RuntimeServices
	logger   logging.Logger
	running  bool
	scanner  *bufio.Scanner
}

// NewTerminalInterface creates a new terminal interface
func NewTerminalInterface(services *runtime.RuntimeServices, logger logging.Logger) *TerminalInterface {
	return &TerminalInterface{
		services: services,
		logger:   logger,
		running:  false,
		scanner:  bufio.NewScanner(os.Stdin),
	}
}

// Start begins the terminal interface
func (ti *TerminalInterface) Start(ctx context.Context) error {
	if ti.running {
		return fmt.Errorf("terminal interface is already running")
	}

	ti.logger.Info("👤 Starting Human Agent Portal terminal interface")

	// Display welcome message
	ti.displayWelcome()

	// Start command processing in background
	go ti.processCommands(ctx)

	ti.running = true
	ti.logger.Info("✅ Terminal interface ready for human interaction")

	return nil
}

// Stop gracefully stops the terminal interface
func (ti *TerminalInterface) Stop(ctx context.Context) error {
	if !ti.running {
		return nil
	}

	ti.logger.Info("🛑 Stopping terminal interface")
	ti.running = false

	fmt.Println("\n👋 Human Agent Portal shutting down. Goodbye!")
	return nil
}

// displayWelcome shows the welcome message and commands
func (ti *TerminalInterface) displayWelcome() {
	fmt.Println("\n" + strings.Repeat("=", 60))
	fmt.Println("🎯 BZZZ Human Agent Portal (HAP)")
	fmt.Println("   Welcome to collaborative AI task coordination")
	fmt.Println(strings.Repeat("=", 60))

	if ti.services.Node != nil {
		fmt.Printf("📍 Node ID: %s\n", ti.services.Node.ID().ShortString())
	}

	if ti.services.Config != nil {
		fmt.Printf("🤖 Agent ID: %s\n", ti.services.Config.Agent.ID)
		if ti.services.Config.Agent.Role != "" {
			fmt.Printf("🎭 Role: %s\n", ti.services.Config.Agent.Role)
		}
	}

	if ti.services.Node != nil {
		fmt.Printf("🌐 Connected Peers: %d\n", ti.services.Node.ConnectedPeers())
	}

	fmt.Println("\n📋 Available Commands:")
	fmt.Println("  status     - Show system status")
	fmt.Println("  peers      - List connected peers")
	fmt.Println("  send <msg> - Send message to coordination channel")
	fmt.Println("  role       - Show role information")
	fmt.Println("  tasks      - Show task information")
	fmt.Println("  health     - Show health status")
	fmt.Println("  help       - Show this help message")
	fmt.Println("  quit/exit  - Exit the interface")
	fmt.Println(strings.Repeat("-", 60))
	fmt.Print("HAP> ")
}

// processCommands handles user input and commands
func (ti *TerminalInterface) processCommands(ctx context.Context) {
	for ti.running && ti.scanner.Scan() {
		input := strings.TrimSpace(ti.scanner.Text())
		if input == "" {
			fmt.Print("HAP> ")
			continue
		}

		// Parse command and arguments
		parts := strings.Fields(input)
		command := strings.ToLower(parts[0])

		switch command {
		case "quit", "exit":
			ti.running = false
			return

		case "help":
			ti.showHelp()

		case "status":
			ti.showStatus()

		case "peers":
			ti.showPeers()

		case "role":
			ti.showRole()

		case "tasks":
			ti.showTasks()

		case "health":
			ti.showHealth()

		case "send":
			if len(parts) < 2 {
				fmt.Println("❌ Usage: send <message>")
			} else {
				message := strings.Join(parts[1:], " ")
				ti.sendMessage(message)
			}

		default:
			fmt.Printf("❌ Unknown command: %s (type 'help' for available commands)\n", command)
		}

		fmt.Print("HAP> ")
	}
}

// showHelp displays the help message
func (ti *TerminalInterface) showHelp() {
	fmt.Println("\n📋 HAP Commands:")
	fmt.Println("  status     - Show current system status")
	fmt.Println("  peers      - List all connected P2P peers")
	fmt.Println("  send <msg> - Send message to coordination channel")
	fmt.Println("  role       - Display role and capability information")
	fmt.Println("  tasks      - Show active tasks (if any)")
	fmt.Println("  health     - Display system health status")
	fmt.Println("  help       - Show this help message")
	fmt.Println("  quit/exit  - Exit the Human Agent Portal")
}

// showStatus displays the current system status
func (ti *TerminalInterface) showStatus() {
	fmt.Println("\n📊 System Status:")
	fmt.Println(strings.Repeat("-", 40))

	if ti.services.Node != nil {
		fmt.Printf("🌐 P2P Status: Connected (%d peers)\n", ti.services.Node.ConnectedPeers())
		fmt.Printf("📍 Node ID: %s\n", ti.services.Node.ID().ShortString())
	}

	if ti.services.Config != nil {
		fmt.Printf("🤖 Agent ID: %s\n", ti.services.Config.Agent.ID)
		fmt.Printf("🎭 Role: %s\n", ti.services.Config.Agent.Role)
		fmt.Printf("🎯 Specialization: %s\n", ti.services.Config.Agent.Specialization)
	}

	// Service status
	fmt.Printf("📡 PubSub: %s\n", ti.getServiceStatus("PubSub", ti.services.PubSub != nil))
	fmt.Printf("🕸️ DHT: %s\n", ti.getServiceStatus("DHT", ti.services.DHT != nil))
	fmt.Printf("🔗 UCXI: %s\n", ti.getServiceStatus("UCXI", ti.services.UCXIServer != nil))
	fmt.Printf("🗳️ Elections: %s\n", ti.getServiceStatus("Elections", ti.services.ElectionManager != nil))
	fmt.Printf("❤️ Health: %s\n", ti.getServiceStatus("Health", ti.services.HealthManager != nil))

	fmt.Printf("⏰ Uptime: %s\n", time.Since(time.Now().Add(-5*time.Minute)).String()) // Placeholder
}

// showPeers displays connected peers
func (ti *TerminalInterface) showPeers() {
	fmt.Println("\n🌐 Connected Peers:")
	fmt.Println(strings.Repeat("-", 40))

	if ti.services.Node != nil {
		peerCount := ti.services.Node.ConnectedPeers()
		fmt.Printf("Total Connected: %d\n", peerCount)

		if peerCount == 0 {
			fmt.Println("No peers currently connected")
			fmt.Println("💡 Tip: Make sure other BZZZ nodes are running on your network")
		} else {
			fmt.Println("🔍 Use P2P tools to see detailed peer information")
		}
	} else {
		fmt.Println("❌ P2P node not available")
	}
}

// showRole displays role and capability information
func (ti *TerminalInterface) showRole() {
	fmt.Println("\n🎭 Role Information:")
	fmt.Println(strings.Repeat("-", 40))

	if ti.services.Config != nil {
		cfg := ti.services.Config
		fmt.Printf("Role: %s\n", cfg.Agent.Role)
		fmt.Printf("Expertise: %v\n", cfg.Agent.Expertise)
		fmt.Printf("Reports To: %v\n", cfg.Agent.ReportsTo)
		fmt.Printf("Deliverables: %v\n", cfg.Agent.Deliverables)
		fmt.Printf("Capabilities: %v\n", cfg.Agent.Capabilities)
		fmt.Printf("Specialization: %s\n", cfg.Agent.Specialization)

		// Authority level
		if authority, err := cfg.GetRoleAuthority(cfg.Agent.Role); err == nil {
			fmt.Printf("Authority Level: %s\n", authority)
		}
	} else {
		fmt.Println("❌ Configuration not available")
	}
}

// showTasks displays task information
func (ti *TerminalInterface) showTasks() {
	fmt.Println("\n📋 Task Information:")
	fmt.Println(strings.Repeat("-", 40))

	// HAP doesn't execute tasks like agents, but can show coordination status
	fmt.Println("📝 HAP Role: Human interaction facilitator")
	fmt.Println("🎯 Purpose: Coordinate with autonomous agents")
	fmt.Println("💼 Current Mode: Interactive terminal")

	if ti.services.TaskCoordinator != nil {
		fmt.Println("✅ Task coordination system is active")
	} else {
		fmt.Println("❌ Task coordination system not available")
	}
}

// showHealth displays health status
func (ti *TerminalInterface) showHealth() {
	fmt.Println("\n❤️ Health Status:")
	fmt.Println(strings.Repeat("-", 40))

	if ti.services.HealthManager != nil {
		status := ti.services.HealthManager.GetOverallStatus()
		healthIcon := "✅"
		if !status.Healthy {
			healthIcon = "❌"
		}
		fmt.Printf("%s Overall Health: %s\n", healthIcon, ti.boolToStatus(status.Healthy))
		fmt.Printf("📋 Details: %s\n", status.Message)
		fmt.Printf("⏰ Last Check: %s\n", status.Timestamp.Format(time.RFC3339))
	} else {
		fmt.Println("❌ Health manager not available")
	}
}

// sendMessage sends a message to the coordination channel
func (ti *TerminalInterface) sendMessage(message string) {
	if ti.services.PubSub == nil {
		fmt.Println("❌ PubSub not available - cannot send message")
		return
	}

	// Create a human-authored message
	messageData := map[string]interface{}{
		"type":      "human_message",
		"author":    "human",
		"node_id":   ti.services.Node.ID().ShortString(),
		"agent_id":  ti.services.Config.Agent.ID,
		"role":      ti.services.Config.Agent.Role,
		"message":   message,
		"timestamp": time.Now().Unix(),
	}

	// Send to coordination channel
	if err := ti.services.PubSub.PublishBzzzMessage("coordination", messageData); err != nil {
		fmt.Printf("❌ Failed to send message: %v\n", err)
	} else {
		fmt.Printf("📤 Message sent to coordination channel\n")
		fmt.Printf("💬 \"%s\"\n", message)
	}
}

// Helper functions

func (ti *TerminalInterface) getServiceStatus(serviceName string, available bool) string {
	if available {
		return "✅ Active"
	}
	return "❌ Inactive"
}

func (ti *TerminalInterface) boolToStatus(b bool) string {
	if b {
		return "Healthy"
	}
	return "Unhealthy"
}

// IsRunning returns whether the terminal interface is running
func (ti *TerminalInterface) IsRunning() bool {
	return ti.running
}

// GetServices returns the runtime services
func (ti *TerminalInterface) GetServices() *runtime.RuntimeServices {
	return ti.services
}