package media

import (
	"context"
	"errors"
	"io"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	"time"

	"github.com/gin-gonic/gin"

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

type fakeStore struct {
	objects map[string]string
}

func (f *fakeStore) Upload(_ context.Context, object string, r io.Reader, _ string) error {
	data, _ := io.ReadAll(r)
	f.objects[object] = string(data)
	return nil
}

func (f *fakeStore) Open(_ context.Context, object string) (io.ReadCloser, error) {
	data, ok := f.objects[object]
	if !ok {
		return nil, errors.New("not found")
	}
	return io.NopCloser(strings.NewReader(data)), nil
}

func (f *fakeStore) Delete(_ context.Context, object string) error {
	delete(f.objects, object)
	return nil
}

func (f *fakeStore) DownloadURL(_ context.Context, object string, _ time.Duration) (string, error) {
	return "http://store/" + object, nil
}

var _ gcs.Store = (*fakeStore)(nil)

func TestUploadReturnsURL(t *testing.T) {
	store := &fakeStore{objects: map[string]string{}}
	svc := New(store)

	url, err := svc.Upload(context.Background(), "ebook/a.pdf", strings.NewReader("data"), "application/pdf")
	if err != nil {
		t.Fatal(err)
	}
	if url != "http://store/ebook/a.pdf" {
		t.Fatalf("url = %q", url)
	}
}

func TestProxyHandler(t *testing.T) {
	gin.SetMode(gin.TestMode)
	store := &fakeStore{objects: map[string]string{"ebook/a.pdf": "PDFDATA"}}
	svc := New(store)

	r := gin.New()
	r.GET("/ebook/proxy", svc.ProxyHandler())

	t.Run("missing object", func(t *testing.T) {
		w := httptest.NewRecorder()
		req := httptest.NewRequestWithContext(context.Background(), http.MethodGet, "/ebook/proxy", nil)
		r.ServeHTTP(w, req)
		if w.Code != http.StatusBadRequest {
			t.Fatalf("code = %d", w.Code)
		}
	})

	t.Run("not found", func(t *testing.T) {
		w := httptest.NewRecorder()
		req := httptest.NewRequestWithContext(context.Background(), http.MethodGet, "/ebook/proxy?object=missing.pdf", nil)
		r.ServeHTTP(w, req)
		if w.Code != http.StatusNotFound {
			t.Fatalf("code = %d", w.Code)
		}
	})

	t.Run("streams pdf", func(t *testing.T) {
		w := httptest.NewRecorder()
		req := httptest.NewRequestWithContext(context.Background(), http.MethodGet, "/ebook/proxy?object=ebook/a.pdf", nil)
		r.ServeHTTP(w, req)
		if w.Code != http.StatusOK {
			t.Fatalf("code = %d", w.Code)
		}
		if w.Header().Get("Content-Type") != "application/pdf" {
			t.Fatalf("content-type = %q", w.Header().Get("Content-Type"))
		}
		if w.Body.String() != "PDFDATA" {
			t.Fatalf("body = %q", w.Body.String())
		}
	})
}
