package api

import (
	"fmt"
	"net/http"
	"testing"

	"github.com/cactus/go-statsd-client/statsd"
	. "github.com/smartystreets/goconvey/convey"
	"goji.io/pattern"
	"golang.org/x/net/context"

	"code.justin.tv/live/yt-live-annotations/app/api/mocks"
	"code.justin.tv/live/yt-live-annotations/youtube"

	youtube_api "google.golang.org/api/youtube/v3"
)

func Test_getAnnotations(t *testing.T) {
	testUserID := "24534"
	Convey("error", t, func() {
		ctx := context.Background()
		ctx = context.WithValue(ctx, pattern.Variable("user_id"), testUserID)
		yt := &mocks.YT{}
		s := &Server{
			yt:    yt,
			stats: &statsd.NoopClient{},
		}
		r, _ := http.NewRequest("GET", "/annotations", nil)

		yt.On("GetYoutubeAnnotations", ctx, testUserID).Return(nil, fmt.Errorf("what"))
		w := makeTestRequest(s.getExistingAnnotations, ctx, r)

		So(w.Code, ShouldEqual, http.StatusInternalServerError)
		So(w.Body.String(), ShouldContainSubstring, "what")
	})

	Convey("success", t, func() {
		ctx := context.Background()
		ctx = context.WithValue(ctx, pattern.Variable("user_id"), testUserID)
		yt := &mocks.YT{}
		s := &Server{
			yt:    yt,
			stats: &statsd.NoopClient{},
		}
		r, _ := http.NewRequest("GET", "/annotations", nil)

		yt.On("GetYoutubeAnnotations", ctx, testUserID).Return(&youtube_api.InvideoPromotion{Items: []*youtube_api.PromotedItem{}}, nil)
		w := makeTestRequest(s.getExistingAnnotations, ctx, r)

		So(w.Code, ShouldEqual, http.StatusOK)
	})
}

func Test_addAnnotation(t *testing.T) {
	testUserID := "24534"
	Convey("error", t, func() {
		ctx := context.Background()
		ctx = context.WithValue(ctx, pattern.Variable("user_id"), testUserID)
		yt := &mocks.YT{}
		s := &Server{
			yt:    yt,
			stats: &statsd.NoopClient{},
		}
		r, _ := http.NewRequest("POST", "/annotations", nil)

		yt.On("SetYoutubeAnnotationsStatus", ctx, testUserID, youtube.StatusUp).Return(fmt.Errorf("what"))
		w := makeTestRequest(s.addAnnotation, ctx, r)

		So(w.Code, ShouldEqual, http.StatusInternalServerError)
		So(w.Body.String(), ShouldContainSubstring, "what")
	})
	Convey("success", t, func() {
		ctx := context.Background()
		ctx = context.WithValue(ctx, pattern.Variable("user_id"), testUserID)
		yt := &mocks.YT{}
		s := &Server{
			yt:    yt,
			stats: &statsd.NoopClient{},
		}
		r, _ := http.NewRequest("POST", "/annotations", nil)

		yt.On("SetYoutubeAnnotationsStatus", ctx, testUserID, youtube.StatusUp).Return(nil)
		w := makeTestRequest(s.addAnnotation, ctx, r)

		So(w.Code, ShouldEqual, http.StatusOK)
	})
}

func Test_removeAnnotation(t *testing.T) {
	testUserID := "24534"
	Convey("error", t, func() {
		ctx := context.Background()
		ctx = context.WithValue(ctx, pattern.Variable("user_id"), testUserID)
		yt := &mocks.YT{}
		s := &Server{
			yt:    yt,
			stats: &statsd.NoopClient{},
		}
		r, _ := http.NewRequest("DELETE", "/annotations", nil)

		yt.On("SetYoutubeAnnotationsStatus", ctx, testUserID, youtube.StatusDown).Return(fmt.Errorf("what"))
		w := makeTestRequest(s.removeAnnotation, ctx, r)

		So(w.Code, ShouldEqual, http.StatusInternalServerError)
		So(w.Body.String(), ShouldContainSubstring, "what")
	})
	Convey("success", t, func() {
		ctx := context.Background()
		ctx = context.WithValue(ctx, pattern.Variable("user_id"), testUserID)
		yt := &mocks.YT{}
		s := &Server{
			yt:    yt,
			stats: &statsd.NoopClient{},
		}
		r, _ := http.NewRequest("DELETE", "/annotations", nil)

		yt.On("SetYoutubeAnnotationsStatus", ctx, testUserID, youtube.StatusDown).Return(nil)
		w := makeTestRequest(s.removeAnnotation, ctx, r)

		So(w.Code, ShouldEqual, http.StatusOK)
	})
}

func Test_clearAnnotations(t *testing.T) {
	testUserID := "24534"
	Convey("error", t, func() {
		ctx := context.Background()
		ctx = context.WithValue(ctx, pattern.Variable("user_id"), testUserID)
		yt := &mocks.YT{}
		s := &Server{
			yt:    yt,
			stats: &statsd.NoopClient{},
		}
		r, _ := http.NewRequest("DELETE", "/annotations", nil)

		yt.On("ClearYoutubeAnnotations", ctx, testUserID).Return(fmt.Errorf("what"))
		w := makeTestRequest(s.clearAllAnnotations, ctx, r)

		So(w.Code, ShouldEqual, http.StatusInternalServerError)
		So(w.Body.String(), ShouldContainSubstring, "what")
	})
	Convey("success", t, func() {
		ctx := context.Background()
		ctx = context.WithValue(ctx, pattern.Variable("user_id"), testUserID)
		yt := &mocks.YT{}
		s := &Server{
			yt:    yt,
			stats: &statsd.NoopClient{},
		}
		r, _ := http.NewRequest("DELETE", "/annotations", nil)

		yt.On("ClearYoutubeAnnotations", ctx, testUserID).Return(nil)
		w := makeTestRequest(s.clearAllAnnotations, ctx, r)

		So(w.Code, ShouldEqual, http.StatusOK)
	})
}
