/*
Copyright © 2023 Philipp Wolfer <phw@uploadedlobster.com>

Scotty is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later version.

Scotty is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
Scotty. If not, see <https://www.gnu.org/licenses/>.
*/

package cli

import (
	"errors"
	"fmt"
	"slices"

	"github.com/manifoldco/promptui"
	"github.com/spf13/cobra"
	"go.uploadedlobster.com/scotty/internal/backends"
	"go.uploadedlobster.com/scotty/internal/config"
	"go.uploadedlobster.com/scotty/internal/i18n"
)

func SelectService(cmd *cobra.Command) (config.ServiceConfig, error) {
	// First try to load service from command line flag
	service, err := GetServiceConfigFromFlag(cmd, "service")
	if err == nil {
		return service, nil
	}

	// Prompt the user to select a service
	services := config.AllServicesAsList()
	if len(services) == 0 {
		err := errors.New(i18n.Tr("no existing service configurations"))
		return config.ServiceConfig{}, err
	}
	sel := promptui.Select{
		Label: i18n.Tr("Service"),
		Items: services,
		Size:  10,
	}
	i, _, err := sel.Run()
	if err != nil {
		return config.ServiceConfig{}, err
	}
	return services[i], nil
}

func SelectBackend(selected string) (string, error) {
	backendList := backends.GetBackends()
	i := slices.IndexFunc(backendList, func(b backends.BackendInfo) bool {
		return b.Name == selected
	})
	sel := promptui.Select{
		Label:     i18n.Tr("Backend"),
		Items:     backendList,
		CursorPos: i,
		Size:      10,
	}
	_, backend, err := sel.Run()
	return backend, err
}

func PromptExtraOptions(config config.ServiceConfig) (config.ServiceConfig, error) {
	backend, err := backends.BackendByName(config.Backend)
	if err != nil {
		return config, err
	}
	opts := backend.Options()
	if opts == nil {
		return config, nil
	}

	values := make(map[string]any, len(opts))
	for _, opt := range opts {
		// Use current value as default
		current, exists := config.ConfigValues[opt.Name]
		if exists {
			opt.Default = fmt.Sprintf("%v", current)
		}

		val, err := Prompt(opt)
		if err != nil {
			return config, err
		}
		values[opt.Name] = val
	}

	config.ConfigValues = values
	return config, nil
}