package form

import (
	"charm.land/huh/v2"

	"git.secluded.site/keld/internal/restic"
)

// manualEntryValue is the sentinel returned by SelectSnapshot when the
// user chooses to type a snapshot ID manually instead of picking from
// the list.
const manualEntryValue = "__manual__"

// IsManualEntry reports whether the value returned by SelectSnapshot
// indicates the user chose manual entry.
func IsManualEntry(v string) bool {
	return v == manualEntryValue
}

// SelectSnapshot presents an interactive picker for the given snapshots.
// Each snapshot is shown as a formatted summary line; the selected
// snapshot's short ID is returned.
//
// An "Enter ID manually…" option is always included at the end so users
// can type arbitrary IDs (including the snapshotID:subfolder syntax).
//
// Returns the selected short ID, or the manualEntryValue sentinel
// (check with IsManualEntry), or ErrAborted if the user cancels.
func SelectSnapshot(snapshots []restic.Snapshot) (string, error) {
	opts := make([]huh.Option[string], 0, len(snapshots)+1)
	for _, s := range snapshots {
		opts = append(opts, huh.NewOption(restic.FormatSnapshotLine(s), s.ShortID))
	}
	opts = append(opts, huh.NewOption("Enter ID manually…", manualEntryValue))

	var selected string
	form := huh.NewForm(
		huh.NewGroup(
			huh.NewSelect[string]().
				Title("Select a snapshot").
				Options(opts...).
				Filtering(true).
				Value(&selected),
		),
	)

	if err := wrapAbort(form.Run()); err != nil {
		return "", err
	}
	return selected, nil
}

// ManualSnapshotID prompts the user to type a snapshot ID. This is used
// as the fallback when snapshot listing fails or when the user chooses
// "Enter ID manually…" from the picker.
func ManualSnapshotID() (string, error) {
	var id string
	form := huh.NewForm(
		huh.NewGroup(
			huh.NewInput().
				Title("Snapshot ID").
				Description("Supports snapshotID:subfolder syntax, or \"latest\".").
				Placeholder("e.g. latest or a1b2c3d4 or a1b2c3d4:/home/user").
				Value(&id).
				Validate(notEmpty("snapshot ID")),
		),
	)

	if err := wrapAbort(form.Run()); err != nil {
		return "", err
	}
	return id, nil
}

// overwriteOptions defines the choices for --overwrite in the order
// they're presented to the user.
var overwriteOptions = []huh.Option[string]{
	huh.NewOption("if-changed  (recommended — only restore what differs)", "if-changed"),
	huh.NewOption("if-newer    (only overwrite older files)", "if-newer"),
	huh.NewOption("never       (skip existing files entirely)", "never"),
	huh.NewOption("always      (restic default — overwrite everything)", "always"),
}

// SelectOverwrite presents an interactive picker for the --overwrite
// behavior. The cursor starts on "if-changed".
//
// Returns the selected value (one of: if-changed, if-newer, never,
// always), or ErrAborted if the user cancels.
func SelectOverwrite() (string, error) {
	var selected string
	form := huh.NewForm(
		huh.NewGroup(
			huh.NewSelect[string]().
				Title("Overwrite existing files?").
				Options(overwriteOptions...).
				Value(&selected),
		),
	)

	if err := wrapAbort(form.Run()); err != nil {
		return "", err
	}
	return selected, nil
}
