package service

import (
	"context"
	"io"
	"time"

	"github.com/minio/minio-go/v7"
	"github.com/rs/zerolog"
)

// AsyncUploader menangani proses upload secara asynchronous
type UploadService interface {
	UploadFile(ctx context.Context, minioClient *minio.Client, uploadID string, reader io.Reader, bucketName string, objectName string, size int64, contentType string) error
}

type uploadService struct {
	uploadManager UploadManager
	Log           zerolog.Logger
}

func NewUploadService(uploadManager UploadManager, log zerolog.Logger) UploadService {
	return &uploadService{
		uploadManager: uploadManager,
		Log:           log,
	}
}

func (u *uploadService) UploadFile(ctx context.Context, minioClient *minio.Client, uploadID string, reader io.Reader, bucketName string, objectName string, size int64, contentType string) error {
	status := &UploadStatus{
		FileName:   objectName,
		Size:       size,
		Progress:   0,
		Status:     "uploading",
		ObjectName: objectName,
		BucketName: bucketName,
		StartTime:  time.Now(),
	}

	u.uploadManager.Add(uploadID, status)

	u.Log.Info().Str("timestamp", time.Now().
		Format(time.RFC3339)).Str("Service:Resource", "UploadService::UploadFile").
		Interface("add status", status).Msg("")

	// Upload ke Minio
	_, err := minioClient.PutObject(
		ctx,
		bucketName,
		objectName,
		reader,
		size,
		minio.PutObjectOptions{
			ContentType: contentType,
			PartSize:    10 * 1024 * 1024, // 10MB part size
		},
	)

	if err != nil {
		u.uploadManager.UpdateStatus(uploadID, "error", err)

		u.Log.Info().Str("timestamp", time.Now().
			Format(time.RFC3339)).Str("Service:Resource", "UploadService::UploadFile").
			Interface("error when upload", err).Msg("")
	}

	u.uploadManager.UpdateStatus(uploadID, "completed", nil)
	return nil
}