package service_test

import (
	"context"
	"testing"

	"github.com/user-management-system/internal/domain"
	"github.com/user-management-system/internal/service"
)

// =============================================================================
// Auth Login Tests - Phase 1
// =============================================================================

func TestAuthService_Login(t *testing.T) {
	env := setupAuthTestEnv(t)
	if env == nil {
		return
	}
	ctx := context.Background()

	t.Run("Login success", func(t *testing.T) {
		// Register user first
		req := &service.RegisterRequest{
			Username: "loginuser",
			Password: "Test123!",
			Email:    "login@test.com",
		}
		_, err := env.authSvc.Register(ctx, req)
		if err != nil {
			t.Fatalf("Register failed: %v", err)
		}

		// Login
		resp, err := env.authSvc.Login(ctx, &service.LoginRequest{
			Username: "loginuser",
			Password: "Test123!",
		}, "127.0.0.1")
		if err != nil {
			t.Fatalf("Login failed: %v", err)
		}
		if resp.AccessToken == "" {
			t.Error("Expected access token")
		}
		if resp.User.Username != "loginuser" {
			t.Errorf("Expected username 'loginuser', got %s", resp.User.Username)
		}
	})

	t.Run("Login with wrong password", func(t *testing.T) {
		_, err := env.authSvc.Login(ctx, &service.LoginRequest{
			Username: "loginuser",
			Password: "wrongpassword",
		}, "127.0.0.1")
		if err == nil {
			t.Error("Expected error for wrong password")
		}
	})

	t.Run("Login with non-existent user", func(t *testing.T) {
		_, err := env.authSvc.Login(ctx, &service.LoginRequest{
			Username: "nonexistent",
			Password: "Test123!",
		}, "127.0.0.1")
		if err == nil {
			t.Error("Expected error for non-existent user")
		}
	})

	t.Run("Login with empty username", func(t *testing.T) {
		_, err := env.authSvc.Login(ctx, &service.LoginRequest{
			Username: "",
			Password: "Test123!",
		}, "127.0.0.1")
		if err == nil {
			t.Error("Expected error for empty username")
		}
	})

	t.Run("Login with empty password", func(t *testing.T) {
		_, err := env.authSvc.Login(ctx, &service.LoginRequest{
			Username: "loginuser",
			Password: "",
		}, "127.0.0.1")
		if err == nil {
			t.Error("Expected error for empty password")
		}
	})

	t.Run("Login with nil request", func(t *testing.T) {
		_, err := env.authSvc.Login(ctx, nil, "127.0.0.1")
		if err == nil {
			t.Error("Expected error for nil request")
		}
	})

	t.Run("Login for locked user", func(t *testing.T) {
		// Register and lock user
		req := &service.RegisterRequest{
			Username: "lockeduser",
			Password: "Test123!",
		}
		resp, _ := env.authSvc.Register(ctx, req)
		env.userSvc.UpdateStatus(ctx, resp.ID, domain.UserStatusLocked)

		// Try to login
		_, err := env.authSvc.Login(ctx, &service.LoginRequest{
			Username: "lockeduser",
			Password: "Test123!",
		}, "127.0.0.1")
		if err == nil {
			t.Error("Expected error for locked user")
		}
	})

	t.Run("Login for disabled user", func(t *testing.T) {
		req := &service.RegisterRequest{
			Username: "disableduser",
			Password: "Test123!",
		}
		resp, _ := env.authSvc.Register(ctx, req)
		env.userSvc.UpdateStatus(ctx, resp.ID, domain.UserStatusDisabled)

		_, err := env.authSvc.Login(ctx, &service.LoginRequest{
			Username: "disableduser",
			Password: "Test123!",
		}, "127.0.0.1")
		if err == nil {
			t.Error("Expected error for disabled user")
		}
	})

	t.Run("Login for inactive user", func(t *testing.T) {
		req := &service.RegisterRequest{
			Username: "inactiveuser",
			Password: "Test123!",
		}
		resp, _ := env.authSvc.Register(ctx, req)
		env.userSvc.UpdateStatus(ctx, resp.ID, domain.UserStatusInactive)

		_, err := env.authSvc.Login(ctx, &service.LoginRequest{
			Username: "inactiveuser",
			Password: "Test123!",
		}, "127.0.0.1")
		if err == nil {
			t.Error("Expected error for inactive user")
		}
	})

	t.Run("nil service Login", func(t *testing.T) {
		var nilSvc *service.AuthService
		_, err := nilSvc.Login(ctx, &service.LoginRequest{
			Username: "test",
			Password: "test",
		}, "127.0.0.1")
		if err == nil {
			t.Error("nil service should return error")
		}
	})

	t.Run("login with totp enabled returns temporary challenge token", func(t *testing.T) {
		req := &service.RegisterRequest{
			Username: "totploginuser",
			Password: "Test123!",
			Email:    "totplogin@test.com",
		}
		user, err := env.authSvc.Register(ctx, req)
		if err != nil {
			t.Fatalf("Register failed: %v", err)
		}
		if err := env.db.Model(&domain.User{}).Where("id = ?", user.ID).Updates(map[string]interface{}{
			"totp_enabled": true,
			"totp_secret":  "JBSWY3DPEHPK3PXP",
		}).Error; err != nil {
			t.Fatalf("enable totp failed: %v", err)
		}

		resp, err := env.authSvc.Login(ctx, &service.LoginRequest{
			Username: "totploginuser",
			Password: "Test123!",
		}, "127.0.0.1")
		if err != nil {
			t.Fatalf("Login failed: %v", err)
		}
		if !resp.RequiresTOTP {
			t.Fatal("expected requires_totp response")
		}
		if resp.TempToken == "" {
			t.Fatal("expected temp_token for second-factor challenge")
		}
		if resp.AccessToken != "" || resp.RefreshToken != "" {
			t.Fatal("totp challenge should not mint full session tokens before second factor verification")
		}
	})
}

