package main

import (
	"log"
	"os"
	"os/signal"
	"time"

	"github.com/playwright-community/playwright-go"
)

const (
	roomURL = "https://app.kosmi.io/room/@hyperspaceout"
)

func main() {
	log.Println("🔍 Starting Kosmi WebSocket Monitor")
	log.Printf("📡 Room URL: %s", roomURL)
	log.Println("This will capture ALL WebSocket traffic from the browser...")
	log.Println()

	// Set up interrupt handler
	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt)

	// Launch Playwright
	pw, err := playwright.Run()
	if err != nil {
		log.Fatalf("Failed to start Playwright: %v", err)
	}
	defer pw.Stop()

	// Launch browser
	browser, err := pw.Chromium.Launch(playwright.BrowserTypeLaunchOptions{
		Headless: playwright.Bool(false), // Keep visible so we can see what's happening
	})
	if err != nil {
		log.Fatalf("Failed to launch browser: %v", err)
	}
	defer browser.Close()

	// Create context
	context, err := browser.NewContext(playwright.BrowserNewContextOptions{
		UserAgent: playwright.String("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"),
	})
	if err != nil {
		log.Fatalf("Failed to create context: %v", err)
	}

	// Create page
	page, err := context.NewPage()
	if err != nil {
		log.Fatalf("Failed to create page: %v", err)
	}

	// Inject WebSocket monitoring script BEFORE navigation
	log.Println("📝 Injecting WebSocket monitoring script...")
	if err := page.AddInitScript(playwright.Script{
		Content: playwright.String(`
			(function() {
				const OriginalWebSocket = window.WebSocket;
				let messageCount = 0;
				
				window.WebSocket = function(url, protocols) {
					console.log('🔌 [WS MONITOR] WebSocket created:', url, 'protocols:', protocols);
					const socket = new OriginalWebSocket(url, protocols);
					
					socket.addEventListener('open', (event) => {
						console.log('✅ [WS MONITOR] WebSocket OPENED');
					});
					
					socket.addEventListener('close', (event) => {
						console.log('🔴 [WS MONITOR] WebSocket CLOSED:', event.code, event.reason);
					});
					
					socket.addEventListener('error', (event) => {
						console.error('❌ [WS MONITOR] WebSocket ERROR:', event);
					});
					
					// Intercept outgoing messages
					const originalSend = socket.send;
					socket.send = function(data) {
						messageCount++;
						console.log('📤 [WS MONITOR] SEND #' + messageCount + ':', data);
						try {
							const parsed = JSON.parse(data);
							console.log('   Type:', parsed.type, 'ID:', parsed.id);
							if (parsed.payload) {
								console.log('   Payload:', JSON.stringify(parsed.payload, null, 2));
							}
						} catch (e) {
							// Not JSON
						}
						return originalSend.call(this, data);
					};
					
					// Intercept incoming messages
					socket.addEventListener('message', (event) => {
						messageCount++;
						console.log('📥 [WS MONITOR] RECEIVE #' + messageCount + ':', event.data);
						try {
							const parsed = JSON.parse(event.data);
							console.log('   Type:', parsed.type, 'ID:', parsed.id);
							if (parsed.payload) {
								console.log('   Payload:', JSON.stringify(parsed.payload, null, 2));
							}
						} catch (e) {
							// Not JSON
						}
					});
					
					return socket;
				};
				
				// Preserve WebSocket properties
				window.WebSocket.prototype = OriginalWebSocket.prototype;
				window.WebSocket.CONNECTING = OriginalWebSocket.CONNECTING;
				window.WebSocket.OPEN = OriginalWebSocket.OPEN;
				window.WebSocket.CLOSING = OriginalWebSocket.CLOSING;
				window.WebSocket.CLOSED = OriginalWebSocket.CLOSED;
			})();
		`),
	}); err != nil {
		log.Fatalf("Failed to inject script: %v", err)
	}

	// Listen to console messages
	page.On("console", func(msg playwright.ConsoleMessage) {
		text := msg.Text()
		msgType := msg.Type()
		
		// Format the output nicely
		prefix := "💬"
		switch msgType {
		case "log":
			prefix = "📋"
		case "error":
			prefix = "❌"
		case "warning":
			prefix = "⚠️"
		case "info":
			prefix = "ℹ️"
		}
		
		log.Printf("%s [BROWSER %s] %s", prefix, msgType, text)
	})

	// Navigate to room
	log.Printf("🌐 Navigating to %s...", roomURL)
	if _, err := page.Goto(roomURL, playwright.PageGotoOptions{
		WaitUntil: playwright.WaitUntilStateDomcontentloaded,
	}); err != nil {
		log.Fatalf("Failed to navigate: %v", err)
	}

	log.Println("✅ Page loaded! Monitoring WebSocket traffic...")
	log.Println("Press Ctrl+C to stop monitoring")
	log.Println()

	// Wait for a bit to see initial traffic
	time.Sleep(5 * time.Second)

	// Try to send a test message
	log.Println("\n📝 Attempting to send a test message via UI...")
	result, err := page.Evaluate(`
		(async function() {
			// Find the chat input
			const textareas = document.querySelectorAll('textarea');
			for (let ta of textareas) {
				if (ta.offsetParent !== null) {
					ta.value = 'Test message from monitor script 🔍';
					ta.dispatchEvent(new Event('input', { bubbles: true }));
					ta.dispatchEvent(new Event('change', { bubbles: true }));
					ta.focus();
					
					// Wait a bit
					await new Promise(resolve => setTimeout(resolve, 100));
					
					// Try to find and click send button
					const buttons = document.querySelectorAll('button');
					for (let btn of buttons) {
						if (btn.textContent.toLowerCase().includes('send') || 
						    btn.getAttribute('aria-label')?.toLowerCase().includes('send')) {
							btn.click();
							return { success: true, method: 'button' };
						}
					}
					
					// If no button, press Enter
					const enterEvent = new KeyboardEvent('keydown', {
						key: 'Enter',
						code: 'Enter',
						keyCode: 13,
						which: 13,
						bubbles: true,
						cancelable: true
					});
					ta.dispatchEvent(enterEvent);
					return { success: true, method: 'enter' };
				}
			}
			return { success: false, error: 'No input found' };
		})();
	`)
	
	if err != nil {
		log.Printf("❌ Failed to send test message: %v", err)
	} else {
		resultMap := result.(map[string]interface{})
		if success, ok := resultMap["success"].(bool); ok && success {
			method := resultMap["method"].(string)
			log.Printf("✅ Test message sent via %s", method)
			log.Println("📊 Check the console output above to see the WebSocket traffic!")
		} else {
			log.Printf("❌ Failed to send: %v", resultMap["error"])
		}
	}

	// Keep monitoring
	log.Println("\n⏳ Continuing to monitor... Press Ctrl+C to stop")
	
	// Wait for interrupt
	<-interrupt
	log.Println("\n👋 Stopping monitor...")
}

