//go:build integration

package inttest

import (
	"context"
	"net/http"
	"net/http/httptest"
	"slices"
	"strings"
	"testing"

	"github.com/google/uuid"
	"go.uber.org/zap/zaptest"

	"scrabble/backend/internal/account"
	"scrabble/backend/internal/server"
	"scrabble/backend/internal/session"
)

// TestTelegramAuthSeedsPromoVariantForNewUserOnly drives the sessions/telegram endpoint
// to confirm a promo deep-link start-param widens a brand-new account's variant
// preferences — English Scrabble on top of the default pair, but only for a
// non-Russian-speaking arrival — that a new account with no such payload keeps the
// default, and that an existing account is never re-seeded on a later login (the
// new-user-only contract).
func TestTelegramAuthSeedsPromoVariantForNewUserOnly(t *testing.T) {
	srv := server.New(":0", server.Deps{
		Logger:   zaptest.NewLogger(t),
		DB:       testDB,
		Accounts: account.NewStore(testDB),
		Sessions: session.NewService(session.NewStore(testDB), session.NewCache()),
		Notifier: &captureNotifier{},
	})
	h := srv.Handler()

	post := func(ext, language, startParam string) {
		body := `{"external_id":"` + ext + `","language_code":"` + language + `","first_name":"Promo"`
		if startParam != "" {
			body += `,"start_param":"` + startParam + `"`
		}
		body += `}`
		rec := httptest.NewRecorder()
		req := httptest.NewRequest(http.MethodPost, "/api/v1/internal/sessions/telegram", strings.NewReader(body))
		req.Header.Set("Content-Type", "application/json")
		h.ServeHTTP(rec, req)
		if rec.Code != http.StatusOK {
			t.Fatalf("telegram auth = %d: %s", rec.Code, rec.Body.String())
		}
	}
	store := account.NewStore(testDB)
	reload := func(ext string) []string {
		acc, err := store.AccountByIdentity(context.Background(), account.KindTelegram, ext)
		if err != nil {
			t.Fatalf("lookup %s: %v", ext, err)
		}
		return acc.VariantPreferences
	}

	// An English-speaking arrival on a promo deep-link gains English Scrabble on top of
	// the default pair, so a native English player is not lost at the door.
	promoExt := "tg-" + uuid.NewString()
	post(promoExt, "en", "verudit_ru-scrabble_en")
	if got, want := reload(promoExt), []string{"erudit_ru", "scrabble_ru", "scrabble_en"}; !slices.Equal(got, want) {
		t.Errorf("english promo account variants = %v, want %v", got, want)
	}

	// A Russian-speaking arrival on the same link stays on the default pair: the two
	// Russian-alphabet games serve them, and English would only clutter New Game.
	ruExt := "tg-" + uuid.NewString()
	post(ruExt, "ru", "verudit_ru-scrabble_en")
	if got, want := reload(ruExt), []string{"erudit_ru", "scrabble_ru"}; !slices.Equal(got, want) {
		t.Errorf("russian promo account variants = %v, want %v", got, want)
	}

	// A brand-new account with no promo payload keeps the default.
	plainExt := "tg-" + uuid.NewString()
	post(plainExt, "en", "")
	if got, want := reload(plainExt), []string{"erudit_ru", "scrabble_ru"}; !slices.Equal(got, want) {
		t.Errorf("plain new account variants = %v, want %v", got, want)
	}

	// A later login of the promo account, even via a different payload, must not re-seed:
	// the seed is first-contact only.
	post(promoExt, "en", "vscrabble_ru")
	if got, want := reload(promoExt), []string{"erudit_ru", "scrabble_ru", "scrabble_en"}; !slices.Equal(got, want) {
		t.Errorf("existing account re-seeded = %v, want unchanged %v", got, want)
	}
}
