package auth

import (
	"bytes"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/store/identity"
)

func TestDesktopOnboardingProvisioningRequiresEnabledClientAndRegistrationAfterCutoff(t *testing.T) {
	cutoff := "2026-08-09T00:00:00Z"
	for _, test := range []struct {
		name    string
		user    identity.User
		enabled bool
		cutoff  string
		want    bool
	}{
		{
			name:    "eligible new user",
			user:    identity.User{CreatedAt: time.Date(2026, 8, 9, 0, 0, 1, 0, time.UTC)},
			enabled: true,
			cutoff:  cutoff,
			want:    true,
		},
		{
			name:   "disabled client",
			user:   identity.User{CreatedAt: time.Date(2026, 8, 9, 0, 0, 1, 0, time.UTC)},
			cutoff: cutoff,
		},
		{
			name:    "registration before cutoff",
			user:    identity.User{CreatedAt: time.Date(2026, 8, 8, 23, 59, 59, 0, time.UTC)},
			enabled: true,
			cutoff:  cutoff,
		},
		{
			name:    "registration exactly at cutoff",
			user:    identity.User{CreatedAt: time.Date(2026, 8, 9, 0, 0, 0, 0, time.UTC)},
			enabled: true,
			cutoff:  cutoff,
		},
		{
			name:    "missing registration time",
			enabled: true,
			cutoff:  cutoff,
		},
		{
			name:    "malformed cutoff",
			user:    identity.User{CreatedAt: time.Date(2026, 8, 9, 0, 0, 1, 0, time.UTC)},
			enabled: true,
			cutoff:  "2026-08-09",
		},
	} {
		t.Run(test.name, func(t *testing.T) {
			require.Equal(t, test.want, desktopOnboardingProvisioningEligible(test.user, test.enabled, test.cutoff))
		})
	}
}

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

	tests := []struct {
		name     string
		body     string
		wantBody string
	}{
		{
			name:     "invalid email",
			body:     `{"email":"not-an-email","name":"User","password":"secret"}`,
			wantBody: "invalid email address",
		},
		{
			name:     "empty name",
			body:     `{"email":"user@example.com","name":"   ","password":"secret"}`,
			wantBody: "name is required",
		},
		{
			name:     "short password",
			body:     `{"email":"user@example.com","name":"User","password":"12345"}`,
			wantBody: "Password must be at least 6 characters",
		},
	}

	handler := &RegistrationHandler{}
	router := gin.New()
	router.POST("/api/v1/auth/register", handler.Register)

	for _, tt := range tests {
		tt := tt
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			recorder := httptest.NewRecorder()
			request := httptest.NewRequest(http.MethodPost, "/api/v1/auth/register", bytes.NewBufferString(tt.body))
			router.ServeHTTP(recorder, request)

			require.Equal(t, http.StatusBadRequest, recorder.Code)
			require.Contains(t, recorder.Body.String(), tt.wantBody)
		})
	}
}

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

	handler := &RegistrationHandler{passwordAuthDisabled: true}
	router := gin.New()
	router.POST("/api/v1/auth/register", handler.Register)

	recorder := httptest.NewRecorder()
	request := httptest.NewRequest(http.MethodPost, "/api/v1/auth/register", bytes.NewBufferString(`{"email":"user@example.com","name":"User","password":"secret"}`))
	router.ServeHTTP(recorder, request)

	require.Equal(t, http.StatusServiceUnavailable, recorder.Code)
	require.Contains(t, recorder.Body.String(), "Password auth is disabled")
}
