package storage

import (
	"context"
	"fmt"
	"mime"
	"mime/multipart"
	"path/filepath"
	"strings"
	"time"

	"github.com/google/uuid"
	"github.com/minio/minio-go/v7"

	appcfg "web-qudo-be/config/config"
)

// CMSPreviewURL is the absolute URL served by this API (GET /cms-media/viewer/...) for DB image_url / media_url fields.
func CMSPreviewURL(cfg *appcfg.Config, objectKey string) string {
	base := cfg.APIPublicBaseURL()
	key := strings.TrimPrefix(strings.TrimSpace(objectKey), "/")
	return base + "/cms-media/viewer/" + key
}

var imageExts = map[string]bool{
	".jpg": true, ".jpeg": true, ".png": true, ".gif": true, ".webp": true,
}

var mediaExts = map[string]bool{
	".jpg": true, ".jpeg": true, ".png": true, ".gif": true, ".webp": true,
	".mp4": true, ".webm": true,
}

// UploadCMSObject stores a file in MinIO under cms/{folder}/YYYY/MM/{uuid}{ext} and returns object key + preview URL (API viewer, not direct MinIO).
func UploadCMSObject(ms *appcfg.MinioStorage, folder string, file *multipart.FileHeader, allowVideo bool) (objectKey string, previewURL string, err error) {
	if file == nil {
		return "", "", fmt.Errorf("file is required")
	}
	ext := strings.ToLower(filepath.Ext(file.Filename))
	if allowVideo {
		if !mediaExts[ext] {
			return "", "", fmt.Errorf("unsupported file type (allowed: images, mp4, webm)")
		}
	} else if !imageExts[ext] {
		return "", "", fmt.Errorf("unsupported image type")
	}

	client, err := ms.ConnectMinio()
	if err != nil {
		return "", "", err
	}

	src, err := file.Open()
	if err != nil {
		return "", "", err
	}
	defer src.Close()

	bucket := ms.Cfg.ObjectStorage.MinioStorage.BucketName
	now := time.Now()
	objectKey = fmt.Sprintf("cms/%s/%d/%02d/%s%s", folder, now.Year(), int(now.Month()), uuid.New().String(), ext)

	contentType := mime.TypeByExtension(ext)
	if contentType == "" {
		contentType = "application/octet-stream"
	}

	_, err = client.PutObject(context.Background(), bucket, objectKey, src, file.Size, minio.PutObjectOptions{
		ContentType: contentType,
	})
	if err != nil {
		return "", "", err
	}

	return objectKey, CMSPreviewURL(ms.Cfg, objectKey), nil
}
