package model

import "time"

const SchemaVersion = 1

type JobType string

const (
	JobShare   JobType = "share"
	JobAppdata JobType = "appdata"
	JobDocker  JobType = "docker"
	JobVM      JobType = "vm"
	JobFlash   JobType = "flash"
)

type RepositoryType string

const (
	RepositoryLocal RepositoryType = "local"
	RepositorySMB   RepositoryType = "smb"
	RepositoryNFS   RepositoryType = "nfs"
	RepositorySFTP  RepositoryType = "sftp"
)

type Config struct {
	SchemaVersion int                  `json:"schemaVersion"`
	Jobs          []Job                `json:"jobs"`
	Repositories  []Repository         `json:"repositories"`
	Notifications []NotificationTarget `json:"notifications"`
	Settings      Settings             `json:"settings"`
}

type Settings struct {
	ResticPath       string `json:"resticPath"`
	RestoreRoot      string `json:"restoreRoot"`
	PersistentLogDir string `json:"persistentLogDir,omitempty"`
	CatchUpWindowHrs int    `json:"catchUpWindowHours"`
	CheckCron        string `json:"checkCron"`
	PruneCron        string `json:"pruneCron"`
}

type Job struct {
	SchemaVersion int         `json:"schemaVersion"`
	ID            string      `json:"id"`
	Name          string      `json:"name"`
	Type          JobType     `json:"type"`
	Enabled       bool        `json:"enabled"`
	RepositoryID  string      `json:"repositoryId"`
	Sources       []Source    `json:"sources"`
	Schedule      Schedule    `json:"schedule"`
	Consistency   Consistency `json:"consistency"`
	Compression   string      `json:"compression"`
	Excludes      []string    `json:"excludes,omitempty"`
	Tags          []string    `json:"tags,omitempty"`
	Retention     Retention   `json:"retention"`
	NotifyOn      []string    `json:"notifyOn,omitempty"`
	ShutdownSecs  int         `json:"shutdownTimeoutSeconds"`
}

type Source struct {
	Path       string            `json:"path,omitempty"`
	WorkloadID string            `json:"workloadId,omitempty"`
	Metadata   map[string]string `json:"metadata,omitempty"`
}

type Schedule struct {
	Cron     string `json:"cron"`
	Timezone string `json:"timezone,omitempty"`
}

type Consistency struct {
	Mode string `json:"mode"`
}

type Retention struct {
	Daily   int `json:"daily"`
	Weekly  int `json:"weekly"`
	Monthly int `json:"monthly"`
}

type Repository struct {
	SchemaVersion int               `json:"schemaVersion"`
	ID            string            `json:"id"`
	Name          string            `json:"name"`
	Type          RepositoryType    `json:"type"`
	Location      string            `json:"location"`
	PasswordRef   string            `json:"passwordRef"`
	CredentialRef string            `json:"credentialRef,omitempty"`
	Mount         *MountConfig      `json:"mount,omitempty"`
	Options       map[string]string `json:"options,omitempty"`
}

type MountConfig struct {
	Managed    bool   `json:"managed"`
	Remote     string `json:"remote,omitempty"`
	MountPoint string `json:"mountPoint,omitempty"`
	ReadOnly   bool   `json:"readOnly,omitempty"`
}

type NotificationTarget struct {
	SchemaVersion int      `json:"schemaVersion"`
	ID            string   `json:"id"`
	Name          string   `json:"name"`
	Type          string   `json:"type"`
	Enabled       bool     `json:"enabled"`
	URL           string   `json:"url,omitempty"`
	Topic         string   `json:"topic,omitempty"`
	TokenRef      string   `json:"tokenRef,omitempty"`
	Events        []string `json:"events,omitempty"`
}

type Run struct {
	SchemaVersion  int        `json:"schemaVersion"`
	ID             string     `json:"id"`
	JobID          string     `json:"jobId,omitempty"`
	TaskType       string     `json:"taskType"`
	Status         string     `json:"status"`
	Priority       int        `json:"priority"`
	CreatedAt      time.Time  `json:"createdAt"`
	StartedAt      *time.Time `json:"startedAt,omitempty"`
	FinishedAt     *time.Time `json:"finishedAt,omitempty"`
	SnapshotID     string     `json:"snapshotId,omitempty"`
	Message        string     `json:"message,omitempty"`
	ErrorCode      string     `json:"errorCode,omitempty"`
	BytesAdded     int64      `json:"bytesAdded,omitempty"`
	FilesNew       int64      `json:"filesNew,omitempty"`
	BytesProcessed int64      `json:"bytesProcessed,omitempty"`
	FilesProcessed int64      `json:"filesProcessed,omitempty"`
}

type RestoreTask struct {
	SchemaVersion int      `json:"schemaVersion"`
	ID            string   `json:"id"`
	RepositoryID  string   `json:"repositoryId"`
	SnapshotID    string   `json:"snapshotId"`
	Includes      []string `json:"includes"`
	Target        string   `json:"target"`
	InPlace       bool     `json:"inPlace"`
	Confirmed     bool     `json:"confirmed"`
}

type Snapshot struct {
	ID       string    `json:"id"`
	ShortID  string    `json:"short_id"`
	Time     time.Time `json:"time"`
	Hostname string    `json:"hostname"`
	Paths    []string  `json:"paths"`
	Tags     []string  `json:"tags"`
}

func DefaultConfig() Config {
	return Config{
		SchemaVersion: SchemaVersion,
		Jobs:          []Job{},
		Repositories:  []Repository{},
		Notifications: []NotificationTarget{},
		Settings: Settings{
			ResticPath:       "/usr/local/libexec/backupper/restic",
			RestoreRoot:      "/mnt/user/backupper-restores",
			CatchUpWindowHrs: 24,
			CheckCron:        "0 3 1 * *",
			PruneCron:        "0 4 * * 0",
		},
	}
}
