package command

import (
	"encoding/json"
	"strings"
)

// ParseArgs converts a slice of raw arguments into structured ParsedArgs.
// Supports: positional args, key=value pairs, and quoted values like key="hello world".
// Pure function — no side effects.
func ParseArgs(args []string) ParsedArgs {
	p := ParsedArgs{
		Named: make(map[string]string),
		Raw:   args,
	}

	// First, rejoin args to handle quoted values that were split by Fields().
	joined := strings.Join(args, " ")
	tokens := tokenize(joined)

	for _, tok := range tokens {
		if idx := strings.IndexByte(tok, '='); idx > 0 {
			key := tok[:idx]
			val := tok[idx+1:]
			// Strip surrounding quotes from value
			val = stripQuotes(val)
			p.Named[key] = val
		} else {
			p.Positional = append(p.Positional, tok)
		}
	}

	return p
}

// ArgsToJSON converts a named args map to a JSON string for tools.Registry.Execute.
// Pure function.
func ArgsToJSON(named map[string]string) string {
	if len(named) == 0 {
		return ""
	}
	m := make(map[string]any, len(named))
	for k, v := range named {
		m[k] = v
	}
	b, _ := json.Marshal(m)
	return string(b)
}

// tokenize splits a string respecting quoted values.
// e.g. `host=server1 command="uptime -a"` → ["host=server1", `command="uptime -a"`]
func tokenize(s string) []string {
	var tokens []string
	var current strings.Builder
	inQuote := false
	quoteChar := byte(0)

	for i := 0; i < len(s); i++ {
		ch := s[i]
		switch {
		case !inQuote && (ch == '"' || ch == '\''):
			inQuote = true
			quoteChar = ch
			current.WriteByte(ch)
		case inQuote && ch == quoteChar:
			inQuote = false
			current.WriteByte(ch)
		case !inQuote && ch == ' ':
			if current.Len() > 0 {
				tokens = append(tokens, current.String())
				current.Reset()
			}
		default:
			current.WriteByte(ch)
		}
	}
	if current.Len() > 0 {
		tokens = append(tokens, current.String())
	}
	return tokens
}

// stripQuotes removes surrounding double or single quotes from a string.
func stripQuotes(s string) string {
	if len(s) >= 2 {
		if (s[0] == '"' && s[len(s)-1] == '"') || (s[0] == '\'' && s[len(s)-1] == '\'') {
			return s[1 : len(s)-1]
		}
	}
	return s
}
