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

package init

import (
	"errors"
	"fmt"

	"github.com/charmbracelet/huh"
	"github.com/spf13/cobra"

	"git.secluded.site/lune/internal/config"
	"git.secluded.site/lune/internal/ui"
)

// runUIPrefsStep runs the UI preferences configuration step.
func runUIPrefsStep(cfg *config.Config) wizardNav {
	color := cfg.UI.Color
	if color == "" {
		color = colorAuto
	}

	err := huh.NewSelect[string]().
		Title("Color output").
		Description("When should lune use colored output?").
		Options(
			huh.NewOption("Auto (detect terminal capability)", colorAuto),
			huh.NewOption("Always", "always"),
			huh.NewOption("Never", "never"),
		).
		Value(&color).
		Run()
	if err != nil {
		if errors.Is(err, huh.ErrUserAborted) {
			return navQuit
		}

		return navQuit
	}

	cfg.UI.Color = color

	return navNext
}

// runAreasStep runs the areas configuration step.
func runAreasStep(cfg *config.Config) wizardNav {
	return manageAreasAsStep(cfg)
}

// runNotebooksStep runs the notebooks configuration step.
func runNotebooksStep(cfg *config.Config) wizardNav {
	return manageNotebooksAsStep(cfg)
}

// runHabitsStep runs the habits configuration step.
func runHabitsStep(cfg *config.Config) wizardNav {
	return manageHabitsAsStep(cfg)
}

// runDefaultsStep runs the defaults configuration step.
func runDefaultsStep(cfg *config.Config) wizardNav {
	hasAreas := len(cfg.Areas) > 0
	hasNotebooks := len(cfg.Notebooks) > 0

	if !hasAreas && !hasNotebooks {
		return navNext
	}

	if hasAreas {
		nav := selectDefaultAreaWithNav(cfg)
		if nav != navNext {
			return nav
		}
	}

	if hasNotebooks {
		return selectDefaultNotebookWithNav(cfg)
	}

	return navNext
}

// runAccessTokenStep runs the access token configuration step.
func runAccessTokenStep(cmd *cobra.Command) wizardNav {
	err := configureAccessToken(cmd)
	if errors.Is(err, errQuit) {
		return navQuit
	}

	if err != nil {
		out := cmd.OutOrStdout()
		fmt.Fprintln(out, ui.Error.Render("Token configuration failed: "+err.Error()))

		var skip bool

		skipErr := huh.NewConfirm().
			Title("Skip token configuration?").
			Description("You can configure it later with 'lune init'.").
			Affirmative("Skip for now").
			Negative("Go back").
			Value(&skip).
			Run()
		if skipErr != nil {
			return navQuit
		}

		if skip {
			return navNext
		}

		return navBack
	}

	return navNext
}

// selectDefaultAreaWithNav selects the default area and returns navigation.
func selectDefaultAreaWithNav(cfg *config.Config) wizardNav {
	options := []huh.Option[string]{huh.NewOption("None", "")}
	for _, area := range cfg.Areas {
		options = append(options, huh.NewOption(area.Name+" ("+area.Key+")", area.Key))
	}

	choice, nav := runDefaultSelect("Default area", "Used when no area is specified.", cfg.Defaults.Area, options)
	if nav != navNext || choice == "" {
		return nav
	}

	cfg.Defaults.Area = choice

	return navNext
}

// selectDefaultNotebookWithNav selects the default notebook and returns navigation.
func selectDefaultNotebookWithNav(cfg *config.Config) wizardNav {
	options := []huh.Option[string]{huh.NewOption("None", "")}
	for _, nb := range cfg.Notebooks {
		options = append(options, huh.NewOption(nb.Name+" ("+nb.Key+")", nb.Key))
	}

	desc := "Used when no notebook is specified."
	choice, nav := runDefaultSelect("Default notebook", desc, cfg.Defaults.Notebook, options)

	if nav != navNext || choice == "" {
		return nav
	}

	cfg.Defaults.Notebook = choice

	return navNext
}

func runDefaultSelect(title, desc, current string, options []huh.Option[string]) (string, wizardNav) {
	options = append(options,
		huh.NewOption("← Back", choiceBack),
		huh.NewOption("Next →", choiceNext),
	)

	value := current

	err := huh.NewSelect[string]().
		Title(title).
		Description(desc).
		Options(options...).
		Value(&value).
		Run()
	if err != nil {
		return "", navQuit
	}

	switch value {
	case choiceBack:
		return "", navBack
	case choiceNext:
		return "", navNext
	default:
		return value, navNext
	}
}
