package v1

import (
	"io"
	"os"
	"path/filepath"

	"quyun/v2/providers/storage"

	"github.com/gofiber/fiber/v3"
)

// @provider
type Storage struct {
	storage *storage.Storage
}

// Upload file
//
// @Router /t/:tenantCode/v1/storage/* [put]
// @Summary Upload file
// @Tags Storage
// @Accept octet-stream
// @Produce json
// @Param expires query string true "Expiry"
// @Param sign query string true "Signature"
// @Success 200 {string} string "success"
// @Bind expires query
// @Bind sign query
func (s *Storage) Upload(ctx fiber.Ctx, expires, sign string) (string, error) {
	key := ctx.Params("*")
	if err := s.storage.Verify("PUT", key, expires, sign); err != nil {
		return "", fiber.NewError(fiber.StatusForbidden, err.Error())
	}

	// Save file
	localPath := s.storage.Config.LocalPath
	if localPath == "" {
		localPath = "./storage"
	}
	fullPath := filepath.Join(localPath, key)
	if err := os.MkdirAll(filepath.Dir(fullPath), 0o755); err != nil {
		return "", err
	}

	f, err := os.Create(fullPath)
	if err != nil {
		return "", err
	}
	defer f.Close()

	if _, err := io.Copy(f, ctx.Request().BodyStream()); err != nil {
		return "", err
	}

	return "success", nil
}

// Download file
//
// @Router /t/:tenantCode/v1/storage/* [get]
// @Summary Download file
// @Tags Storage
// @Accept json
// @Produce octet-stream
// @Param expires query string true "Expiry"
// @Param sign query string true "Signature"
// @Success 200 {file} file
// @Bind expires query
// @Bind sign query
func (s *Storage) Download(ctx fiber.Ctx, expires, sign string) error {
	key := ctx.Params("*")
	if err := s.storage.Verify("GET", key, expires, sign); err != nil {
		return fiber.NewError(fiber.StatusForbidden, err.Error())
	}

	localPath := s.storage.Config.LocalPath
	if localPath == "" {
		localPath = "./storage"
	}
	fullPath := filepath.Join(localPath, key)

	return ctx.SendFile(fullPath)
}
