package docstore

import (
	"context"
	"strings"

	"github.com/tech/sendico/pkg/merrors"
	"github.com/tech/sendico/pkg/mlogger"
)

// Driver identifies the document storage backend.
type Driver string

const (
	DriverLocal Driver = "local_fs"
	DriverS3    Driver = "s3"
	DriverMinio Driver = "minio"
)

// Config configures the document storage backend.
type Config struct {
	Driver Driver       `yaml:"driver"`
	Local  *LocalConfig `yaml:"local"`
	S3     *S3Config    `yaml:"s3"`
}

// LocalConfig configures local filesystem storage.
type LocalConfig struct {
	RootPath string `yaml:"root_path"`
}

// S3Config configures S3/Minio storage.
type S3Config struct {
	Endpoint        string `yaml:"endpoint"`
	Region          string `yaml:"region"`
	Bucket          string `yaml:"bucket"`
	AccessKeyEnv    string `yaml:"access_key_env"`
	SecretKeyEnv    string `yaml:"secret_access_key_env"`
	AccessKey       string `yaml:"access_key"` //nolint:gosec // config field, not a hardcoded secret
	SecretAccessKey string `yaml:"secret_access_key"`
	UseSSL          bool   `yaml:"use_ssl"`
	ForcePathStyle  bool   `yaml:"force_path_style"`
}

// Store defines storage operations for generated documents.
type Store interface {
	Save(ctx context.Context, key string, data []byte) error
	Load(ctx context.Context, key string) ([]byte, error)
}

// New creates a document store based on config.
func New(logger mlogger.Logger, cfg Config) (Store, error) {
	switch strings.ToLower(string(cfg.Driver)) {
	case string(DriverLocal):
		if cfg.Local == nil {
			return nil, merrors.InvalidArgument("docstore: local config missing")
		}

		return NewLocalStore(logger, *cfg.Local)
	case string(DriverS3), string(DriverMinio):
		if cfg.S3 == nil {
			return nil, merrors.InvalidArgument("docstore: s3 config missing")
		}

		return NewS3Store(logger, *cfg.S3)
	default:
		return nil, merrors.InvalidArgument("docstore: unsupported driver")
	}
}
