package main

import (
	"context"
	"encoding/json"
	"errors"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/sms"
)

type stubMobileVerificationSender struct {
	err error
}

func (sender stubMobileVerificationSender) Send(_ context.Context, _ string, _ string) (sms.Receipt, error) {
	return sms.Receipt{Provider: sms.ProviderNoop}, sender.err
}

func TestE2EMobileVerificationSenderRecordsLatestCode(t *testing.T) {
	t.Parallel()

	recorder := newE2EMobileVerificationRecorder()
	sender := newE2EMobileVerificationSender(stubMobileVerificationSender{}, recorder)

	_, err := sender.Send(context.Background(), "+1 (555) 123-4567", "123456")
	require.NoError(t, err)

	entry, ok, err := recorder.latest("+15551234567")
	require.NoError(t, err)
	require.True(t, ok)
	require.Equal(t, "+15551234567", entry.Mobile)
	require.Equal(t, "123456", entry.Code)
	require.False(t, entry.SentAt.IsZero())
}

func TestE2EMobileVerificationSenderDoesNotRecordFailedSends(t *testing.T) {
	t.Parallel()

	recorder := newE2EMobileVerificationRecorder()
	sender := newE2EMobileVerificationSender(stubMobileVerificationSender{err: errors.New("boom")}, recorder)

	_, err := sender.Send(context.Background(), "+1 (555) 123-4567", "123456")
	require.EqualError(t, err, "boom")

	_, ok, lookupErr := recorder.latest("+15551234567")
	require.NoError(t, lookupErr)
	require.False(t, ok)
}

func TestE2EMobileVerificationLatestHandlerReturnsLatestCode(t *testing.T) {
	t.Parallel()

	recorder := newE2EMobileVerificationRecorder()
	recorder.record("+15551234567", "654321")

	request := httptest.NewRequest(http.MethodGet, "/internal/e2e/mobile-verification/latest?mobile=%2B1%20(555)%20123-4567", nil)
	response := httptest.NewRecorder()

	e2eMobileVerificationLatestHandler(recorder).ServeHTTP(response, request)

	require.Equal(t, http.StatusOK, response.Code)

	var body e2eMobileVerificationEntry
	err := json.NewDecoder(response.Body).Decode(&body)
	require.NoError(t, err)
	require.Equal(t, "+15551234567", body.Mobile)
	require.Equal(t, "654321", body.Code)
	require.False(t, body.SentAt.IsZero())
}

func TestE2EMobileVerificationLatestHandlerRejectsInvalidMobile(t *testing.T) {
	t.Parallel()

	request := httptest.NewRequest(http.MethodGet, "/internal/e2e/mobile-verification/latest?mobile=not-a-phone", nil)
	response := httptest.NewRecorder()

	e2eMobileVerificationLatestHandler(newE2EMobileVerificationRecorder()).ServeHTTP(response, request)

	require.Equal(t, http.StatusBadRequest, response.Code)
	require.Contains(t, response.Body.String(), "mobile")
}
