package cmd

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"

	"omixlab.com/mosis-portal/pkg/mospkg"
)

// RunCmd returns the run command
func RunCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "run [directory]",
		Short: "Run app in desktop designer",
		Long:  "Launch the Mosis designer to preview and test your app.",
		Args:  cobra.MaximumNArgs(1),
		RunE:  runRun,
	}

	cmd.Flags().String("entry", "", "Override entry point")
	cmd.Flags().Bool("no-hot-reload", false, "Disable hot reload")
	cmd.Flags().String("log", "", "Write logs to file")
	cmd.Flags().String("designer", "", "Path to mosis-designer executable")

	return cmd
}

func runRun(cmd *cobra.Command, args []string) error {
	dir := "."
	if len(args) > 0 {
		dir = args[0]
	}

	// Read manifest to get entry point
	manifestPath := filepath.Join(dir, "manifest.json")
	manifestData, err := os.ReadFile(manifestPath)
	if err != nil {
		return fmt.Errorf("manifest.json not found\n\nAre you in a Mosis project directory?")
	}

	manifest, err := mospkg.ParseManifest(manifestData)
	if err != nil {
		return fmt.Errorf("invalid manifest.json: %w", err)
	}

	// Determine entry point
	entry, _ := cmd.Flags().GetString("entry")
	if entry == "" {
		entry = manifest.Entry
	}

	entryPath := filepath.Join(dir, entry)
	if _, err := os.Stat(entryPath); os.IsNotExist(err) {
		return fmt.Errorf("entry point not found: %s", entry)
	}

	// Find designer executable
	designerPath, _ := cmd.Flags().GetString("designer")
	if designerPath == "" {
		designerPath = viper.GetString("designer_path")
	}
	if designerPath == "" {
		designerPath = "mosis-designer"
	}

	// Check if designer exists
	designerExe, err := exec.LookPath(designerPath)
	if err != nil {
		// Try common locations
		commonPaths := []string{
			"./mosis-designer",
			"./mosis-designer.exe",
			"./build/Debug/mosis-designer.exe",
			"./build/Release/mosis-designer.exe",
		}
		for _, p := range commonPaths {
			if _, err := os.Stat(p); err == nil {
				designerExe = p
				break
			}
		}
		if designerExe == "" {
			return fmt.Errorf("mosis-designer not found\n\nSet path with: mosis config set designer_path /path/to/mosis-designer")
		}
	}

	// Build command arguments
	cmdArgs := []string{entryPath}

	logPath, _ := cmd.Flags().GetString("log")
	if logPath != "" {
		cmdArgs = append(cmdArgs, "--log", logPath)
	}

	fmt.Println("Starting Mosis Designer...")
	fmt.Printf("Loading: %s\n\n", entry)

	// Execute designer
	process := exec.Command(designerExe, cmdArgs...)
	process.Stdout = os.Stdout
	process.Stderr = os.Stderr
	process.Stdin = os.Stdin

	// Set working directory to project directory
	absDir, _ := filepath.Abs(dir)
	process.Dir = absDir

	noHotReload, _ := cmd.Flags().GetBool("no-hot-reload")
	if !noHotReload {
		fmt.Println("[Hot reload enabled - changes auto-refresh]")
	}
	fmt.Println("Press Ctrl+C to stop\n")

	if err := process.Run(); err != nil {
		if exitErr, ok := err.(*exec.ExitError); ok {
			return fmt.Errorf("designer exited with code %d", exitErr.ExitCode())
		}
		return fmt.Errorf("run designer: %w", err)
	}

	return nil
}
