package customize

import (
	"fmt"
	"os"

	"gopkg.in/yaml.v2"

	"github.com/photoprism/photoprism/internal/i18n"
	"github.com/photoprism/photoprism/pkg/clean"
	"github.com/photoprism/photoprism/pkg/fs"
)

const (
	RootPath = "/"
)

// Settings represents user settings for Web UI, indexing, and import.
type Settings struct {
	UI        UISettings       `json:"ui" yaml:"UI"`
	Search    SearchSettings   `json:"search" yaml:"Search"`
	Maps      MapsSettings     `json:"maps" yaml:"Maps"`
	Features  FeatureSettings  `json:"features" yaml:"Features"`
	Import    ImportSettings   `json:"import" yaml:"Import"`
	Index     IndexSettings    `json:"index" yaml:"Index"`
	Stack     StackSettings    `json:"stack" yaml:"Stack"`
	Share     ShareSettings    `json:"share" yaml:"Share"`
	Download  DownloadSettings `json:"download" yaml:"Download"`
	Templates TemplateSettings `json:"templates" yaml:"Templates"`
}

// NewDefaultSettings creates a new default Settings instance.
func NewDefaultSettings() *Settings {
	return NewSettings(DefaultTheme, DefaultLocale)
}

// NewSettings creates a new Settings instance.
func NewSettings(theme, lang string) *Settings {
	return &Settings{
		UI: UISettings{
			Scrollbar: true,
			Zoom:      false,
			Theme:     theme,
			Language:  lang,
		},
		Search: SearchSettings{
			BatchSize: 0,
		},
		Maps: MapsSettings{
			Animate: 0,
			Style:   "",
		},
		Features: FeatureSettings{
			Favorites: true,
			Reactions: true,
			Ratings:   true,
			Upload:    true,
			Download:  true,
			Private:   true,
			Files:     true,
			Videos:    true,
			Folders:   true,
			Albums:    true,
			Moments:   true,
			Estimates: true,
			People:    true,
			Labels:    true,
			Places:    true,
			Edit:      true,
			Archive:   true,
			Review:    true,
			Share:     true,
			Library:   true,
			Import:    true,
			Logs:      true,
			Search:    true,
			Settings:  true,
			Services:  true,
			Account:   true,
			Delete:    false,
		},
		Import: ImportSettings{
			Path: RootPath,
			Move: false,
		},
		Index: IndexSettings{
			Path:    RootPath,
			Rescan:  false,
			Convert: true,
		},
		Stack: StackSettings{
			UUID: true,
			Meta: true,
			Name: false,
		},
		Share: ShareSettings{
			Title: "",
		},
		Download: NewDownloadSettings(),
		Templates: TemplateSettings{
			Default: "index.gohtml",
		},
	}
}

// Propagate updates settings in other packages as needed.
func (s *Settings) Propagate() {
	i18n.SetLocale(s.UI.Language)
}

// StackSequences checks if files should be stacked based on their file name prefix (sequential names).
func (s Settings) StackSequences() bool {
	return s.Stack.Name
}

// StackUUID checks if files should be stacked based on unique image or instance id.
func (s Settings) StackUUID() bool {
	return s.Stack.UUID
}

// StackMeta checks if files should be stacked based on their place and time metadata.
func (s Settings) StackMeta() bool {
	return s.Stack.Meta
}

// Load user settings from file.
func (s *Settings) Load(fileName string) error {
	if fileName == "" {
		return fmt.Errorf("no settings filename provided")
	} else if !fs.FileExists(fileName) {
		return fmt.Errorf("settings file not found: %s", clean.Log(fileName))
	}

	yamlConfig, err := os.ReadFile(fileName)

	if err != nil {
		return err
	}

	if err := yaml.Unmarshal(yamlConfig, s); err != nil {
		return err
	}

	s.Propagate()

	return nil
}

// Save user settings to a file.
func (s *Settings) Save(fileName string) error {
	data, err := yaml.Marshal(s)

	if err != nil {
		return err
	}

	s.Propagate()

	if err := os.WriteFile(fileName, data, fs.ModeFile); err != nil {
		return err
	}

	return nil
}
