package services

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

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

	"github.com/treytartt/honeydue-api/internal/config"
	"github.com/treytartt/honeydue-api/internal/dto/requests"
	"github.com/treytartt/honeydue-api/internal/repositories"
	"github.com/treytartt/honeydue-api/internal/testutil"
)

func setupAuthService(t *testing.T) (*AuthService, *repositories.UserRepository) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	notifRepo := repositories.NewNotificationRepository(db)
	cfg := &config.Config{
		Server: config.ServerConfig{
			DebugFixedCodes: true,
		},
		Security: config.SecurityConfig{
			SecretKey:            "test-secret",
			ConfirmationExpiry:   24 * time.Hour,
			PasswordResetExpiry:  15 * time.Minute,
			MaxPasswordResetRate: 3,
			TokenExpiryDays:      90,
			TokenRefreshDays:     60,
		},
	}
	service := NewAuthService(userRepo, cfg)
	service.SetNotificationRepository(notifRepo)
	return service, userRepo
}

// === Login ===

func TestAuthService_Login(t *testing.T) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	cfg := &config.Config{
		Security: config.SecurityConfig{SecretKey: "test-secret"},
	}
	service := NewAuthService(userRepo, cfg)

	testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")

	req := &requests.LoginRequest{
		Username: "testuser",
		Password: "Password123",
	}

	resp, err := service.Login(req)
	require.NoError(t, err)
	assert.NotEmpty(t, resp.Token)
	assert.Equal(t, "testuser", resp.User.Username)
}

func TestAuthService_Login_ByEmail(t *testing.T) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	cfg := &config.Config{
		Security: config.SecurityConfig{SecretKey: "test-secret"},
	}
	service := NewAuthService(userRepo, cfg)

	testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")

	req := &requests.LoginRequest{
		Email:    "test@test.com",
		Password: "Password123",
	}

	resp, err := service.Login(req)
	require.NoError(t, err)
	assert.NotEmpty(t, resp.Token)
}

func TestAuthService_Login_InvalidCredentials(t *testing.T) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	cfg := &config.Config{
		Security: config.SecurityConfig{SecretKey: "test-secret"},
	}
	service := NewAuthService(userRepo, cfg)

	testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")

	req := &requests.LoginRequest{
		Username: "testuser",
		Password: "WrongPassword1",
	}

	_, err := service.Login(req)
	testutil.AssertAppError(t, err, http.StatusUnauthorized, "error.invalid_credentials")
}

func TestAuthService_Login_UserNotFound(t *testing.T) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	cfg := &config.Config{
		Security: config.SecurityConfig{SecretKey: "test-secret"},
	}
	service := NewAuthService(userRepo, cfg)

	req := &requests.LoginRequest{
		Username: "nonexistent",
		Password: "Password123",
	}

	_, err := service.Login(req)
	testutil.AssertAppError(t, err, http.StatusUnauthorized, "error.invalid_credentials")
}

func TestAuthService_Login_InactiveUser(t *testing.T) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	cfg := &config.Config{
		Security: config.SecurityConfig{SecretKey: "test-secret"},
	}
	service := NewAuthService(userRepo, cfg)

	user := testutil.CreateTestUser(t, db, "inactive", "inactive@test.com", "Password123")
	// Deactivate
	user.IsActive = false
	db.Save(user)

	req := &requests.LoginRequest{
		Username: "inactive",
		Password: "Password123",
	}

	_, err := service.Login(req)
	testutil.AssertAppError(t, err, http.StatusUnauthorized, "error.account_inactive")
}

// === Register ===

func TestAuthService_Register(t *testing.T) {
	service, _ := setupAuthService(t)

	req := &requests.RegisterRequest{
		Username: "newuser",
		Email:    "new@test.com",
		Password: "Password123",
	}

	resp, code, err := service.Register(req)
	require.NoError(t, err)
	assert.NotEmpty(t, resp.Token)
	assert.Equal(t, "newuser", resp.User.Username)
	assert.Equal(t, "123456", code) // DebugFixedCodes=true
}

