package api

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

	"code.justin.tv/video/spectre/auth/authtest"
	"code.justin.tv/video/spectre/backend"
	"code.justin.tv/video/spectre/backend/backendtest"
	. "github.com/smartystreets/goconvey/convey"
	"github.com/zenazn/goji/web"
)

func performShowPlaylistRequest(c web.C) *httptest.ResponseRecorder {
	router := Router{Backend: backendtest.NewBackend(), AuthHandler: authtest.NewHandler()}
	w := httptest.NewRecorder()

	router.ShowPlaylist(c, w, &http.Request{})
	return w
}

func TestShowPlaylist(t *testing.T) {
	Convey("shows a valid playlist", t, func() {
		c := web.C{URLParams: map[string]string{
			"channel_id":  "50",
			"playlist_id": "2",
		}}

		w := performShowPlaylistRequest(c)
		So(w.Code, ShouldEqual, http.StatusOK)
	})

	Convey("404s for missing playlist", t, func() {
		c := web.C{URLParams: map[string]string{
			"channel_id":  "50",
			"playlist_id": "3",
		}}
		w := performShowPlaylistRequest(c)
		So(w.Code, ShouldEqual, http.StatusNotFound)
	})
}

func performCreatePlaylistRequest(c web.C, body backend.PlaylistParams) *httptest.ResponseRecorder {
	router := Router{Backend: backendtest.NewBackend(), AuthHandler: authtest.NewHandler()}
	w := httptest.NewRecorder()

	requestBody, _ := json.Marshal(body)
	r, _ := http.NewRequest("", "", bytes.NewBuffer(requestBody))

	router.CreatePlaylist(c, w, r)
	return w
}

func TestCreatePlaylist(t *testing.T) {
	Convey("creates a valid playlist", t, func() {

		c := web.C{URLParams: map[string]string{
			"channel_id": "40000",
		}}

		body := backend.PlaylistParams{}

		w := performCreatePlaylistRequest(c, body)
		So(w.Code, ShouldEqual, http.StatusOK)
		So(w.Body.String(), ShouldContainSubstring, "40000")
	})

	Convey("errors if channel already has playlist", t, func() {
		c := web.C{URLParams: map[string]string{
			"channel_id": "50",
		}}

		body := backend.PlaylistParams{}

		w := performCreatePlaylistRequest(c, body)
		So(w.Code, ShouldEqual, http.StatusBadRequest)
	})
}

func performUpdatePlaylistRequest(c web.C, body backend.PlaylistParams) *httptest.ResponseRecorder {
	router := Router{Backend: backendtest.NewBackend(), AuthHandler: authtest.NewHandler()}
	w := httptest.NewRecorder()

	requestBody, _ := json.Marshal(body)
	r, _ := http.NewRequest("", "", bytes.NewBuffer(requestBody))

	router.UpdatePlaylist(c, w, r)
	return w
}

func TestUpdatePlaylist(t *testing.T) {
	Convey("updates a valid playlist", t, func() {

		c := web.C{URLParams: map[string]string{
			"channel_id":  "50",
			"playlist_id": "2",
		}}

		body := backend.PlaylistParams{
		// Playlist: `{"vod_ids": ["123", "456"]}`,
		}

		w := performUpdatePlaylistRequest(c, body)
		So(w.Code, ShouldEqual, http.StatusOK)
	})

	Convey("404s for invalid playlist", t, func() {
		c := web.C{URLParams: map[string]string{
			"channel_id":  "50",
			"playlist_id": "3",
		}}

		body := backend.PlaylistParams{
		// Playlist: `{"vod_ids": ["123", "456"]}`,
		}

		w := performUpdatePlaylistRequest(c, body)
		So(w.Code, ShouldEqual, http.StatusNotFound)
	})

	Convey("400s for active channel", t, func() {
		c := web.C{URLParams: map[string]string{
			"channel_id":  "10",
			"playlist_id": "1",
		}}

		body := backend.PlaylistParams{
		// Playlist: `{"vod_ids": ["123", "456"]}`,
		}

		w := performUpdatePlaylistRequest(c, body)
		So(w.Code, ShouldEqual, http.StatusBadRequest)
	})
}

func performDestroyPlaylistRequest(c web.C) *httptest.ResponseRecorder {
	router := Router{Backend: backendtest.NewBackend(), AuthHandler: authtest.NewHandler()}
	w := httptest.NewRecorder()

	router.DestroyPlaylist(c, w, &http.Request{})
	return w
}

func TestDestroyPlaylist(t *testing.T) {
	Convey("deletes an existing playlist", t, func() {

		c := web.C{URLParams: map[string]string{
			"channel_id":  "50",
			"playlist_id": "2",
		}}

		w := performDestroyPlaylistRequest(c)
		So(w.Code, ShouldEqual, http.StatusOK)
	})

	Convey("404s for invalid playlist", t, func() {
		c := web.C{URLParams: map[string]string{
			"channel_id":  "50",
			"playlist_id": "3",
		}}
		w := performDestroyPlaylistRequest(c)
		So(w.Code, ShouldEqual, http.StatusNotFound)
	})

	Convey("404s for playlist belonging to another user", t, func() {
		c := web.C{URLParams: map[string]string{
			"channel_id":  "50",
			"playlist_id": "1",
		}}
		w := performDestroyPlaylistRequest(c)
		So(w.Code, ShouldEqual, http.StatusNotFound)
	})

	Convey("404s for invalid channel", t, func() {
		c := web.C{URLParams: map[string]string{
			"channel_id":  "7000",
			"playlist_id": "1",
		}}
		w := performDestroyPlaylistRequest(c)
		So(w.Code, ShouldEqual, http.StatusNotFound)
	})

	Convey("400s for active channel", t, func() {
		c := web.C{URLParams: map[string]string{
			"channel_id":  "10",
			"playlist_id": "1",
		}}
		w := performDestroyPlaylistRequest(c)
		So(w.Code, ShouldEqual, http.StatusBadRequest)
	})
}
