package config

import (
	"errors"
	"fmt"
	"time"

	"github.com/robfig/cron/v3"
	"github.com/tidbcloud/observability/pkg/common/constants"
)

// Config holds the configuration for the backup manager
type Config struct {
	// params for VMBackup
	StorageDataPath       string
	SnapshotCreateURL     string
	Destination           string
	Concurrency           int
	FullBackupConcurrency int
	MaxBytesPerSecond     string // Will be parsed by underlying vmbackup library
	CustomS3Endpoint      string // Custom S3 endpoint for use with S3-compatible storages (e.g. MinIO). S3 is used if not set
	S3ForcePathStyle      bool   // Prefixing endpoint with bucket name when set false, true by default.

	// Backup scheduler settings
	HttpListenAddr            string
	IncrSchedule              string
	FullSchedule              string
	BackupRetention           time.Duration
	VMRetentionPeriod         time.Duration
	VMRetentionTimeZoneOffset time.Duration
	DisableFullBackup         bool
	DisableBackupRetention    bool
	Migrate                   bool
	Vendor                    constants.ProvidedVendor
	Region                    string
}

// Validate checks if the configuration is valid
func (c *Config) Validate() error {
	if c.StorageDataPath == "" {
		return errors.New("storageDataPath cannot be empty")
	}

	if c.Destination == "" {
		return errors.New("destination cannot be empty")
	}

	if c.SnapshotCreateURL == "" {
		return errors.New("snapshot.createURL cannot be empty")
	}

	if c.Concurrency <= 0 {
		return errors.New("concurrency must be greater than 0")
	}

	if c.FullBackupConcurrency <= 0 {
		return errors.New("fullBackupConcurrency must be greater than 0")
	}

	// MaxBytesPerSecond will be validated by the underlying backup library.
	// A basic check could be if it's non-empty and not obviously invalid,
	// but delegating to the library that uses it is often safer.

	if c.IncrSchedule == "" {
		return errors.New("incrSchedule cannot be empty")
	}
	_, err := cron.ParseStandard(c.IncrSchedule)
	if err != nil {
		return fmt.Errorf("invalid incrSchedule format: %w", err)
	}

	if c.FullSchedule != "" {
		_, err := cron.ParseStandard(c.FullSchedule)
		if err != nil {
			return fmt.Errorf("invalid fullSchedule format: %w", err)
		}
	}

	if c.BackupRetention < 0 {
		return errors.New("backupRetention cannot be negative")
	}

	if c.VMRetentionPeriod < 0 {
		return errors.New("vmRetentionPeriod cannot be negative")
	}

	if c.Vendor != constants.AWS && c.Vendor != constants.GCP && c.Vendor != constants.Azure && c.Vendor != constants.AliCloud {
		return fmt.Errorf("invalid vendor: %s", c.Vendor)
	}

	return nil
}
