package file_storage

import (
	"context"
	"crypto/rand"
	"encoding/hex"
	"errors"
	"strings"
)

// ErrFileNotFound — файл не найден в хранилище. Возвращается Get для
// отсутствующих объектов (маппинг smithy-ошибок NoSuchKey/NotFound).
var ErrFileNotFound = errors.New("файл не найден")

type File struct {
	Name string
	Data []byte
	Mime string
}

type IFileStorage interface {
	Put(ctx context.Context, file *File) error
	Get(ctx context.Context, filename string) (*File, error)
	Delete(ctx context.Context, filename string) error
	MimeType(filename string) string
}

// FileType возвращает категорию файла по расширению имени: pdf → "pdf",
// jpg/jpeg/png/gif/webp → "image", mp3/ogg/wav → "audio", иначе "".
// Регистр расширения и query-параметры игнорируются.
// Используется для деривации file_type улик (см. storytelling.Application).
func FileType(filename string) string {
	ext := strings.ToLower(extension(filename))
	switch ext {
	case ".pdf":
		return "pdf"
	case ".jpg", ".jpeg", ".png", ".gif", ".webp":
		return "image"
	case ".mp3", ".ogg", ".wav":
		return "audio"
	default:
		return ""
	}
}

// NewName возвращает случайное имя файла в хранилище (hex-токен 16 байт
// без расширения): исключает коллизии в общем бакете. Расширение добавляет
// вызывающий код.
func NewName() (string, error) {
	var b [16]byte
	if _, err := rand.Read(b[:]); err != nil {
		return "", err
	}
	return hex.EncodeToString(b[:]), nil
}
