package media

import (
	"context"
	"io"
	"net/http"
	"path"
	"strings"
	"time"

	"github.com/gin-gonic/gin"

	"gitlab.com/dynaweb/ains-microservices/pkg/gcs"
)

type Service struct {
	store gcs.Store
	ttl   time.Duration
}

func New(store gcs.Store) *Service {
	return &Service{store: store, ttl: 15 * time.Minute}
}

func (s *Service) Upload(ctx context.Context, object string, r io.Reader, contentType string) (string, error) {
	if err := s.store.Upload(ctx, object, r, contentType); err != nil {
		return "", err
	}
	return s.store.DownloadURL(ctx, object, s.ttl)
}

func (s *Service) URL(ctx context.Context, object string) (string, error) {
	return s.store.DownloadURL(ctx, object, s.ttl)
}

func (s *Service) ProxyHandler() gin.HandlerFunc {
	return func(c *gin.Context) {
		object := strings.TrimSpace(c.Query("object"))
		if object == "" {
			c.String(http.StatusBadRequest, "missing object")
			return
		}

		body, err := s.store.Open(c.Request.Context(), object)
		if err != nil {
			c.String(http.StatusNotFound, "not found")
			return
		}
		defer func() { _ = body.Close() }()

		contentType := contentTypeFor(object)
		c.Header("Content-Type", contentType)
		c.Header("Content-Disposition", "inline")
		c.Status(http.StatusOK)
		if _, err := io.Copy(c.Writer, body); err != nil {
			_ = c.Error(err)
		}
	}
}

func contentTypeFor(object string) string {
	switch strings.ToLower(path.Ext(object)) {
	case ".pdf":
		return "application/pdf"
	case ".png":
		return "image/png"
	case ".jpg", ".jpeg":
		return "image/jpeg"
	case ".gif":
		return "image/gif"
	case ".webp":
		return "image/webp"
	case ".svg":
		return "image/svg+xml"
	default:
		return "application/octet-stream"
	}
}
