package api

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"testing"

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

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

func Test_processMessage(t *testing.T) {
	Convey("not valid message", t, func() {
		ctx := context.Background()
		s := &Server{
			stats: &statsd.NoopClient{},
		}
		r, _ := http.NewRequest("POST", "/", bytes.NewBufferString("whatever"))

		w := makeTestRequest(s.processMessage, ctx, r)

		So(w.Code, ShouldEqual, http.StatusOK)
		So(w.Body.String(), ShouldContainSubstring, "error")
	})

	Convey("not valid message body", t, func() {
		ctx := context.Background()
		s := &Server{
			stats: &statsd.NoopClient{},
		}
		r, _ := http.NewRequest("POST", "/", bytes.NewBufferString(`{"Message": "whatever"}`))

		w := makeTestRequest(s.processMessage, ctx, r)

		So(w.Code, ShouldEqual, http.StatusOK)
		So(w.Body.String(), ShouldContainSubstring, "error")
	})

	Convey("error on get annotations enabled", t, func() {
		ctx := context.Background()
		backend := &mocks.Backend{}
		s := &Server{
			backend: backend,
			stats:   &statsd.NoopClient{},
		}

		testChannelID := "1234"
		body := messageBody{ChannelID: 1234}
		b, _ := json.Marshal(body)
		m := message{
			Message: string(b),
		}
		marshalled, _ := json.Marshal(m)

		r, _ := http.NewRequest("POST", "/", bytes.NewBuffer(marshalled))

		backend.On("GetAnnotationsEnabled", ctx, testChannelID).Return(false, fmt.Errorf("what"))

		w := makeTestRequest(s.processMessage, ctx, r)

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

	Convey("disabled", t, func() {
		ctx := context.Background()
		backend := &mocks.Backend{}
		s := &Server{
			backend: backend,
			stats:   &statsd.NoopClient{},
		}

		testChannelID := "1234"
		body := messageBody{ChannelID: 1234}
		b, _ := json.Marshal(body)
		m := message{
			Message: string(b),
		}
		marshalled, _ := json.Marshal(m)

		r, _ := http.NewRequest("POST", "/", bytes.NewBuffer(marshalled))

		backend.On("GetAnnotationsEnabled", ctx, testChannelID).Return(false, nil)

		w := makeTestRequest(s.processMessage, ctx, r)

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

	Convey("enabled", t, func() {
		ctx := context.Background()
		backend := &mocks.Backend{}
		yt := &mocks.YT{}
		s := &Server{
			backend: backend,
			yt:      yt,
			stats:   &statsd.NoopClient{},
		}

		testChannelID := "1234"
		body := messageBody{ChannelID: 1234}
		b, _ := json.Marshal(body)

		backend.On("GetAnnotationsEnabled", ctx, testChannelID).Return(true, nil)

		Convey("stream up", func() {
			m := message{
				Message: string(b),
			}
			m.MessageAttributes.Event.Value = "stream_change_up"
			marshalled, _ := json.Marshal(m)

			yt.On("SetYoutubeAnnotationsStatus", ctx, testChannelID, youtube.StatusUp).Return(nil)
			backend.On("UpdateAnnotationsTimestamp", ctx, testChannelID).Return(nil)

			r, _ := http.NewRequest("POST", "/", bytes.NewBuffer(marshalled))

			w := makeTestRequest(s.processMessage, ctx, r)

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

		Convey("stream down", func() {
			m := message{
				Message: string(b),
			}
			m.MessageAttributes.Event.Value = "stream_change_down"
			marshalled, _ := json.Marshal(m)

			yt.On("SetYoutubeAnnotationsStatus", ctx, testChannelID, youtube.StatusDown).Return(nil)
			backend.On("UpdateAnnotationsTimestamp", ctx, testChannelID).Return(nil)

			r, _ := http.NewRequest("POST", "/", bytes.NewBuffer(marshalled))

			w := makeTestRequest(s.processMessage, ctx, r)

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