package main

import (
	"flag"
	"fmt"
	"os"
	"sort"

	"git.teamworkapps.com/shortcut/cremote/client"
)

const Version = "2.2.1"

var (
	// Global flags
	daemonHost = flag.String("host", "localhost", "Daemon host")
	daemonPort = flag.Int("port", 8989, "Daemon port")
)

func main() {
	// Define subcommands
	openTabCmd := flag.NewFlagSet("open-tab", flag.ExitOnError)
	loadURLCmd := flag.NewFlagSet("load-url", flag.ExitOnError)
	fillFormCmd := flag.NewFlagSet("fill-form", flag.ExitOnError)
	uploadFileCmd := flag.NewFlagSet("upload-file", flag.ExitOnError)
	submitFormCmd := flag.NewFlagSet("submit-form", flag.ExitOnError)
	getSourceCmd := flag.NewFlagSet("get-source", flag.ExitOnError)
	getElementCmd := flag.NewFlagSet("get-element", flag.ExitOnError)
	clickElementCmd := flag.NewFlagSet("click-element", flag.ExitOnError)
	closeTabCmd := flag.NewFlagSet("close-tab", flag.ExitOnError)
	waitNavCmd := flag.NewFlagSet("wait-navigation", flag.ExitOnError)
	evalJsCmd := flag.NewFlagSet("eval-js", flag.ExitOnError)
	switchIframeCmd := flag.NewFlagSet("switch-iframe", flag.ExitOnError)
	switchMainCmd := flag.NewFlagSet("switch-main", flag.ExitOnError)
	screenshotCmd := flag.NewFlagSet("screenshot", flag.ExitOnError)
	statusCmd := flag.NewFlagSet("status", flag.ExitOnError)
	listTabsCmd := flag.NewFlagSet("list-tabs", flag.ExitOnError)
	disableCacheCmd := flag.NewFlagSet("disable-cache", flag.ExitOnError)
	enableCacheCmd := flag.NewFlagSet("enable-cache", flag.ExitOnError)
	clearCacheCmd := flag.NewFlagSet("clear-cache", flag.ExitOnError)
	clearAllSiteDataCmd := flag.NewFlagSet("clear-all-site-data", flag.ExitOnError)
	clearCookiesCmd := flag.NewFlagSet("clear-cookies", flag.ExitOnError)
	clearStorageCmd := flag.NewFlagSet("clear-storage", flag.ExitOnError)
	dragAndDropCmd := flag.NewFlagSet("drag-and-drop", flag.ExitOnError)
	dragAndDropCoordinatesCmd := flag.NewFlagSet("drag-and-drop-coordinates", flag.ExitOnError)
	dragAndDropOffsetCmd := flag.NewFlagSet("drag-and-drop-offset", flag.ExitOnError)

	// Advanced mouse operations
	rightClickCmd := flag.NewFlagSet("right-click", flag.ExitOnError)
	doubleClickCmd := flag.NewFlagSet("double-click", flag.ExitOnError)
	middleClickCmd := flag.NewFlagSet("middle-click", flag.ExitOnError)
	hoverCmd := flag.NewFlagSet("hover", flag.ExitOnError)
	mouseMoveCmd := flag.NewFlagSet("mouse-move", flag.ExitOnError)
	scrollWheelCmd := flag.NewFlagSet("scroll-wheel", flag.ExitOnError)

	// Keyboard operations
	keyCombinationCmd := flag.NewFlagSet("key-combination", flag.ExitOnError)
	specialKeyCmd := flag.NewFlagSet("special-key", flag.ExitOnError)
	modifierClickCmd := flag.NewFlagSet("modifier-click", flag.ExitOnError)

	// Note: Touch operations and advanced scrolling/text operations are planned for future implementation
	// touchTapCmd := flag.NewFlagSet("touch-tap", flag.ExitOnError)
	// touchLongPressCmd := flag.NewFlagSet("touch-long-press", flag.ExitOnError)
	// touchSwipeCmd := flag.NewFlagSet("touch-swipe", flag.ExitOnError)
	// pinchZoomCmd := flag.NewFlagSet("pinch-zoom", flag.ExitOnError)
	// scrollElementCmd := flag.NewFlagSet("scroll-element", flag.ExitOnError)
	// scrollToCoordinatesCmd := flag.NewFlagSet("scroll-to-coordinates", flag.ExitOnError)
	// selectTextCmd := flag.NewFlagSet("select-text", flag.ExitOnError)
	// selectAllTextCmd := flag.NewFlagSet("select-all-text", flag.ExitOnError)

	// Define flags for each subcommand
	// open-tab flags
	openTabTimeout := openTabCmd.Int("timeout", 30, "Timeout in seconds for opening the tab")
	openTabHost := openTabCmd.String("host", "localhost", "Daemon host")
	openTabPort := openTabCmd.Int("port", 8989, "Daemon port")

	// load-url flags
	loadURLTabID := loadURLCmd.String("tab", "", "Tab ID to load URL in (optional, uses current tab if not specified)")
	loadURLTarget := loadURLCmd.String("url", "", "URL to load")
	loadURLTimeout := loadURLCmd.Int("timeout", 30, "Timeout in seconds for loading the URL")
	loadURLHost := loadURLCmd.String("host", "localhost", "Daemon host")
	loadURLPort := loadURLCmd.Int("port", 8989, "Daemon port")

	// fill-form flags
	fillFormTabID := fillFormCmd.String("tab", "", "Tab ID to fill form in (optional, uses current tab if not specified)")
	fillFormSelector := fillFormCmd.String("selector", "", "CSS selector for the input field")
	fillFormValue := fillFormCmd.String("value", "", "Value to fill in the form field")
	fillFormTimeout := fillFormCmd.Int("timeout", 5, "Timeout in seconds for the fill operation")
	fillFormHost := fillFormCmd.String("host", "localhost", "Daemon host")
	fillFormPort := fillFormCmd.Int("port", 8989, "Daemon port")

	// upload-file flags
	uploadFileTabID := uploadFileCmd.String("tab", "", "Tab ID to upload file in (optional, uses current tab if not specified)")
	uploadFileSelector := uploadFileCmd.String("selector", "", "CSS selector for the file input")
	uploadFilePath := uploadFileCmd.String("file", "", "Path to the file to upload")
	uploadFileTimeout := uploadFileCmd.Int("timeout", 5, "Timeout in seconds for the upload operation")
	uploadFileHost := uploadFileCmd.String("host", "localhost", "Daemon host")
	uploadFilePort := uploadFileCmd.Int("port", 8989, "Daemon port")

	// submit-form flags
	submitFormTabID := submitFormCmd.String("tab", "", "Tab ID to submit form in (optional, uses current tab if not specified)")
	submitFormSelector := submitFormCmd.String("selector", "", "CSS selector for the form")
	submitFormTimeout := submitFormCmd.Int("timeout", 5, "Timeout in seconds for the submit operation")
	submitFormHost := submitFormCmd.String("host", "localhost", "Daemon host")
	submitFormPort := submitFormCmd.Int("port", 8989, "Daemon port")

	// get-source flags
	getSourceTabID := getSourceCmd.String("tab", "", "Tab ID to get source from (optional, uses current tab if not specified)")
	getSourceTimeout := getSourceCmd.Int("timeout", 5, "Timeout in seconds for getting the page source")
	getSourceHost := getSourceCmd.String("host", "localhost", "Daemon host")
	getSourcePort := getSourceCmd.Int("port", 8989, "Daemon port")

	// get-element flags
	getElementTabID := getElementCmd.String("tab", "", "Tab ID to get element from (optional, uses current tab if not specified)")
	getElementSelector := getElementCmd.String("selector", "", "CSS selector for the element")
	getElementTimeout := getElementCmd.Int("timeout", 5, "Timeout in seconds for finding the element")
	getElementHost := getElementCmd.String("host", "localhost", "Daemon host")
	getElementPort := getElementCmd.Int("port", 8989, "Daemon port")

	// click-element flags
	clickElementTabID := clickElementCmd.String("tab", "", "Tab ID to click element in (optional, uses current tab if not specified)")
	clickElementSelector := clickElementCmd.String("selector", "", "CSS selector for the element to click")
	clickElementTimeout := clickElementCmd.Int("timeout", 5, "Timeout in seconds for the click operation")
	clickElementHost := clickElementCmd.String("host", "localhost", "Daemon host")
	clickElementPort := clickElementCmd.Int("port", 8989, "Daemon port")

	// close-tab flags
	closeTabID := closeTabCmd.String("tab", "", "Tab ID to close (optional, uses current tab if not specified)")
	closeTabTimeout := closeTabCmd.Int("timeout", 5, "Timeout in seconds for closing the tab")
	closeTabHost := closeTabCmd.String("host", "localhost", "Daemon host")
	closeTabPort := closeTabCmd.Int("port", 8989, "Daemon port")

	// wait-navigation flags
	waitNavTabID := waitNavCmd.String("tab", "", "Tab ID to wait for navigation (optional, uses current tab if not specified)")
	waitNavTimeout := waitNavCmd.Int("timeout", 5, "Timeout in seconds")
	waitNavHost := waitNavCmd.String("host", "localhost", "Daemon host")
	waitNavPort := waitNavCmd.Int("port", 8989, "Daemon port")

	// eval-js flags
	evalJsTabID := evalJsCmd.String("tab", "", "Tab ID to execute JavaScript in (optional, uses current tab if not specified)")
	evalJsCode := evalJsCmd.String("code", "", "JavaScript code to execute")
	evalJsTimeout := evalJsCmd.Int("timeout", 5, "Timeout in seconds for JavaScript execution")
	evalJsHost := evalJsCmd.String("host", "localhost", "Daemon host")
	evalJsPort := evalJsCmd.Int("port", 8989, "Daemon port")

	// switch-iframe flags
	switchIframeTabID := switchIframeCmd.String("tab", "", "Tab ID to switch iframe context in (optional, uses current tab if not specified)")
	switchIframeSelector := switchIframeCmd.String("selector", "", "CSS selector for the iframe element")
	switchIframeTimeout := switchIframeCmd.Int("timeout", 5, "Timeout in seconds for iframe switching")
	switchIframeHost := switchIframeCmd.String("host", "localhost", "Daemon host")
	switchIframePort := switchIframeCmd.Int("port", 8989, "Daemon port")

	// switch-main flags
	switchMainTabID := switchMainCmd.String("tab", "", "Tab ID to switch back to main context (optional, uses current tab if not specified)")
	switchMainTimeout := switchMainCmd.Int("timeout", 5, "Timeout in seconds for switching back to main context")
	switchMainHost := switchMainCmd.String("host", "localhost", "Daemon host")
	switchMainPort := switchMainCmd.Int("port", 8989, "Daemon port")

	// screenshot flags
	screenshotTabID := screenshotCmd.String("tab", "", "Tab ID to take screenshot of (optional, uses current tab if not specified)")
	screenshotOutput := screenshotCmd.String("output", "", "Output file path for the screenshot (PNG format)")
	screenshotFullPage := screenshotCmd.Bool("full-page", false, "Capture full page screenshot (default: viewport only)")
	screenshotTimeout := screenshotCmd.Int("timeout", 5, "Timeout in seconds for taking the screenshot")
	screenshotHost := screenshotCmd.String("host", "localhost", "Daemon host")
	screenshotPort := screenshotCmd.Int("port", 8989, "Daemon port")

	// status flags
	statusHost := statusCmd.String("host", "localhost", "Daemon host")
	statusPort := statusCmd.Int("port", 8989, "Daemon port")

	// list-tabs flags
	listTabsHost := listTabsCmd.String("host", "localhost", "Daemon host")
	listTabsPort := listTabsCmd.Int("port", 8989, "Daemon port")

	// disable-cache flags
	disableCacheTabID := disableCacheCmd.String("tab", "", "Tab ID to disable cache for (optional, uses current tab if not specified)")
	disableCacheTimeout := disableCacheCmd.Int("timeout", 5, "Timeout in seconds for disabling cache")
	disableCacheHost := disableCacheCmd.String("host", "localhost", "Daemon host")
	disableCachePort := disableCacheCmd.Int("port", 8989, "Daemon port")

	// enable-cache flags
	enableCacheTabID := enableCacheCmd.String("tab", "", "Tab ID to enable cache for (optional, uses current tab if not specified)")
	enableCacheTimeout := enableCacheCmd.Int("timeout", 5, "Timeout in seconds for enabling cache")
	enableCacheHost := enableCacheCmd.String("host", "localhost", "Daemon host")
	enableCachePort := enableCacheCmd.Int("port", 8989, "Daemon port")

	// clear-cache flags
	clearCacheTabID := clearCacheCmd.String("tab", "", "Tab ID to clear cache for (optional, uses current tab if not specified)")
	clearCacheTimeout := clearCacheCmd.Int("timeout", 5, "Timeout in seconds for clearing cache")
	clearCacheHost := clearCacheCmd.String("host", "localhost", "Daemon host")
	clearCachePort := clearCacheCmd.Int("port", 8989, "Daemon port")

	// clear-all-site-data flags
	clearAllSiteDataTabID := clearAllSiteDataCmd.String("tab", "", "Tab ID to clear all site data for (optional, uses current tab if not specified)")
	clearAllSiteDataTimeout := clearAllSiteDataCmd.Int("timeout", 5, "Timeout in seconds for clearing all site data")
	clearAllSiteDataHost := clearAllSiteDataCmd.String("host", "localhost", "Daemon host")
	clearAllSiteDataPort := clearAllSiteDataCmd.Int("port", 8989, "Daemon port")

	// clear-cookies flags
	clearCookiesTabID := clearCookiesCmd.String("tab", "", "Tab ID to clear cookies for (optional, uses current tab if not specified)")
	clearCookiesTimeout := clearCookiesCmd.Int("timeout", 5, "Timeout in seconds for clearing cookies")
	clearCookiesHost := clearCookiesCmd.String("host", "localhost", "Daemon host")
	clearCookiesPort := clearCookiesCmd.Int("port", 8989, "Daemon port")

	// clear-storage flags
	clearStorageTabID := clearStorageCmd.String("tab", "", "Tab ID to clear storage for (optional, uses current tab if not specified)")
	clearStorageTimeout := clearStorageCmd.Int("timeout", 5, "Timeout in seconds for clearing storage")
	clearStorageHost := clearStorageCmd.String("host", "localhost", "Daemon host")
	clearStoragePort := clearStorageCmd.Int("port", 8989, "Daemon port")

	// drag-and-drop flags
	dragAndDropTabID := dragAndDropCmd.String("tab", "", "Tab ID to perform drag and drop on (optional, uses current tab if not specified)")
	dragAndDropSource := dragAndDropCmd.String("source", "", "CSS selector for the source element to drag")
	dragAndDropTarget := dragAndDropCmd.String("target", "", "CSS selector for the target element to drop on")
	dragAndDropTimeout := dragAndDropCmd.Int("timeout", 5, "Timeout in seconds for drag and drop operation")
	dragAndDropHost := dragAndDropCmd.String("host", "localhost", "Daemon host")
	dragAndDropPort := dragAndDropCmd.Int("port", 8989, "Daemon port")

	// drag-and-drop-coordinates flags
	dragAndDropCoordinatesTabID := dragAndDropCoordinatesCmd.String("tab", "", "Tab ID to perform drag and drop on (optional, uses current tab if not specified)")
	dragAndDropCoordinatesSource := dragAndDropCoordinatesCmd.String("source", "", "CSS selector for the source element to drag")
	dragAndDropCoordinatesX := dragAndDropCoordinatesCmd.Int("x", 0, "Target X coordinate")
	dragAndDropCoordinatesY := dragAndDropCoordinatesCmd.Int("y", 0, "Target Y coordinate")
	dragAndDropCoordinatesTimeout := dragAndDropCoordinatesCmd.Int("timeout", 5, "Timeout in seconds for drag and drop operation")
	dragAndDropCoordinatesHost := dragAndDropCoordinatesCmd.String("host", "localhost", "Daemon host")
	dragAndDropCoordinatesPort := dragAndDropCoordinatesCmd.Int("port", 8989, "Daemon port")

	// drag-and-drop-offset flags
	dragAndDropOffsetTabID := dragAndDropOffsetCmd.String("tab", "", "Tab ID to perform drag and drop on (optional, uses current tab if not specified)")
	dragAndDropOffsetSource := dragAndDropOffsetCmd.String("source", "", "CSS selector for the source element to drag")
	dragAndDropOffsetX := dragAndDropOffsetCmd.Int("offset-x", 0, "Horizontal offset in pixels")
	dragAndDropOffsetY := dragAndDropOffsetCmd.Int("offset-y", 0, "Vertical offset in pixels")
	dragAndDropOffsetTimeout := dragAndDropOffsetCmd.Int("timeout", 5, "Timeout in seconds for drag and drop operation")
	dragAndDropOffsetHost := dragAndDropOffsetCmd.String("host", "localhost", "Daemon host")
	dragAndDropOffsetPort := dragAndDropOffsetCmd.Int("port", 8989, "Daemon port")

	// right-click flags
	rightClickTabID := rightClickCmd.String("tab", "", "Tab ID to perform right-click on (optional, uses current tab if not specified)")
	rightClickSelector := rightClickCmd.String("selector", "", "CSS selector for the element to right-click")
	rightClickTimeout := rightClickCmd.Int("timeout", 5, "Timeout in seconds for right-click operation")
	rightClickHost := rightClickCmd.String("host", "localhost", "Daemon host")
	rightClickPort := rightClickCmd.Int("port", 8989, "Daemon port")

	// double-click flags
	doubleClickTabID := doubleClickCmd.String("tab", "", "Tab ID to perform double-click on (optional, uses current tab if not specified)")
	doubleClickSelector := doubleClickCmd.String("selector", "", "CSS selector for the element to double-click")
	doubleClickTimeout := doubleClickCmd.Int("timeout", 5, "Timeout in seconds for double-click operation")
	doubleClickHost := doubleClickCmd.String("host", "localhost", "Daemon host")
	doubleClickPort := doubleClickCmd.Int("port", 8989, "Daemon port")

	// middle-click flags
	middleClickTabID := middleClickCmd.String("tab", "", "Tab ID to perform middle-click on (optional, uses current tab if not specified)")
	middleClickSelector := middleClickCmd.String("selector", "", "CSS selector for the element to middle-click")
	middleClickTimeout := middleClickCmd.Int("timeout", 5, "Timeout in seconds for middle-click operation")
	middleClickHost := middleClickCmd.String("host", "localhost", "Daemon host")
	middleClickPort := middleClickCmd.Int("port", 8989, "Daemon port")

	// hover flags
	hoverTabID := hoverCmd.String("tab", "", "Tab ID to perform hover on (optional, uses current tab if not specified)")
	hoverSelector := hoverCmd.String("selector", "", "CSS selector for the element to hover over")
	hoverTimeout := hoverCmd.Int("timeout", 5, "Timeout in seconds for hover operation")
	hoverHost := hoverCmd.String("host", "localhost", "Daemon host")
	hoverPort := hoverCmd.Int("port", 8989, "Daemon port")

	// mouse-move flags
	mouseMoveTabID := mouseMoveCmd.String("tab", "", "Tab ID to move mouse on (optional, uses current tab if not specified)")
	mouseMoveX := mouseMoveCmd.Int("x", 0, "X coordinate to move mouse to")
	mouseMoveY := mouseMoveCmd.Int("y", 0, "Y coordinate to move mouse to")
	mouseMoveTimeout := mouseMoveCmd.Int("timeout", 5, "Timeout in seconds for mouse move operation")
	mouseMoveHost := mouseMoveCmd.String("host", "localhost", "Daemon host")
	mouseMovePort := mouseMoveCmd.Int("port", 8989, "Daemon port")

	// scroll-wheel flags
	scrollWheelTabID := scrollWheelCmd.String("tab", "", "Tab ID to scroll on (optional, uses current tab if not specified)")
	scrollWheelX := scrollWheelCmd.Int("x", 0, "X coordinate for scroll wheel")
	scrollWheelY := scrollWheelCmd.Int("y", 0, "Y coordinate for scroll wheel")
	scrollWheelDeltaX := scrollWheelCmd.Int("delta-x", 0, "Horizontal scroll delta (negative = left, positive = right)")
	scrollWheelDeltaY := scrollWheelCmd.Int("delta-y", 0, "Vertical scroll delta (negative = up, positive = down)")
	scrollWheelTimeout := scrollWheelCmd.Int("timeout", 5, "Timeout in seconds for scroll wheel operation")
	scrollWheelHost := scrollWheelCmd.String("host", "localhost", "Daemon host")
	scrollWheelPort := scrollWheelCmd.Int("port", 8989, "Daemon port")

	// key-combination flags
	keyCombinationTabID := keyCombinationCmd.String("tab", "", "Tab ID to send key combination to (optional, uses current tab if not specified)")
	keyCombinationKeys := keyCombinationCmd.String("keys", "", "Key combination to send (e.g., 'Ctrl+C', 'Alt+Tab', 'Shift+Enter')")
	keyCombinationTimeout := keyCombinationCmd.Int("timeout", 5, "Timeout in seconds for key combination operation")
	keyCombinationHost := keyCombinationCmd.String("host", "localhost", "Daemon host")
	keyCombinationPort := keyCombinationCmd.Int("port", 8989, "Daemon port")

	// special-key flags
	specialKeyTabID := specialKeyCmd.String("tab", "", "Tab ID to send special key to (optional, uses current tab if not specified)")
	specialKeyKey := specialKeyCmd.String("key", "", "Special key to send (e.g., 'Enter', 'Escape', 'Tab', 'F1', 'ArrowUp')")
	specialKeyTimeout := specialKeyCmd.Int("timeout", 5, "Timeout in seconds for special key operation")
	specialKeyHost := specialKeyCmd.String("host", "localhost", "Daemon host")
	specialKeyPort := specialKeyCmd.Int("port", 8989, "Daemon port")

	// modifier-click flags
	modifierClickTabID := modifierClickCmd.String("tab", "", "Tab ID to perform modifier click on (optional, uses current tab if not specified)")
	modifierClickSelector := modifierClickCmd.String("selector", "", "CSS selector for the element to click")
	modifierClickModifiers := modifierClickCmd.String("modifiers", "", "Modifier keys (e.g., 'Ctrl', 'Shift', 'Alt', 'Ctrl+Shift')")
	modifierClickTimeout := modifierClickCmd.Int("timeout", 5, "Timeout in seconds for modifier click operation")
	modifierClickHost := modifierClickCmd.String("host", "localhost", "Daemon host")
	modifierClickPort := modifierClickCmd.Int("port", 8989, "Daemon port")

	// Note: Touch operations flags will be added when the functionality is implemented
	// touchTapTabID := touchTapCmd.String("tab", "", "Tab ID to perform touch tap on (optional, uses current tab if not specified)")
	// ... (other touch operation flags)

	// Check if a subcommand is provided
	if len(os.Args) < 2 {
		printUsage()
		os.Exit(1)
	}

	// Parse the appropriate subcommand
	switch os.Args[1] {
	case "version":
		fmt.Printf("cremote CLI version %s\n", Version)

		// Also get daemon version if possible
		c := client.NewClient("localhost", 8989)
		daemonVersion, err := c.GetVersion()
		if err != nil {
			fmt.Printf("Daemon: Unable to connect (%v)\n", err)
		} else {
			fmt.Printf("Daemon version %s\n", daemonVersion)
		}
		return

	case "open-tab":
		openTabCmd.Parse(os.Args[2:])

		// Create a client
		c := client.NewClient(*openTabHost, *openTabPort)

		// Open a new tab
		tabID, err := c.OpenTab(*openTabTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		// Print the tab ID
		fmt.Println(tabID)

	case "load-url":
		loadURLCmd.Parse(os.Args[2:])
		if *loadURLTarget == "" {
			fmt.Println("Error: url flag is required")
			loadURLCmd.PrintDefaults()
			os.Exit(1)
		}

		// Create a client
		c := client.NewClient(*loadURLHost, *loadURLPort)

		// Load the URL
		err := c.LoadURL(*loadURLTabID, *loadURLTarget, *loadURLTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("URL loaded successfully")

	case "fill-form":
		fillFormCmd.Parse(os.Args[2:])
		if *fillFormSelector == "" || *fillFormValue == "" {
			fmt.Println("Error: selector and value flags are required")
			fillFormCmd.PrintDefaults()
			os.Exit(1)
		}

		// Create a client
		c := client.NewClient(*fillFormHost, *fillFormPort)

		// Fill the form field
		err := c.FillFormField(*fillFormTabID, *fillFormSelector, *fillFormValue, *fillFormTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("Form field filled successfully")

	case "upload-file":
		uploadFileCmd.Parse(os.Args[2:])
		if *uploadFileSelector == "" || *uploadFilePath == "" {
			fmt.Println("Error: selector and file flags are required")
			uploadFileCmd.PrintDefaults()
			os.Exit(1)
		}

		// Create a client
		c := client.NewClient(*uploadFileHost, *uploadFilePort)

		// Check if the local file exists
		if _, err := os.Stat(*uploadFilePath); os.IsNotExist(err) {
			fmt.Fprintf(os.Stderr, "Error: Local file does not exist: %s\n", *uploadFilePath)
			os.Exit(1)
		}

		// First, transfer the file to the daemon container
		fmt.Printf("Transferring file to daemon container: %s\n", *uploadFilePath)
		containerPath, err := c.UploadFileToContainer(*uploadFilePath, "")
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error transferring file to container: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("File transferred to container: %s\n", containerPath)

		// Then upload the file to the web form using the container path
		err = c.UploadFile(*uploadFileTabID, *uploadFileSelector, containerPath, *uploadFileTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error uploading file to web form: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("File uploaded to web form successfully")

	case "submit-form":
		submitFormCmd.Parse(os.Args[2:])
		if *submitFormSelector == "" {
			fmt.Println("Error: selector flag is required")
			submitFormCmd.PrintDefaults()
			os.Exit(1)
		}

		// Create a client
		c := client.NewClient(*submitFormHost, *submitFormPort)

		// Submit the form
		err := c.SubmitForm(*submitFormTabID, *submitFormSelector, *submitFormTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("Form submitted successfully")

	case "get-source":
		getSourceCmd.Parse(os.Args[2:])

		// Create a client
		c := client.NewClient(*getSourceHost, *getSourcePort)

		// Get the page source
		source, err := c.GetPageSource(*getSourceTabID, *getSourceTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		// Print the source
		fmt.Println(source)

	case "get-element":
		getElementCmd.Parse(os.Args[2:])
		if *getElementSelector == "" {
			fmt.Println("Error: selector flag is required")
			getElementCmd.PrintDefaults()
			os.Exit(1)
		}

		// Create a client
		c := client.NewClient(*getElementHost, *getElementPort)

		// Get the element HTML
		html, err := c.GetElementHTML(*getElementTabID, *getElementSelector, *getElementTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		// Print the HTML
		fmt.Println(html)

	case "click-element":
		clickElementCmd.Parse(os.Args[2:])
		if *clickElementSelector == "" {
			fmt.Println("Error: selector flag is required")
			clickElementCmd.PrintDefaults()
			os.Exit(1)
		}

		// Create a client
		c := client.NewClient(*clickElementHost, *clickElementPort)

		// Click the element
		err := c.ClickElement(*clickElementTabID, *clickElementSelector, *clickElementTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("Element clicked successfully")

	case "close-tab":
		closeTabCmd.Parse(os.Args[2:])

		// Create a client
		c := client.NewClient(*closeTabHost, *closeTabPort)

		// Close the tab
		err := c.CloseTab(*closeTabID, *closeTabTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("Tab closed successfully")

	case "wait-navigation":
		waitNavCmd.Parse(os.Args[2:])

		// Create a client
		c := client.NewClient(*waitNavHost, *waitNavPort)

		// Wait for navigation
		err := c.WaitNavigation(*waitNavTabID, *waitNavTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("Navigation completed")

	case "eval-js":
		evalJsCmd.Parse(os.Args[2:])
		if *evalJsCode == "" {
			fmt.Println("Error: code flag is required")
			evalJsCmd.PrintDefaults()
			os.Exit(1)
		}

		// Create a client
		c := client.NewClient(*evalJsHost, *evalJsPort)

		// Execute JavaScript
		result, err := c.EvalJS(*evalJsTabID, *evalJsCode, *evalJsTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		// Print the result if there is one
		if result != "" {
			fmt.Println(result)
		}

	case "switch-iframe":
		switchIframeCmd.Parse(os.Args[2:])
		if *switchIframeSelector == "" {
			fmt.Println("Error: selector flag is required")
			switchIframeCmd.PrintDefaults()
			os.Exit(1)
		}

		// Create a client
		c := client.NewClient(*switchIframeHost, *switchIframePort)

		// Switch to iframe
		err := c.SwitchToIframe(*switchIframeTabID, *switchIframeSelector, *switchIframeTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("Switched to iframe context")

	case "switch-main":
		switchMainCmd.Parse(os.Args[2:])

		// Create a client
		c := client.NewClient(*switchMainHost, *switchMainPort)

		// Switch back to main page
		err := c.SwitchToMain(*switchMainTabID, *switchMainTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("Switched to main page context")

	case "screenshot":
		screenshotCmd.Parse(os.Args[2:])
		if *screenshotOutput == "" {
			fmt.Println("Error: output flag is required")
			screenshotCmd.PrintDefaults()
			os.Exit(1)
		}

		// Create a client
		c := client.NewClient(*screenshotHost, *screenshotPort)

		// Take screenshot
		err := c.TakeScreenshot(*screenshotTabID, *screenshotOutput, *screenshotFullPage, *screenshotTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Printf("Screenshot saved to: %s\n", *screenshotOutput)

	case "status":
		statusCmd.Parse(os.Args[2:])

		// Create a client
		c := client.NewClient(*statusHost, *statusPort)

		// Check daemon status
		running, err := c.CheckStatus()
		if err != nil {
			// If we can't connect, the daemon is not running
			fmt.Println("Daemon is not running")
			os.Exit(0)
		}

		if running {
			fmt.Println("Daemon is running")
		} else {
			fmt.Println("Daemon is not running")
			os.Exit(0)
		}

	case "list-tabs":
		listTabsCmd.Parse(os.Args[2:])

		// Create a client
		c := client.NewClient(*listTabsHost, *listTabsPort)

		// List tabs
		tabs, err := c.ListTabs()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		// Sort tabs by history index (most recent first)
		sort.Slice(tabs, func(i, j int) bool {
			return tabs[i].HistoryIndex > tabs[j].HistoryIndex
		})

		// Print the tabs
		if len(tabs) == 0 {
			fmt.Println("No tabs open")
		} else {
			fmt.Println("Open tabs (in order of recent use):")
			for _, tab := range tabs {
				currentMarker := " "
				if tab.IsCurrent {
					currentMarker = "*"
				}
				fmt.Printf("%s %s: %s\n", currentMarker, tab.ID, tab.URL)
			}
		}

	case "disable-cache":
		disableCacheCmd.Parse(os.Args[2:])

		// Create a client
		c := client.NewClient(*disableCacheHost, *disableCachePort)

		// Disable cache
		err := c.DisableCache(*disableCacheTabID, *disableCacheTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("Cache disabled successfully")

	case "enable-cache":
		enableCacheCmd.Parse(os.Args[2:])

		// Create a client
		c := client.NewClient(*enableCacheHost, *enableCachePort)

		// Enable cache
		err := c.EnableCache(*enableCacheTabID, *enableCacheTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("Cache enabled successfully")

	case "clear-cache":
		clearCacheCmd.Parse(os.Args[2:])

		// Create a client
		c := client.NewClient(*clearCacheHost, *clearCachePort)

		// Clear cache
		err := c.ClearCache(*clearCacheTabID, *clearCacheTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("Cache cleared successfully")

	case "clear-all-site-data":
		clearAllSiteDataCmd.Parse(os.Args[2:])

		// Create a client
		c := client.NewClient(*clearAllSiteDataHost, *clearAllSiteDataPort)

		// Clear all site data
		err := c.ClearAllSiteData(*clearAllSiteDataTabID, *clearAllSiteDataTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("All site data cleared successfully")

	case "clear-cookies":
		clearCookiesCmd.Parse(os.Args[2:])

		// Create a client
		c := client.NewClient(*clearCookiesHost, *clearCookiesPort)

		// Clear cookies
		err := c.ClearCookies(*clearCookiesTabID, *clearCookiesTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("Cookies cleared successfully")

	case "clear-storage":
		clearStorageCmd.Parse(os.Args[2:])

		// Create a client
		c := client.NewClient(*clearStorageHost, *clearStoragePort)

		// Clear storage
		err := c.ClearStorage(*clearStorageTabID, *clearStorageTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("Storage cleared successfully")

	case "drag-and-drop":
		dragAndDropCmd.Parse(os.Args[2:])

		// Validate required parameters
		if *dragAndDropSource == "" {
			fmt.Fprintf(os.Stderr, "Error: --source parameter is required\n")
			os.Exit(1)
		}
		if *dragAndDropTarget == "" {
			fmt.Fprintf(os.Stderr, "Error: --target parameter is required\n")
			os.Exit(1)
		}

		// Create a client
		c := client.NewClient(*dragAndDropHost, *dragAndDropPort)

		// Perform drag and drop
		err := c.DragAndDrop(*dragAndDropTabID, *dragAndDropSource, *dragAndDropTarget, *dragAndDropTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Println("Drag and drop completed successfully")

	case "drag-and-drop-coordinates":
		dragAndDropCoordinatesCmd.Parse(os.Args[2:])

		// Validate required parameters
		if *dragAndDropCoordinatesSource == "" {
			fmt.Fprintf(os.Stderr, "Error: --source parameter is required\n")
			os.Exit(1)
		}

		// Create a client
		c := client.NewClient(*dragAndDropCoordinatesHost, *dragAndDropCoordinatesPort)

		// Perform drag and drop to coordinates
		err := c.DragAndDropToCoordinates(*dragAndDropCoordinatesTabID, *dragAndDropCoordinatesSource, *dragAndDropCoordinatesX, *dragAndDropCoordinatesY, *dragAndDropCoordinatesTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Printf("Drag and drop to coordinates (%d, %d) completed successfully\n", *dragAndDropCoordinatesX, *dragAndDropCoordinatesY)

	case "drag-and-drop-offset":
		dragAndDropOffsetCmd.Parse(os.Args[2:])

		// Validate required parameters
		if *dragAndDropOffsetSource == "" {
			fmt.Fprintf(os.Stderr, "Error: --source parameter is required\n")
			os.Exit(1)
		}

		// Create a client
		c := client.NewClient(*dragAndDropOffsetHost, *dragAndDropOffsetPort)

		// Perform drag and drop by offset
		err := c.DragAndDropByOffset(*dragAndDropOffsetTabID, *dragAndDropOffsetSource, *dragAndDropOffsetX, *dragAndDropOffsetY, *dragAndDropOffsetTimeout)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}

		fmt.Printf("Drag and drop by offset (%d, %d) completed successfully\n", *dragAndDropOffsetX, *dragAndDropOffsetY)

	case "right-click":
		rightClickCmd.Parse(os.Args[2:])
		c := client.NewClient(*rightClickHost, *rightClickPort)
		err := c.RightClick(*rightClickTabID, *rightClickSelector, *rightClickTimeout)
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("Right-click completed successfully\n")

	case "double-click":
		doubleClickCmd.Parse(os.Args[2:])
		c := client.NewClient(*doubleClickHost, *doubleClickPort)
		err := c.DoubleClick(*doubleClickTabID, *doubleClickSelector, *doubleClickTimeout)
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("Double-click completed successfully\n")

	case "middle-click":
		middleClickCmd.Parse(os.Args[2:])
		c := client.NewClient(*middleClickHost, *middleClickPort)
		err := c.MiddleClick(*middleClickTabID, *middleClickSelector, *middleClickTimeout)
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("Middle-click completed successfully\n")

	case "hover":
		hoverCmd.Parse(os.Args[2:])
		c := client.NewClient(*hoverHost, *hoverPort)
		err := c.Hover(*hoverTabID, *hoverSelector, *hoverTimeout)
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("Hover completed successfully\n")

	case "mouse-move":
		mouseMoveCmd.Parse(os.Args[2:])
		c := client.NewClient(*mouseMoveHost, *mouseMovePort)
		err := c.MouseMove(*mouseMoveTabID, *mouseMoveX, *mouseMoveY, *mouseMoveTimeout)
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("Mouse move to (%d, %d) completed successfully\n", *mouseMoveX, *mouseMoveY)

	case "scroll-wheel":
		scrollWheelCmd.Parse(os.Args[2:])
		c := client.NewClient(*scrollWheelHost, *scrollWheelPort)
		err := c.ScrollWheel(*scrollWheelTabID, *scrollWheelX, *scrollWheelY, *scrollWheelDeltaX, *scrollWheelDeltaY, *scrollWheelTimeout)
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("Scroll wheel at (%d, %d) with delta (%d, %d) completed successfully\n", *scrollWheelX, *scrollWheelY, *scrollWheelDeltaX, *scrollWheelDeltaY)

	case "key-combination":
		keyCombinationCmd.Parse(os.Args[2:])
		c := client.NewClient(*keyCombinationHost, *keyCombinationPort)
		err := c.KeyCombination(*keyCombinationTabID, *keyCombinationKeys, *keyCombinationTimeout)
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("Key combination '%s' sent successfully\n", *keyCombinationKeys)

	case "special-key":
		specialKeyCmd.Parse(os.Args[2:])
		c := client.NewClient(*specialKeyHost, *specialKeyPort)
		err := c.SpecialKey(*specialKeyTabID, *specialKeyKey, *specialKeyTimeout)
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("Special key '%s' sent successfully\n", *specialKeyKey)

	case "modifier-click":
		modifierClickCmd.Parse(os.Args[2:])
		c := client.NewClient(*modifierClickHost, *modifierClickPort)
		err := c.ModifierClick(*modifierClickTabID, *modifierClickSelector, *modifierClickModifiers, *modifierClickTimeout)
		if err != nil {
			fmt.Printf("Error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("Modifier click with '%s' completed successfully\n", *modifierClickModifiers)

	default:
		printUsage()
		os.Exit(1)
	}
}

func printUsage() {
	fmt.Println("Usage: cremote <command> [options]")
	fmt.Println("Commands:")
	fmt.Println("  version           Show version information for CLI and daemon")
	fmt.Println("  open-tab          Open a new tab and return its ID")
	fmt.Println("  load-url          Load a URL in a tab")
	fmt.Println("  fill-form         Fill a form field with a value")
	fmt.Println("  upload-file       Transfer a file to daemon container and upload to a file input")
	fmt.Println("  submit-form       Submit a form")
	fmt.Println("  get-source        Get the source code of a page")
	fmt.Println("  get-element       Get the HTML of an element")
	fmt.Println("  click-element     Click on an element")
	fmt.Println("  close-tab         Close a tab")
	fmt.Println("  wait-navigation   Wait for a navigation event")
	fmt.Println("  eval-js           Execute JavaScript code in a tab")
	fmt.Println("  switch-iframe     Switch to iframe context for subsequent commands")
	fmt.Println("  switch-main       Switch back to main page context")
	fmt.Println("  screenshot        Take a screenshot of the current page")
	fmt.Println("  list-tabs         List all open tabs")
	fmt.Println("  disable-cache     Disable browser cache for a tab")
	fmt.Println("  enable-cache      Enable browser cache for a tab")
	fmt.Println("  clear-cache       Clear browser cache for a tab")
	fmt.Println("  clear-all-site-data Clear all site data (cookies, storage, cache, etc.)")
	fmt.Println("  clear-cookies     Clear cookies for a tab")
	fmt.Println("  clear-storage     Clear web storage (localStorage, sessionStorage, etc.)")
	fmt.Println("  drag-and-drop     Drag and drop from source element to target element")
	fmt.Println("  drag-and-drop-coordinates Drag and drop from source element to specific coordinates")
	fmt.Println("  drag-and-drop-offset Drag and drop from source element by relative offset")
	fmt.Println("  right-click       Right-click on an element")
	fmt.Println("  double-click      Double-click on an element")
	fmt.Println("  middle-click      Middle-click on an element")
	fmt.Println("  hover             Hover over an element")
	fmt.Println("  mouse-move        Move mouse to specific coordinates")
	fmt.Println("  scroll-wheel      Scroll with mouse wheel at specific coordinates")
	fmt.Println("  key-combination   Send key combinations (Ctrl+C, Alt+Tab, etc.)")
	fmt.Println("  special-key       Send special keys (Enter, Escape, Tab, F1, etc.)")
	fmt.Println("  modifier-click    Click with modifier keys (Ctrl+click, Shift+click)")
	fmt.Println("  status            Check if the daemon is running")
	fmt.Println("\nRun 'cremote <command> -h' for more information on a command")
	fmt.Println("\nBefore using this tool, make sure the daemon is running:")
	fmt.Println("  cremotedaemon")
	fmt.Println("\nThe daemon requires Chromium/Chrome to be running with remote debugging enabled:")
	fmt.Println("  chromium --remote-debugging-port=9222 --user-data-dir=/tmp/chromium-debug")
	fmt.Println("\nNote: Most commands can use the current tab if you don't specify a tab ID.")
}
