package cmd

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

	"github.com/urfave/cli/v3"
)

// REPL represents a Read-Eval-Print Loop for interactive CLI usage
type REPL struct {
	app     *cli.Command
	prompt  string
	history []string
}

// NewREPL creates a new REPL instance
func NewREPL(app *cli.Command) *REPL {
	return &REPL{
		app:    app,
		prompt: "arp> ",
	}
}

// Run starts the REPL loop
func (r *REPL) Run(ctx context.Context) error {
	scanner := bufio.NewScanner(os.Stdin)

	fmt.Println("ARP CLI - Interactive Mode")
	fmt.Println("Type 'help' for available commands, 'exit' or 'quit' to leave.")
	fmt.Println()

	for {
		// Show prompt
		fmt.Print(r.prompt)

		// Read line
		if !scanner.Scan() {
			// EOF (Ctrl+D)
			fmt.Println()
			break
		}

		line := strings.TrimSpace(scanner.Text())
		if line == "" {
			continue
		}

		// Check for exit commands
		if line == "exit" || line == "quit" || line == "q" {
			fmt.Println("Goodbye!")
			break
		}

		// Parse the line into args
		args, err := parseArgs(line)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error parsing command: %v\n", err)
			continue
		}

		// Prepend the app name to match CLI expectations
		args = append([]string{"arp_cli"}, args...)

		// Execute the command
		if err := r.app.Run(ctx, args); err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		}

		// Store in history
		r.history = append(r.history, line)
	}

	if err := scanner.Err(); err != nil {
		return fmt.Errorf("reading input: %w", err)
	}

	return nil
}

// parseArgs parses a command line string into arguments
// Handles quoted strings and basic escaping
func parseArgs(line string) ([]string, error) {
	var args []string
	var current strings.Builder
	inQuote := false
	quoteChar := rune(0)

	for i, ch := range line {
		switch {
		case ch == '\\' && i+1 < len(line):
			// Handle escape sequences
			next := rune(line[i+1])
			if next == '"' || next == '\'' || next == '\\' || next == ' ' {
				current.WriteRune(next)
				// Skip the next character
				line = line[:i] + line[i+1:]
			} else {
				current.WriteRune(ch)
			}
		case (ch == '"' || ch == '\'') && !inQuote:
			inQuote = true
			quoteChar = ch
		case ch == quoteChar && inQuote:
			inQuote = false
			quoteChar = 0
		case ch == ' ' && !inQuote:
			if current.Len() > 0 {
				args = append(args, current.String())
				current.Reset()
			}
		default:
			current.WriteRune(ch)
		}
	}

	// Add the last argument
	if current.Len() > 0 {
		args = append(args, current.String())
	}

	return args, nil
}
