// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

package ui

import (
	"fmt"

	"github.com/charmbracelet/huh/spinner"
)

// Spin executes fn while displaying a spinner with the given title.
// Uses generics to preserve the return type of the wrapped function.
// In non-interactive mode, the function runs directly without spinner UI.
func Spin[T any](title string, fn func() (T, error)) (T, error) {
	// In plain/non-interactive mode, just run the function directly
	if IsPlain() {
		return fn()
	}

	var result T

	var fnErr error

	spinErr := spinner.New().
		Title(title).
		Action(func() {
			result, fnErr = fn()
		}).
		Run()
	if spinErr != nil {
		return result, fmt.Errorf("spinner: %w", spinErr)
	}

	return result, fnErr
}

// SpinVoid executes fn while displaying a spinner with the given title.
// Use for functions that only return an error.
// In non-interactive mode, the function runs directly without spinner UI.
func SpinVoid(title string, fn func() error) error {
	// In plain/non-interactive mode, just run the function directly
	if IsPlain() {
		return fn()
	}

	var fnErr error

	spinErr := spinner.New().
		Title(title).
		Action(func() {
			fnErr = fn()
		}).
		Run()
	if spinErr != nil {
		return fmt.Errorf("spinner: %w", spinErr)
	}

	return fnErr
}
