package service_test

import (
	"context"
	"testing"

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

// =============================================================================
// Auth Setter Tests - Phase 1
// =============================================================================

func TestAuthService_Setters(t *testing.T) {
	env := setupAuthTestEnv(t)
	if env == nil {
		return
	}

	t.Run("SetWebhookService", func(t *testing.T) {
		env.authSvc.SetWebhookService(nil)
	})

	t.Run("SetLoginLogRepository", func(t *testing.T) {
		env.authSvc.SetLoginLogRepository(nil)
	})

	t.Run("SetAnomalyDetector", func(t *testing.T) {
		env.authSvc.SetAnomalyDetector(nil)
	})

	t.Run("SetDeviceService", func(t *testing.T) {
		env.authSvc.SetDeviceService(nil)
	})

	t.Run("SetSMSCodeService", func(t *testing.T) {
		env.authSvc.SetSMSCodeService(nil)
	})
}

// =============================================================================
// Auth Nil Service Tests
// =============================================================================

func TestAuthService_NilServiceMethods(t *testing.T) {
	ctx := context.Background()
	var nilSvc *service.AuthService

	t.Run("RefreshToken", func(t *testing.T) {
		_, err := nilSvc.RefreshToken(ctx, "token")
		if err == nil {
			t.Error("Expected error")
		}
	})

	t.Run("GetUserInfo", func(t *testing.T) {
		_, err := nilSvc.GetUserInfo(ctx, 1)
		if err == nil {
			t.Error("Expected error")
		}
	})

	t.Run("Logout", func(t *testing.T) {
		err := nilSvc.Logout(ctx, "user", nil)
		// Logout on nil service should not error
		_ = err
	})

	t.Run("IsTokenBlacklisted", func(t *testing.T) {
		if nilSvc.IsTokenBlacklisted(ctx, "jti") {
			t.Error("Expected false")
		}
	})

	t.Run("OAuthLogin", func(t *testing.T) {
		_, err := nilSvc.OAuthLogin(ctx, "provider", "state")
		if err == nil {
			t.Error("Expected error")
		}
	})

	t.Run("OAuthCallback", func(t *testing.T) {
		_, err := nilSvc.OAuthCallback(ctx, "provider", "code")
		if err == nil {
			t.Error("Expected error")
		}
	})

	t.Run("GetEnabledOAuthProviders", func(t *testing.T) {
		providers := nilSvc.GetEnabledOAuthProviders()
		// nil service returns empty slice, not nil
		if len(providers) != 0 {
			t.Error("Expected empty slice")
		}
	})

	t.Run("LoginByCode", func(t *testing.T) {
		_, err := nilSvc.LoginByCode(ctx, "phone", "code", "ip")
		if err == nil {
			t.Error("Expected error")
		}
	})

	t.Run("WarmupCache", func(t *testing.T) {
		err := nilSvc.WarmupCache(ctx, 10)
		// Should not error on nil service
		_ = err
	})

	t.Run("RefreshTokenTTLSeconds", func(t *testing.T) {
		if nilSvc.RefreshTokenTTLSeconds() != 0 {
			t.Error("Expected 0")
		}
	})
}

// =============================================================================
// User Status Tests
// =============================================================================

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

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

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

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

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

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

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

	t.Run("Login with active status", func(t *testing.T) {
		req := &service.RegisterRequest{
			Username: "active_login",
			Password: "Test123!",
		}
		resp, _ := env.authSvc.Register(ctx, req)
		env.userSvc.UpdateStatus(ctx, resp.ID, domain.UserStatusActive)

		_, err := env.authSvc.Login(ctx, &service.LoginRequest{
			Username: "active_login",
			Password: "Test123!",
		}, "127.0.0.1")
		if err != nil {
			t.Errorf("Active user should login: %v", err)
		}
	})
}

// =============================================================================
// Register Edge Cases
// =============================================================================

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

	t.Run("Register with email", func(t *testing.T) {
		req := &service.RegisterRequest{
			Username: "emailuser",
			Password: "Test123!",
			Email:    "email@test.com",
		}
		resp, err := env.authSvc.Register(ctx, req)
		if err != nil {
			t.Fatalf("Register failed: %v", err)
		}
		if resp.Email != "email@test.com" {
			t.Errorf("Expected email, got %s", resp.Email)
		}
	})

	t.Run("Register with phone", func(t *testing.T) {
		req := &service.RegisterRequest{
			Username: "phoneuser",
			Password: "Test123!",
			Phone:    "13800138000",
		}
		_, err := env.authSvc.Register(ctx, req)
		// Phone registration requires SMS config, expect error
		if err == nil {
			t.Log("Phone registration succeeded")
		} else {
			t.Logf("Phone registration failed (expected without SMS config): %v", err)
		}
	})

	t.Run("Register with duplicate email", func(t *testing.T) {
		req1 := &service.RegisterRequest{
			Username: "dupemail1",
			Password: "Test123!",
			Email:    "dup@test.com",
		}
		env.authSvc.Register(ctx, req1)

		req2 := &service.RegisterRequest{
			Username: "dupemail2",
			Password: "Test123!",
			Email:    "dup@test.com",
		}
		_, err := env.authSvc.Register(ctx, req2)
		if err == nil {
			t.Error("Expected error for duplicate email")
		}
	})

	t.Run("Register with duplicate phone", func(t *testing.T) {
		req1 := &service.RegisterRequest{
			Username: "dupphone1",
			Password: "Test123!",
			Phone:    "13900139000",
		}
		env.authSvc.Register(ctx, req1)

		req2 := &service.RegisterRequest{
			Username: "dupphone2",
			Password: "Test123!",
			Phone:    "13900139000",
		}
		_, err := env.authSvc.Register(ctx, req2)
		if err == nil {
			t.Error("Expected error for duplicate phone")
		}
	})
}

// =============================================================================
// Login Edge Cases
// =============================================================================

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

	// Create user with known credentials
	req := &service.RegisterRequest{
		Username: "loginedge",
		Password: "Test123!",
		Email:    "loginedge@test.com",
	}
	env.authSvc.Register(ctx, req)

	t.Run("Login with username", func(t *testing.T) {
		_, err := env.authSvc.Login(ctx, &service.LoginRequest{
			Username: "loginedge",
			Password: "Test123!",
		}, "127.0.0.1")
		if err != nil {
			t.Errorf("Login failed: %v", err)
		}
	})

	t.Run("Login with email as account", func(t *testing.T) {
		_, err := env.authSvc.Login(ctx, &service.LoginRequest{
			Account:  "loginedge@test.com",
			Password: "Test123!",
		}, "127.0.0.1")
		if err != nil {
			t.Errorf("Login with email failed: %v", err)
		}
	})

	t.Run("Login with remember", func(t *testing.T) {
		resp, err := env.authSvc.Login(ctx, &service.LoginRequest{
			Username: "loginedge",
			Password: "Test123!",
			Remember: true,
		}, "127.0.0.1")
		if err != nil {
			t.Fatalf("Login failed: %v", err)
		}
		if resp.RefreshToken == "" {
			t.Error("Expected refresh token with remember")
		}
	})

	t.Run("Login with device info", func(t *testing.T) {
		_, err := env.authSvc.Login(ctx, &service.LoginRequest{
			Username:      "loginedge",
			Password:      "Test123!",
			DeviceID:      "device123",
			DeviceName:    "Test Device",
			DeviceBrowser: "Chrome",
			DeviceOS:      "Windows",
		}, "127.0.0.1")
		if err != nil {
			t.Errorf("Login with device info failed: %v", err)
		}
	})
}