func TestAuthService_Register(t *testing.T) {
	env := setupAuthTestEnv(t)
	if env == nil {
		return
	}
	ctx := context.Background()

	t.Run("Register success", func(t *testing.T) {
		req := &service.RegisterRequest{
			Username: "newuser",
			Password: "Test123!",
			Email:    "new@test.com",
			Nickname: "New User",
		}
		resp, err := env.authSvc.Register(ctx, req)
		if err != nil {
			t.Fatalf("Register failed: %v", err)
		}
		if resp.Username != "newuser" {
			t.Errorf("Expected username 'newuser', got %s", resp.Username)
		}
	})

	t.Run("Register with duplicate username", func(t *testing.T) {
		req := &service.RegisterRequest{
			Username: "dupuser",
			Password: "Test123!",
		}
		env.authSvc.Register(ctx, req)

		// Try again
		_, err := env.authSvc.Register(ctx, req)
		if err == nil {
			t.Error("Expected error for duplicate username")
		}
	})

	t.Run("Register with empty username", func(t *testing.T) {
		req := &service.RegisterRequest{
			Username: "",
			Password: "Test123!",
		}
		_, err := env.authSvc.Register(ctx, req)
		if err == nil {
			t.Error("Expected error for empty username")
		}
	})

	t.Run("Register with empty password", func(t *testing.T) {
		req := &service.RegisterRequest{
			Username: "nopass",
			Password: "",
		}
		_, err := env.authSvc.Register(ctx, req)
		if err == nil {
			t.Error("Expected error for empty password")
		}
	})

	t.Run("Register with weak password", func(t *testing.T) {
		req := &service.RegisterRequest{
			Username: "weakpass",
			Password: "123",
		}
		_, err := env.authSvc.Register(ctx, req)
		if err == nil {
			t.Error("Expected error for weak password")
		}
	})

	t.Run("Register with nil request", func(t *testing.T) {
		_, err := env.authSvc.Register(ctx, nil)
		if err == nil {
			t.Error("Expected error for nil request")
		}
	})

	t.Run("nil service Register", func(t *testing.T) {
		var nilSvc *service.AuthService
		req := &service.RegisterRequest{
			Username: "test",
			Password: "Test123!",
		}
		_, err := nilSvc.Register(ctx, req)
		if err == nil {
			t.Error("nil service should return error")
		}
	})
}
