package app

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"strings"

	"golang.org/x/term"

	"github.com/ClareAI/astra-insight-mcp/internal/config"
)

// RunConfigure implements `astra configure` / `astra auth` — save LLM and Astra keys to ~/.astra/llm.json.
func RunConfigure(args []string) {
	if args == nil {
		args = []string{}
	}
	fs := flag.NewFlagSet("configure", flag.ExitOnError)
	apiKeyFlag := fs.String("api-key", "", "LLM API key; if empty, prompts interactively (hidden)")
	baseURLFlag := fs.String("base-url", "", "API base URL (default: from --provider when non-interactive)")
	modelFlag := fs.String("model", "", "Model id (default: from --provider when non-interactive)")
	providerFlag := fs.String("provider", "", "openrouter | gemini (default: openrouter when using --api-key only; prompted when entering key interactively)")
	astraKeyFlag := fs.String("astra-key", "", "Astra platform API key (for agent management); if empty, prompts interactively")
	showPath := fs.Bool("show-path", false, "Print config file path and exit")

	fs.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: astra configure [flags]\n\n")
		fmt.Fprintf(os.Stderr, "Save LLM credentials to ~/.astra/llm.json (mode 0600).\n")
		fmt.Fprintf(os.Stderr, "Supports OpenRouter and Google Gemini.\n\n")
		fmt.Fprintf(os.Stderr, "Examples:\n")
		fmt.Fprintf(os.Stderr, "  astra configure                              # choose provider + key + optional URL/model\n")
		fmt.Fprintf(os.Stderr, "  astra configure --provider gemini --api-key AIza...\n")
		fmt.Fprintf(os.Stderr, "  astra configure --show-path\n\n")
		fmt.Fprintf(os.Stderr, "Flags:\n")
		fs.PrintDefaults()
	}

	if err := fs.Parse(args); err != nil {
		os.Exit(1)
	}

	path, err := config.LLMFilePath()
	if err != nil {
		fmt.Fprintf(os.Stderr, "[configure] error: %v\n", err)
		os.Exit(1)
	}

	if *showPath {
		fmt.Println(path)
		return
	}

	existing, _ := config.LoadLLMFile()

	var prov config.LLMProviderID
	provSet := false
	if strings.TrimSpace(*providerFlag) != "" {
		p, ok := config.ParseLLMProvider(*providerFlag)
		if !ok {
			fmt.Fprintf(os.Stderr, "[configure] invalid --provider %q (use openrouter or gemini)\n", *providerFlag)
			os.Exit(1)
		}
		prov = p
		provSet = true
	}

	keyFromFlag := strings.TrimSpace(*apiKeyFlag) != ""
	apiKey := strings.TrimSpace(*apiKeyFlag)
	if apiKey == "" {
		if !term.IsTerminal(int(os.Stdin.Fd())) || !term.IsTerminal(int(os.Stderr.Fd())) {
			fmt.Fprintf(os.Stderr, "[configure] stdin is not a TTY. Pass --api-key or run in a terminal.\n")
			os.Exit(1)
		}
		if !provSet {
			prov = promptLLMProviderUntilValid()
			provSet = true
		}
		var err error
		apiKey, err = readHiddenAPIKey("Enter API key (input hidden):")
		if err != nil {
			fmt.Fprintf(os.Stderr, "%s[configure] failed to read key: %v%s\n", replYellow, err, replReset)
			os.Exit(1)
		}
	} else if !provSet {
		prov = config.ProviderOpenRouter
		provSet = true
	}

	if apiKey == "" {
		fmt.Fprintf(os.Stderr, "%s[configure] API key cannot be empty%s\n", replYellow, replReset)
		os.Exit(1)
	}

	baseURL := strings.TrimSpace(*baseURLFlag)
	if baseURL == "" {
		if keyFromFlag {
			baseURL = prov.DefaultBaseURL()
		} else {
			def := existing.BaseURL
			if def == "" {
				def = prov.DefaultBaseURL()
			}
			baseURL = readLineDefault(fmt.Sprintf("API base URL [%s]: ", def), def)
		}
	}

	model := strings.TrimSpace(*modelFlag)
	if model == "" {
		if keyFromFlag {
			model = prov.DefaultModel()
		} else {
			def := existing.Model
			if def == "" {
				def = prov.DefaultModel()
			}
			model = readLineDefault(fmt.Sprintf("Model [%s]: ", def), def)
		}
	}

	astraKey := strings.TrimSpace(*astraKeyFlag)
	if astraKey == "" {
		astraKey = existing.AstraAPIKey
	}
	if astraKey == "" && !keyFromFlag && term.IsTerminal(int(os.Stdin.Fd())) {
		if k := promptAstraPlatformKey(); k != "" {
			astraKey = k
		}
	}

	cfg := config.LLMEnv{
		APIKey:      apiKey,
		BaseURL:     baseURL,
		Model:       model,
		FastModel:   "",
		AstraAPIKey: astraKey,
	}

	if err := config.SaveLLMFile(cfg); err != nil {
		fmt.Fprintf(os.Stderr, "[configure] error saving: %v\n", err)
		os.Exit(1)
	}

	fmt.Fprintf(os.Stderr, "[configure] Saved settings to %s\n", path)
	fmt.Fprintf(os.Stderr, "  Run `astra` to start the REPL. Set LLM_* env vars to override for a single session.\n")
}

func readLineDefault(prompt, defaultVal string) string {
	fmt.Fprintf(os.Stderr, "%s%s%s", replDim, prompt, replReset)
	line, err := bufio.NewReader(os.Stdin).ReadString('\n')
	if err != nil {
		return defaultVal
	}
	s := strings.TrimSpace(strings.TrimRight(line, "\r\n"))
	if s == "" {
		return defaultVal
	}
	return s
}