func TestAuthService_Register_DuplicateUsername(t *testing.T) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	cfg := &config.Config{
		Server:   config.ServerConfig{DebugFixedCodes: true},
		Security: config.SecurityConfig{SecretKey: "test", ConfirmationExpiry: 24 * time.Hour},
	}
	service := NewAuthService(userRepo, cfg)

	testutil.CreateTestUser(t, db, "taken", "taken@test.com", "Password123")

	req := &requests.RegisterRequest{
		Username: "taken",
		Email:    "different@test.com",
		Password: "Password123",
	}

	_, _, err := service.Register(req)
	testutil.AssertAppError(t, err, http.StatusConflict, "error.username_taken")
}

func TestAuthService_Register_DuplicateEmail(t *testing.T) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	cfg := &config.Config{
		Server:   config.ServerConfig{DebugFixedCodes: true},
		Security: config.SecurityConfig{SecretKey: "test", ConfirmationExpiry: 24 * time.Hour},
	}
	service := NewAuthService(userRepo, cfg)

	testutil.CreateTestUser(t, db, "existing", "taken@test.com", "Password123")

	req := &requests.RegisterRequest{
		Username: "newuser",
		Email:    "taken@test.com",
		Password: "Password123",
	}

	_, _, err := service.Register(req)
	testutil.AssertAppError(t, err, http.StatusConflict, "error.email_taken")
}

// === GetCurrentUser ===

func TestAuthService_GetCurrentUser(t *testing.T) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	cfg := &config.Config{
		Security: config.SecurityConfig{SecretKey: "test-secret"},
	}
	service := NewAuthService(userRepo, cfg)

	user := testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")
	// Create profile
	userRepo.GetOrCreateProfile(user.ID)

	resp, err := service.GetCurrentUser(user.ID)
	require.NoError(t, err)
	assert.Equal(t, "testuser", resp.Username)
	assert.Equal(t, "test@test.com", resp.Email)
	assert.Equal(t, "email", resp.AuthProvider) // Default for no social auth
}

// === UpdateProfile ===

func TestAuthService_UpdateProfile(t *testing.T) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	cfg := &config.Config{
		Security: config.SecurityConfig{SecretKey: "test-secret"},
	}
	service := NewAuthService(userRepo, cfg)

	user := testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")
	userRepo.GetOrCreateProfile(user.ID)

	newFirst := "John"
	newLast := "Doe"
	req := &requests.UpdateProfileRequest{
		FirstName: &newFirst,
		LastName:  &newLast,
	}

	resp, err := service.UpdateProfile(user.ID, req)
	require.NoError(t, err)
	assert.Equal(t, "John", resp.FirstName)
	assert.Equal(t, "Doe", resp.LastName)
}

func TestAuthService_UpdateProfile_DuplicateEmail(t *testing.T) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	cfg := &config.Config{
		Security: config.SecurityConfig{SecretKey: "test-secret"},
	}
	service := NewAuthService(userRepo, cfg)

	testutil.CreateTestUser(t, db, "user1", "user1@test.com", "Password123")
	user2 := testutil.CreateTestUser(t, db, "user2", "user2@test.com", "Password123")
	userRepo.GetOrCreateProfile(user2.ID)

	takenEmail := "user1@test.com"
	req := &requests.UpdateProfileRequest{
		Email: &takenEmail,
	}

	_, err := service.UpdateProfile(user2.ID, req)
	testutil.AssertAppError(t, err, http.StatusConflict, "error.email_already_taken")
}

func TestAuthService_UpdateProfile_SameEmail(t *testing.T) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	cfg := &config.Config{
		Security: config.SecurityConfig{SecretKey: "test-secret"},
	}
	service := NewAuthService(userRepo, cfg)

	user := testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")
	userRepo.GetOrCreateProfile(user.ID)

	sameEmail := "test@test.com"
	req := &requests.UpdateProfileRequest{
		Email: &sameEmail,
	}

	// Same email should not trigger duplicate error
	resp, err := service.UpdateProfile(user.ID, req)
	require.NoError(t, err)
	assert.Equal(t, "test@test.com", resp.Email)
}

