package main

import (
	"code.justin.tv/dta/necronomicon-user-api/app"
	"code.justin.tv/dta/necronomicon-user-api/app/test"
	"encoding/json"
	"github.com/goadesign/goa"
	"golang.org/x/net/context"
	"strconv"
	"strings"
	"testing"
)

func setupSnapshotTest(t *testing.T) (db *DB, snapshotId int, service *goa.Service, ctrl *SnapshotController, ctx context.Context) {
	db, snapshotId, err := CreateLotrSnapshots(t)
	if err != nil {
		t.Errorf("Couldn't setup database for test")
		return
	}
	service = goa.New("necronomicon-user-api-test")
	resources := new(Resources)
	resources.db = db
	ctrl = NewSnapshotController(service)
	ctrl.resources = resources
	ctx = context.Background()
	return
}

func TestListSnapshotOKListed(t *testing.T) {
	_, _, service, ctrl, ctx := setupSnapshotTest(t)
	_, snapshots := test.ListSnapshotOKListed(t, ctx, service, ctrl, nil, nil, 100, nil)
	if len(snapshots) != 2 {
		t.Fatalf("Expected 2 snapshots, got %d instead", len(snapshots))
	}
	if snapshots[0].User != "sauron" {
		t.Errorf("Expected snapshot user to be `sauron`, got `%s` instead", snapshots[0].User)
	}
	if snapshots[1].Message != "sam" {
		t.Errorf("Expected snapshot message to be `sam`, got `%s` instead", snapshots[1].Message)
	}
}

func TestShowSnapshotOK(t *testing.T) {
	_, snapshotId, service, ctrl, ctx := setupSnapshotTest(t)
	test.ShowSnapshotOK(t, ctx, service, ctrl, snapshotId, nil)
}

func TestShowSnapshotNotFound(t *testing.T) {
	_, snapshotId, service, ctrl, ctx := setupSnapshotTest(t)
	test.ShowSnapshotNotFound(t, ctx, service, ctrl, snapshotId+999, nil)
}

func TestCreateSnapshotCreated(t *testing.T) {
	db, _, service, ctrl, ctx := setupSnapshotTest(t)
	payload := app.SnapshotPayload{}
	payloadStr := []byte(`{
    "message": "test",
    "environments": [
      {"name": "prod", "operation": "modified", "values": {"app1": {"foo": "bar"}}},
      {"name": "staging", "operation": "modified", "parent": "prod", "values": {"app2": {"x": 123}}}
    ]
  }`)
	err := json.Unmarshal(payloadStr, &payload)
	if err != nil {
		t.Fatalf("Couldn't unmarshal payload: %+v", payload)
	}
	rw := test.CreateSnapshotCreated(t, ctx, service, ctrl, nil, &payload)
	loc := rw.Header().Get("Location")
	if loc == "" {
		t.Fatalf("Missing location header!")
	}
	elems := strings.Split(loc, "/")
	snapshotId, err := strconv.Atoi(elems[len(elems)-1])
	if err != nil {
		t.Fatalf("Invalid location header %v, must end with id", loc)
	}
	snapshot, err := db.GetSnapshot(snapshotId)
	if err != nil {
		t.Fatalf("Couldn't get snapshot ID=%d from the database", snapshotId)
	}
	if snapshot.ID != snapshotId || snapshot.Message != "test" || snapshot.State["prod"].Values["app1"]["foo"].(string) != "bar" {
		t.Fatalf("Got an invalid snapshot: %+v", snapshot)
	}
}
