package object_storage

import (
	"context"
	"io"
	"time"
)

type Client interface {
	// PutNewObject создаёт новый объект в хранилище
	//
	// Если такой объект уже существует,
	// то будет возвращена ошибка ErrObjectAlreadyExists.
	PutNewObject(ctx context.Context, objectId string, category Category, r io.Reader, opts ...PutOptions) error

	// GetObject возвращает интерфейс ReadCloser получаемого файла
	//
	// Обязательным условие использования является вызов метода Close()
	// на стороне вызывающего кода.
	//
	// Если такого объекта не существует,
	// то будет возвращена ошибка ErrObjectNotFound.
	GetObject(ctx context.Context, objectId string, category Category, opts ...GetOptions) (io.ReadCloser, error)

	// DeleteObject удаляет объект
	//
	// Если такого объекта не существует,
	// то будет возвращена ошибка ErrObjectNotFound.
	DeleteObject(ctx context.Context, objectId string, category Category, opts ...DeleteOptions) error

	// UpdateObject обновляет содержимое файла по переданному
	// названию и типу
	//
	// Если такого объекта не существует,
	// то будет возвращена ошибка ErrObjectNotFound.
	UpdateObject(ctx context.Context, objectId string, category Category, r io.Reader, opts ...UpdateOptions) error

	// GetPresignedLink возвращает временную публичную ссылку для скачивания
	// на запрашиваемый объект с переданным TTL.
	//
	// Если такого объекта не существует,
	// то будет возвращена ошибка ErrObjectNotFound.
	//
	// Для S3 хранилища: если не указан ttl в LinkOptions, то будет использоваться дефолтный
	// переданный в конфиге.
	GetPresignedLink(ctx context.Context, objectId string, category Category, opts ...LinkOptions) (string, error)

	// TODO: по необходимости можно расширять другими методами
}

type (
	// LocalPrefix - префикс хранимого файла, относительно категории.
	// Например "logos/**2012/02/15**/logo.png"

	PutOptions struct {
		ContentType string
		LocalPrefix []string
	}

	GetOptions struct {
		LocalPrefix []string
	}

	UpdateOptions struct {
		ContentType string
		LocalPrefix []string
	}

	DeleteOptions struct {
		LocalPrefix []string
	}

	LinkOptions struct {
		LocalPrefix []string
		TTL         *time.Duration
	}
)

type (
	Category   string
	Config     any
	ClientType uint
)

const (
	ClientTypeS3 ClientType = iota
)

const (
	LogoCategory     Category = "logos"
	DocumentCategory Category = "documents"

	keySeparator = "/"
)