// === VerifyEmail ===

func TestAuthService_VerifyEmail(t *testing.T) {
	service, _ := setupAuthService(t)

	// Register a user (creates confirmation code)
	req := &requests.RegisterRequest{
		Username: "newuser",
		Email:    "new@test.com",
		Password: "Password123",
	}
	_, _, err := service.Register(req)
	require.NoError(t, err)

	// Get the user ID
	user, err := service.userRepo.FindByEmail("new@test.com")
	require.NoError(t, err)

	// Verify with the debug code
	err = service.VerifyEmail(user.ID, "123456")
	require.NoError(t, err)

	// Verify again — should get already verified error
	err = service.VerifyEmail(user.ID, "123456")
	testutil.AssertAppError(t, err, http.StatusBadRequest, "error.email_already_verified")
}

func TestAuthService_VerifyEmail_InvalidCode(t *testing.T) {
	service, _ := setupAuthService(t)

	// Register
	req := &requests.RegisterRequest{
		Username: "newuser",
		Email:    "new@test.com",
		Password: "Password123",
	}
	_, _, err := service.Register(req)
	require.NoError(t, err)

	user, err := service.userRepo.FindByEmail("new@test.com")
	require.NoError(t, err)

	// Wrong code — with DebugFixedCodes enabled, "123456" bypasses normal lookup,
	// but a wrong code should use the normal path
	err = service.VerifyEmail(user.ID, "000000")
	assert.Error(t, err)
}

// === ResendVerificationCode ===

func TestAuthService_ResendVerificationCode(t *testing.T) {
	service, _ := setupAuthService(t)

	// Register
	req := &requests.RegisterRequest{
		Username: "newuser",
		Email:    "new@test.com",
		Password: "Password123",
	}
	_, _, err := service.Register(req)
	require.NoError(t, err)

	user, err := service.userRepo.FindByEmail("new@test.com")
	require.NoError(t, err)

	code, err := service.ResendVerificationCode(user.ID)
	require.NoError(t, err)
	assert.Equal(t, "123456", code) // DebugFixedCodes
}

func TestAuthService_ResendVerificationCode_AlreadyVerified(t *testing.T) {
	service, _ := setupAuthService(t)

	// Register and verify
	req := &requests.RegisterRequest{
		Username: "newuser",
		Email:    "new@test.com",
		Password: "Password123",
	}
	_, _, err := service.Register(req)
	require.NoError(t, err)

	user, err := service.userRepo.FindByEmail("new@test.com")
	require.NoError(t, err)

	err = service.VerifyEmail(user.ID, "123456")
	require.NoError(t, err)

	_, err = service.ResendVerificationCode(user.ID)
	testutil.AssertAppError(t, err, http.StatusBadRequest, "error.email_already_verified")
}

// === ForgotPassword ===

func TestAuthService_ForgotPassword(t *testing.T) {
	service, _ := setupAuthService(t)

	// Register a user first
	registerReq := &requests.RegisterRequest{
		Username: "testuser",
		Email:    "test@test.com",
		Password: "Password123",
	}
	_, _, err := service.Register(registerReq)
	require.NoError(t, err)

	code, user, err := service.ForgotPassword("test@test.com")
	require.NoError(t, err)
	assert.Equal(t, "123456", code) // DebugFixedCodes
	assert.NotNil(t, user)
	assert.Equal(t, "test@test.com", user.Email)
}

func TestAuthService_ForgotPassword_NonexistentEmail(t *testing.T) {
	service, _ := setupAuthService(t)

	// Should not reveal that email doesn't exist
	code, user, err := service.ForgotPassword("nonexistent@test.com")
	require.NoError(t, err)
	assert.Empty(t, code)
	assert.Nil(t, user)
}

// === ResetPassword ===

