package errortracking

import (
	"fmt"
	"testing"

	"github.com/getsentry/sentry-go"
	"github.com/stretchr/testify/require"
)

func TestCaptureWithStackTrace(t *testing.T) {
	innerError := fmt.Errorf("inner error")
	midError := fmt.Errorf("mid error: %w", innerError)
	err := fmt.Errorf("top error: %w", midError)

	tcs := map[string]struct {
		withStackTrace           bool
		expectedExceptionsLength int
	}{
		"with_stack_trace": {
			withStackTrace:           true,
			expectedExceptionsLength: 3,
		},
		"without_stack_trace": {
			withStackTrace:           false,
			expectedExceptionsLength: 1,
		},
	}

	for tn, tc := range tcs {
		t.Run(tn, func(t *testing.T) {
			sm := &sentryMock{}
			tracker := newSentryTracker(sm)

			if tc.withStackTrace {
				tracker.Capture(err, WithStackTrace())
				require.Len(t, sm.event.Exception, tc.expectedExceptionsLength)

				// exceptions are reversed so that the inner-most error is reported first
				require.Equal(t, innerError.Error(), sm.event.Exception[0].Value)
				require.Equal(t, midError.Error(), sm.event.Exception[1].Value)
				require.Equal(t, err.Error(), sm.event.Exception[2].Value)
			} else {
				tracker.Capture(err)

				require.Len(t, sm.event.Exception, tc.expectedExceptionsLength)
				require.Equal(t, err.Error(), sm.event.Exception[0].Value, "must match top error")
			}
		})
	}
}

type sentryMock struct {
	event *sentry.Event
}

func (sm *sentryMock) CaptureEvent(event *sentry.Event) *sentry.EventID {
	sm.event = event

	return &event.EventID
}
