package storagehandlers

import (
	"context"
	"fmt"
	"log"
	"mime/multipart"
	"os"
	"path/filepath"

	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
)

var (
	useSSL     = false
	bucketName = "storage"
)

type S3_Handler struct {
	minioClient *minio.Client
}

func (s *S3_Handler) Init() error {
	found, err := s.minioClient.BucketExists(context.Background(), bucketName)
	if err != nil {

		log.Println(err)
		return err
	}
	if !found {
		err = s.minioClient.MakeBucket(context.Background(), bucketName, minio.MakeBucketOptions{})
		if err != nil {
			log.Println(err)
			return err
		}
		log.Println("Bucket created successfully")
	}
	log.Println("Bucket found")
	return nil

}

func NewS3Handler() (*S3_Handler, error) {
	MINIO_URL := os.Getenv("MINIO_URL")
	MINIO_ROOT_USER := os.Getenv("MINIO_ROOT_USER")
	MINIO_ROOT_PASSWORD := os.Getenv("MINIO_ROOT_PASSWORD")

	minioClient, err := minio.New(MINIO_URL, &minio.Options{
		Creds:  credentials.NewStaticV4(MINIO_ROOT_USER, MINIO_ROOT_PASSWORD, ""),
		Secure: useSSL,
	})
	if err != nil {
		log.Fatalln(err)
	}
	return &S3_Handler{
		minioClient,
	}, nil
}

func (s *S3_Handler) Add(file *multipart.FileHeader, fileId string) error {
	ctx := context.Background()
	src, err := file.Open()
	if err != nil {
		log.Printf("Error opening file: %v\n", err)
		return err
	}
	defer src.Close()

	extension := filepath.Ext(file.Filename)
	objectName := fileId + extension

	info, err := s.minioClient.PutObject(ctx, bucketName, objectName, src, file.Size, minio.PutObjectOptions{ContentType: "application/octet-stream"})
	if err != nil {
		log.Fatalln(err)
		return err
	}
	log.Printf("Successfully uploaded %s of size %d\n", objectName, info.Size)
	return nil
}

func (s *S3_Handler) Delete(filename string) error {
	opts := minio.RemoveObjectOptions{
		GovernanceBypass: true,
	}
	err := s.minioClient.RemoveObject(context.Background(), bucketName, filename, opts)
	if err != nil {
		log.Fatalln(err)
		return err
	}
	return nil
}

// func (s *S3_Handler) DeleteM(filename string) error {
// 	opts := minio.RemoveObjectOptions{
// 		GovernanceBypass: true,
// 	}
// 	err := s.minioClient.RemoveObjects(context.Background(), bucketName, filename, opts)
// 	if err != nil {
// 		log.Fatalln(err)
// 		return err
// 	}
// 	return nil
// }

func (s *S3_Handler) Get(filename string) (string, error) {
	localPath := filepath.Join(Storagepath, "/tmp/", filename)

	err := s.minioClient.FGetObject(context.Background(), bucketName, filename, localPath, minio.GetObjectOptions{})
	if err != nil {
		fmt.Println(err)
		return "", fmt.Errorf("error downloading file %s: %w", filename, err)
	}
	log.Printf("Successfully downloaded %s\n", filename)
	return localPath, nil

}

func (s *S3_Handler) List() ([]string, error) {
	ctx, cancel := context.WithCancel(context.Background())

	defer cancel()

	objectCh := s.minioClient.ListObjects(ctx, bucketName, minio.ListObjectsOptions{
		Prefix:    "",
		Recursive: true,
	})
	var list []string
	for object := range objectCh {
		if object.Err != nil {
			log.Println(object.Err)
			return nil, object.Err
		}
		list = append(list, object.Key)
	}
	return list, nil
}
