package logparse

import (
	"encoding/json"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestLogLine(t *testing.T) {
	baseEvent := func() BackendServiceCall {
		return BackendServiceCall{
			AccessDate: Time(time.Now().UTC().Truncate(time.Second)),
			Latency:    Duration(time.Millisecond),
			Method:     "my-method",
			URLHost:    "my-host",
			URLPath:    "my-path",
			URLScheme:  "my-scheme",
			URLQuery:   "my-query",
		}
	}

	testErrorCases := func(t *testing.T) []*LogLine {
		mustMarshal := func(in interface{}) []byte {
			out, err := json.Marshal(in)
			require.NoError(t, err)
			return out
		}

		return []*LogLine{
			{
				Message: []byte("}"),
			},
			{
				Message: mustMarshal(struct {
					LogType logType `json:"_type"`
				}{logType("potato")}),
			},
		}
	}

	testSuccessPrefixes := func(t *testing.T) []string {
		return []string{
			"",
			"May 15 18:21:50 admin-panel-aws-0a54647ce259b7897.dev.us-west2.justin.tv admin-panel[6871]: [aae01d3c-f98f-49e7-8c87-ecacbbb50dff]",
		}
	}

	t.Run("BackendServiceCallSuccess", func(t *testing.T) {
		t.Run("success", func(t *testing.T) {
			for _, prefix := range testSuccessPrefixes(t) {
				t.Logf("testing prefix: %s", prefix)

				e := struct {
					BackendServiceCallSuccess
					LogType logType `json:"_type"`
				}{
					BackendServiceCallSuccess{
						BackendServiceCall: baseEvent(),
						ResponseStatus:     200,
					},
					logTypeBackendServiceCallSuccess,
				}

				eAsJSON, err := json.Marshal(e)
				require.NoError(t, err)

				l := &LogLine{Message: []byte(prefix + string(eAsJSON))}
				res, ok := l.BackendServiceCallSuccess()
				require.True(t, ok)
				assert.Equal(t, e.BackendServiceCallSuccess, *res)
			}
		})

		t.Run("error cases", func(t *testing.T) {
			for _, l := range testErrorCases(t) {
				_, ok := l.BackendServiceCallSuccess()
				assert.False(t, ok)
			}
		})
	})

	t.Run("BackendServiceCallError", func(t *testing.T) {
		t.Run("success", func(t *testing.T) {
			for _, prefix := range testSuccessPrefixes(t) {
				t.Logf("testing prefix: %s", prefix)

				e := struct {
					BackendServiceCallError
					LogType logType `json:"_type"`
				}{
					BackendServiceCallError{
						BackendServiceCall: baseEvent(),
						ErrorMessage:       "my-error-message",
					},
					logTypeBackendServiceCallError,
				}

				eAsJSON, err := json.Marshal(e)
				require.NoError(t, err)

				l := &LogLine{Message: []byte(prefix + string(eAsJSON))}
				res, ok := l.BackendServiceCallError()
				require.True(t, ok)
				assert.Equal(t, e.BackendServiceCallError, *res)
			}
		})

		t.Run("error cases", func(t *testing.T) {
			for _, l := range testErrorCases(t) {
				_, ok := l.BackendServiceCallError()
				assert.False(t, ok)
			}
		})
	})
}