func TestAuthService_ResetPassword(t *testing.T) {
	service, _ := setupAuthService(t)

	// Register
	registerReq := &requests.RegisterRequest{
		Username: "testuser",
		Email:    "test@test.com",
		Password: "Password123",
	}
	_, _, err := service.Register(registerReq)
	require.NoError(t, err)

	// Forgot password
	_, _, err = service.ForgotPassword("test@test.com")
	require.NoError(t, err)

	// Verify reset code to get the token
	resetToken, err := service.VerifyResetCode("test@test.com", "123456")
	require.NoError(t, err)
	assert.NotEmpty(t, resetToken)

	// Reset password
	err = service.ResetPassword(resetToken, "NewPassword123")
	require.NoError(t, err)

	// Login with new password
	loginReq := &requests.LoginRequest{
		Username: "testuser",
		Password: "NewPassword123",
	}
	loginResp, err := service.Login(loginReq)
	require.NoError(t, err)
	assert.NotEmpty(t, loginResp.Token)
}

func TestAuthService_ResetPassword_InvalidToken(t *testing.T) {
	service, _ := setupAuthService(t)

	err := service.ResetPassword("invalid-token", "NewPassword123")
	testutil.AssertAppError(t, err, http.StatusBadRequest, "error.invalid_reset_token")
}

// === Logout ===

func TestAuthService_Logout(t *testing.T) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	cfg := &config.Config{
		Security: config.SecurityConfig{SecretKey: "test-secret"},
	}
	service := NewAuthService(userRepo, cfg)

	user := testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")

	// Login first
	loginReq := &requests.LoginRequest{
		Username: "testuser",
		Password: "Password123",
	}
	loginResp, err := service.Login(loginReq)
	require.NoError(t, err)

	// Logout
	err = service.Logout(loginResp.Token)
	require.NoError(t, err)

	// Token should be deleted — refreshing should fail
	_, err = service.RefreshToken(loginResp.Token, user.ID)
	assert.Error(t, err)
}

// === DeleteAccount ===

func TestAuthService_DeleteAccount_EmailAuth(t *testing.T) {
	service, _ := setupAuthService(t)

	// Register
	registerReq := &requests.RegisterRequest{
		Username: "testuser",
		Email:    "test@test.com",
		Password: "Password123",
	}
	_, _, err := service.Register(registerReq)
	require.NoError(t, err)

	user, err := service.userRepo.FindByEmail("test@test.com")
	require.NoError(t, err)

	password := "Password123"
	_, err = service.DeleteAccount(user.ID, &password, nil)
	require.NoError(t, err)
}

func TestAuthService_DeleteAccount_WrongPassword(t *testing.T) {
	service, _ := setupAuthService(t)

	registerReq := &requests.RegisterRequest{
		Username: "testuser",
		Email:    "test@test.com",
		Password: "Password123",
	}
	_, _, err := service.Register(registerReq)
	require.NoError(t, err)

	user, err := service.userRepo.FindByEmail("test@test.com")
	require.NoError(t, err)

	wrongPassword := "WrongPassword1"
	_, err = service.DeleteAccount(user.ID, &wrongPassword, nil)
	testutil.AssertAppError(t, err, http.StatusUnauthorized, "error.invalid_credentials")
}

func TestAuthService_DeleteAccount_NoPassword(t *testing.T) {
	service, _ := setupAuthService(t)

	registerReq := &requests.RegisterRequest{
		Username: "testuser",
		Email:    "test@test.com",
		Password: "Password123",
	}
	_, _, err := service.Register(registerReq)
	require.NoError(t, err)

	user, err := service.userRepo.FindByEmail("test@test.com")
	require.NoError(t, err)

	_, err = service.DeleteAccount(user.ID, nil, nil)
	testutil.AssertAppError(t, err, http.StatusBadRequest, "error.password_required")
}

func TestAuthService_DeleteAccount_UserNotFound(t *testing.T) {
	service, _ := setupAuthService(t)

	password := "Password123"
	_, err := service.DeleteAccount(99999, &password, nil)
	testutil.AssertAppError(t, err, http.StatusNotFound, "error.user_not_found")
}

