package main

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/chromedp/chromedp"
)

func main() {
	if len(os.Args) < 3 {
		fmt.Println("Usage: test-browser-login <email> <password>")
		os.Exit(1)
	}

	email := os.Args[1]
	password := os.Args[2]

	// Set up Chrome options - VISIBLE browser for debugging
	opts := append(chromedp.DefaultExecAllocatorOptions[:],
		chromedp.Flag("headless", false), // NOT headless - we want to see it
		chromedp.Flag("disable-gpu", false),
	)
	
	// Create allocator context
	allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
	defer cancel()
	
	// Create context with timeout
	ctx, cancel := chromedp.NewContext(allocCtx)
	defer cancel()

	// Set a reasonable timeout for the entire login process
	ctx, cancel = context.WithTimeout(ctx, 120*time.Second)
	defer cancel()

	var token string

	// Run the browser automation tasks
	err := chromedp.Run(ctx,
		// Navigate to Kosmi
		chromedp.Navigate("https://app.kosmi.io"),
		
		// Wait for page to load completely
		chromedp.WaitReady("body"),
		chromedp.Sleep(2*time.Second),
		
		// Click Login button
		chromedp.ActionFunc(func(ctx context.Context) error {
			fmt.Println("Looking for Log in button...")
			var buttonTexts []string
			chromedp.Evaluate(`
				Array.from(document.querySelectorAll('button')).map(el => el.textContent.trim())
			`, &buttonTexts).Do(ctx)
			fmt.Printf("Found buttons: %v\n", buttonTexts)
			
			var found bool
			if err := chromedp.Evaluate(`
				(() => {
					const buttons = Array.from(document.querySelectorAll('button'));
					// Try both "Login" and "Log in"
					const btn = buttons.find(el => {
						const text = el.textContent.trim();
						return text === 'Login' || text === 'Log in';
					});
					if (btn) {
						btn.click();
						return true;
					}
					return false;
				})()
			`, &found).Do(ctx); err != nil {
				return err
			}
			if !found {
				return fmt.Errorf("Login button not found")
			}
			fmt.Println("✓ Clicked Login button")
			return nil
		}),
		
		// Wait for login modal
		chromedp.Sleep(3*time.Second),
		
		// Click "Login with Email" button
		chromedp.ActionFunc(func(ctx context.Context) error {
			fmt.Println("Looking for Login with Email button...")
			var buttonTexts []string
			chromedp.Evaluate(`
				Array.from(document.querySelectorAll('button')).map(el => el.textContent.trim())
			`, &buttonTexts).Do(ctx)
			fmt.Printf("Found buttons: %v\n", buttonTexts)
			
			var found bool
			if err := chromedp.Evaluate(`
				(() => {
					const btn = Array.from(document.querySelectorAll('button')).find(el => el.textContent.includes('Email'));
					if (btn) {
						btn.click();
						return true;
					}
					return false;
				})()
			`, &found).Do(ctx); err != nil {
				return err
			}
			if !found {
				return fmt.Errorf("Login with Email button not found")
			}
			fmt.Println("✓ Clicked Login with Email button")
			return nil
		}),
		
		// Wait for email form
		chromedp.Sleep(3*time.Second),
		chromedp.WaitVisible(`input[type="password"]`, chromedp.ByQuery),
		
		chromedp.ActionFunc(func(ctx context.Context) error {
			fmt.Println("Password input found, filling in email...")
			var inputTypes []string
			chromedp.Evaluate(`
				Array.from(document.querySelectorAll('input')).map(el => el.type + (el.placeholder ? ' ('+el.placeholder+')' : ''))
			`, &inputTypes).Do(ctx)
			fmt.Printf("Available inputs: %v\n", inputTypes)
			return nil
		}),
		
		// Click on the email input to focus it
		chromedp.Click(`input[placeholder*="Email"], input[placeholder*="Username"]`, chromedp.ByQuery),
		chromedp.Sleep(200*time.Millisecond),
		
		// Type email character by character
		chromedp.ActionFunc(func(ctx context.Context) error {
			fmt.Printf("Typing email: %s\n", email)
			return chromedp.SendKeys(`input[placeholder*="Email"], input[placeholder*="Username"]`, email, chromedp.ByQuery).Do(ctx)
		}),
		
		chromedp.Sleep(500*time.Millisecond),
		
		// Click on the password input to focus it
		chromedp.Click(`input[type="password"]`, chromedp.ByQuery),
		chromedp.Sleep(200*time.Millisecond),
		
		// Type password character by character
		chromedp.ActionFunc(func(ctx context.Context) error {
			fmt.Printf("Typing password (length: %d)...\n", len(password))
			return chromedp.SendKeys(`input[type="password"]`, password, chromedp.ByQuery).Do(ctx)
		}),
		
		// Verify password was filled correctly
		chromedp.ActionFunc(func(ctx context.Context) error {
			var actualLength int
			chromedp.Evaluate(`
				(() => {
					const passwordInput = document.querySelector('input[type="password"]');
					return passwordInput ? passwordInput.value.length : 0;
				})()
			`, &actualLength).Do(ctx)
			
			fmt.Printf("✓ Password filled (actual length in browser: %d, expected: %d)\n", actualLength, len(password))
			
			if actualLength != len(password) {
				return fmt.Errorf("password length mismatch: got %d, expected %d", actualLength, len(password))
			}
			return nil
		}),
		
		chromedp.Sleep(500*time.Millisecond),
		
		chromedp.ActionFunc(func(ctx context.Context) error {
			fmt.Println("Looking for submit button...")
			var buttonTexts []string
			chromedp.Evaluate(`
				Array.from(document.querySelectorAll('button')).map(el => el.textContent.trim() + (el.disabled ? ' (disabled)' : ''))
			`, &buttonTexts).Do(ctx)
			fmt.Printf("Submit buttons available: %v\n", buttonTexts)
			return nil
		}),
		
		// Wait a moment for form validation
		chromedp.Sleep(1*time.Second),
		
		// Click the login submit button (be very specific)
		chromedp.ActionFunc(func(ctx context.Context) error {
			fmt.Println("Attempting to click submit button...")
			var result string
			if err := chromedp.Evaluate(`
				(() => {
					const buttons = Array.from(document.querySelectorAll('button'));
					console.log('All buttons:', buttons.map(b => ({
						text: b.textContent.trim(),
						disabled: b.disabled,
						visible: b.offsetParent !== null
					})));
					
					// Find the submit button in the login form
					// It should be visible, enabled, and contain "Login" but not be the main nav button
					const submitBtn = buttons.find(el => {
						const text = el.textContent.trim();
						const isLoginBtn = text === 'Login' || text.startsWith('Login');
						const isEnabled = !el.disabled;
						const isVisible = el.offsetParent !== null;
						const isInForm = el.closest('form') !== null || el.closest('[role="dialog"]') !== null;
						
						return isLoginBtn && isEnabled && isVisible && isInForm;
					});
					
					if (submitBtn) {
						console.log('Found submit button:', submitBtn.textContent.trim());
						submitBtn.click();
						return 'CLICKED: ' + submitBtn.textContent.trim();
					}
					
					return 'NOT_FOUND';
				})()
			`, &result).Do(ctx); err != nil {
				return err
			}
			
			fmt.Printf("Submit button result: %s\n", result)
			
			if result == "NOT_FOUND" {
				return fmt.Errorf("Login submit button not found or not clickable")
			}
			
			fmt.Println("✓ Clicked submit button")
			return nil
		}),
		
		// Wait for login to complete
		chromedp.Sleep(5*time.Second),
		
		// Check for errors
		chromedp.ActionFunc(func(ctx context.Context) error {
			var errorText string
			chromedp.Evaluate(`
				(() => {
					const errorEl = document.querySelector('[role="alert"], .error, .alert-error');
					return errorEl ? errorEl.textContent : '';
				})()
			`, &errorText).Do(ctx)
			
			if errorText != "" {
				fmt.Printf("❌ Login error: %s\n", errorText)
				return fmt.Errorf("login failed: %s", errorText)
			}
			
			fmt.Println("✓ No error messages")
			return nil
		}),
		
		// Extract token from localStorage
		chromedp.Evaluate(`localStorage.getItem('token')`, &token),
		
		// Check token details
		chromedp.ActionFunc(func(ctx context.Context) error {
			var userInfo string
			chromedp.Evaluate(`
				(() => {
					try {
						const token = localStorage.getItem('token');
						if (!token) return 'NO_TOKEN';
						
						const parts = token.split('.');
						if (parts.length !== 3) return 'INVALID_TOKEN';
						
						const payload = JSON.parse(atob(parts[1]));
						return JSON.stringify(payload, null, 2);
					} catch (e) {
						return 'ERROR: ' + e.message;
					}
				})()
			`, &userInfo).Do(ctx)
			
			fmt.Printf("\n=== Token Payload ===\n%s\n", userInfo)
			return nil
		}),
		
		// Keep browser open for inspection
		chromedp.ActionFunc(func(ctx context.Context) error {
			fmt.Println("\n✓ Login complete! Browser will stay open for 30 seconds for inspection...")
			return nil
		}),
		chromedp.Sleep(30*time.Second),
	)

	if err != nil {
		fmt.Printf("\n❌ Error: %v\n", err)
		os.Exit(1)
	}

	if token == "" {
		fmt.Println("\n❌ No token found in localStorage")
		os.Exit(1)
	}

	fmt.Printf("\n✅ Token obtained (length: %d)\n", len(token))
	fmt.Printf("First 50 chars: %s...\n", token[:min(50, len(token))])
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