// === Helper functions ===

func TestGenerateSixDigitCode(t *testing.T) {
	code := generateSixDigitCode()
	assert.Len(t, code, 6)
	// Should be numeric
	for _, c := range code {
		assert.True(t, c >= '0' && c <= '9', "code should contain only digits")
	}
}

func TestGenerateResetToken(t *testing.T) {
	token := generateResetToken()
	assert.NotEmpty(t, token)
	assert.Len(t, token, 64) // 32 bytes = 64 hex chars
}

func TestGetStringOrEmpty(t *testing.T) {
	s := "hello"
	assert.Equal(t, "hello", getStringOrEmpty(&s))
	assert.Equal(t, "", getStringOrEmpty(nil))
}

func TestIsPrivateRelayEmail(t *testing.T) {
	assert.True(t, isPrivateRelayEmail("abc@privaterelay.appleid.com"))
	assert.True(t, isPrivateRelayEmail("ABC@PRIVATERELAY.APPLEID.COM"))
	assert.False(t, isPrivateRelayEmail("user@gmail.com"))
}

func TestGetEmailFromRequest(t *testing.T) {
	email := "req@test.com"
	assert.Equal(t, "req@test.com", getEmailFromRequest(&email, "claims@test.com"))
	assert.Equal(t, "claims@test.com", getEmailFromRequest(nil, "claims@test.com"))
	empty := ""
	assert.Equal(t, "claims@test.com", getEmailFromRequest(&empty, "claims@test.com"))
}

// === getEmailOrDefault ===

func TestGetEmailOrDefault(t *testing.T) {
	// Non-empty email returns itself
	assert.Equal(t, "user@test.com", getEmailOrDefault("user@test.com"))

	// Empty email returns a generated placeholder
	result := getEmailOrDefault("")
	assert.Contains(t, result, "@privaterelay.appleid.com")
	assert.Contains(t, result, "apple_")
}

// === generateUniqueUsername ===

func TestGenerateUniqueUsername(t *testing.T) {
	// Normal email generates username from email prefix
	username := generateUniqueUsername("john@test.com", nil)
	assert.Contains(t, username, "john_")

	// Private relay email falls back to first name
	firstName := "Jane"
	username = generateUniqueUsername("abc@privaterelay.appleid.com", &firstName)
	assert.Contains(t, username, "jane_")

	// Private relay email and no first name — fallback
	username = generateUniqueUsername("abc@privaterelay.appleid.com", nil)
	assert.Contains(t, username, "user_")

	// Empty email with first name
	firstName2 := "Bob"
	username = generateUniqueUsername("", &firstName2)
	assert.Contains(t, username, "bob_")

	// Empty email and no first name
	username = generateUniqueUsername("", nil)
	assert.Contains(t, username, "user_")
}

// === generateGoogleUsername ===

func TestGenerateGoogleUsername(t *testing.T) {
	// Normal email
	username := generateGoogleUsername("john@gmail.com", "John")
	assert.Contains(t, username, "john_")

	// Empty email falls back to first name
	username = generateGoogleUsername("", "Alice")
	assert.Contains(t, username, "alice_")

	// Empty email and empty first name — fallback
	username = generateGoogleUsername("", "")
	assert.Contains(t, username, "google_")
}

// === Login with empty password ===

func TestAuthService_Login_EmptyPassword(t *testing.T) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	cfg := &config.Config{
		Security: config.SecurityConfig{SecretKey: "test-secret"},
	}
	service := NewAuthService(userRepo, cfg)

	testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")

	req := &requests.LoginRequest{
		Username: "testuser",
		Password: "",
	}

	_, err := service.Login(req)
	testutil.AssertAppError(t, err, http.StatusUnauthorized, "error.invalid_credentials")
}

// === ForgotPassword rate limiting ===

func TestAuthService_ForgotPassword_RateLimit(t *testing.T) {
	service, _ := setupAuthService(t)

	registerReq := &requests.RegisterRequest{
		Username: "testuser",
		Email:    "test@test.com",
		Password: "Password123",
	}
	_, _, err := service.Register(registerReq)
	require.NoError(t, err)

	// Make max allowed reset requests (3 based on setup)
	for i := 0; i < 3; i++ {
		_, _, err := service.ForgotPassword("test@test.com")
		require.NoError(t, err)
	}

	// The 4th should be rate limited
	_, _, err = service.ForgotPassword("test@test.com")
	assert.Error(t, err)
}

// === VerifyResetCode with wrong code ===

func TestAuthService_VerifyResetCode_WrongCode(t *testing.T) {
	service, _ := setupAuthService(t)

	registerReq := &requests.RegisterRequest{
		Username: "testuser",
		Email:    "test@test.com",
		Password: "Password123",
	}
	_, _, err := service.Register(registerReq)
	require.NoError(t, err)

	_, _, err = service.ForgotPassword("test@test.com")
	require.NoError(t, err)

	// Wrong code but with debug mode, "123456" works, "000000" should fail
	_, err = service.VerifyResetCode("test@test.com", "000000")
	assert.Error(t, err)
}

// === VerifyResetCode with nonexistent email ===

func TestAuthService_VerifyResetCode_NonexistentEmail(t *testing.T) {
	service, _ := setupAuthService(t)

	_, err := service.VerifyResetCode("nonexistent@test.com", "123456")
	assert.Error(t, err)
}

// === UpdateProfile — change email to new email ===

func TestAuthService_UpdateProfile_ChangeEmail(t *testing.T) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	cfg := &config.Config{
		Security: config.SecurityConfig{SecretKey: "test-secret"},
	}
	service := NewAuthService(userRepo, cfg)

	user := testutil.CreateTestUser(t, db, "testuser", "test@test.com", "Password123")
	userRepo.GetOrCreateProfile(user.ID)

	newEmail := "newemail@test.com"
	req := &requests.UpdateProfileRequest{
		Email: &newEmail,
	}

	resp, err := service.UpdateProfile(user.ID, req)
	require.NoError(t, err)
	assert.Equal(t, "newemail@test.com", resp.Email)
}

// === DeleteAccount — empty password string ===

func TestAuthService_DeleteAccount_EmptyPassword(t *testing.T) {
	service, _ := setupAuthService(t)

	registerReq := &requests.RegisterRequest{
		Username: "testuser",
		Email:    "test@test.com",
		Password: "Password123",
	}
	_, _, err := service.Register(registerReq)
	require.NoError(t, err)

	user, err := service.userRepo.FindByEmail("test@test.com")
	require.NoError(t, err)

	emptyPw := ""
	_, err = service.DeleteAccount(user.ID, &emptyPw, nil)
	testutil.AssertAppError(t, err, http.StatusBadRequest, "error.password_required")
}

// === SetNotificationRepository ===

func TestAuthService_SetNotificationRepository(t *testing.T) {
	db := testutil.SetupTestDB(t)
	userRepo := repositories.NewUserRepository(db)
	notifRepo := repositories.NewNotificationRepository(db)
	cfg := &config.Config{
		Security: config.SecurityConfig{SecretKey: "test-secret"},
	}
	service := NewAuthService(userRepo, cfg)
	assert.Nil(t, service.notificationRepo)

	service.SetNotificationRepository(notifRepo)
	assert.NotNil(t, service.notificationRepo)
}

// === Register creates profile and notification preferences ===

func TestAuthService_Register_CreatesProfile(t *testing.T) {
	service, userRepo := setupAuthService(t)

	req := &requests.RegisterRequest{
		Username:  "profileuser",
		Email:     "profile@test.com",
		Password:  "Password123",
		FirstName: "John",
		LastName:  "Doe",
	}

	resp, _, err := service.Register(req)
	require.NoError(t, err)
	assert.Equal(t, "profileuser", resp.User.Username)

	// Profile should exist
	profile, err := userRepo.GetOrCreateProfile(resp.User.ID)
	require.NoError(t, err)
	assert.NotNil(t, profile)
}
