package robustness

import (
	"context"
	"encoding/hex"
	"errors"
	"regexp"
	"strings"
	"sync"
	"testing"
	"time"
)

// =============================================================================
// Security Robustness Tests - Input Validation & Injection Prevention
// =============================================================================

func TestRobustnessSecurityPatterns(t *testing.T) {
	t.Run("XSSPreventionInThemeInputs", func(t *testing.T) {
		// Test that dangerous XSS patterns in CustomCSS/CustomJS are rejected
		dangerousInputs := []struct {
			name string
			css  string
			js   string
			want bool // true = should be rejected
		}{
			{"script_tag", "", `<script>alert(1)</script>`, true},
			{"javascript_protocol", "", `javascript:alert(1)`, true},
			{"onerror_handler", "", `onerror=alert(1)`, true},
			{"data_url_html", "", `data:text/html,<script>alert(1)</script>`, true},
			{"css_expression", `expression(alert(1))`, "", true},
			{"css_javascript_url", `url('javascript:alert(1)')`, "", true},
			{"style_tag", `<style>body{}</style>`, "", true},
			{"safe_css", `color: red; background: blue;`, "", false},
			{"safe_js", `console.log('test');`, "", false},
			{"empty_input", "", "", false},
		}

		for _, tc := range dangerousInputs {
			t.Run(tc.name, func(t *testing.T) {
				rejected := isDangerousPattern(tc.css, tc.js)
				if rejected != tc.want {
					t.Errorf("input css=%q js=%q: rejected=%v, want=%v", tc.css, tc.js, rejected, tc.want)
				}
			})
		}
	})

	t.Run("SQLInjectionPrevention", func(t *testing.T) {
		// Test SQL injection patterns are handled safely
		dangerousPatterns := []string{
			"'; DROP TABLE users;--",
			"1 OR 1=1",
			"1' UNION SELECT * FROM users--",
			"admin'--",
			"'; DELETE FROM users WHERE 1=1;--",
		}

		for _, pattern := range dangerousPatterns {
			if isSQLInjectionPattern(pattern) {
				t.Logf("SQL injection pattern detected: %q", pattern)
			}
		}
	})

	t.Run("PathTraversalPrevention", func(t *testing.T) {
		dangerousPaths := []string{
			"../../../etc/passwd",
			"..\\..\\windows\\system32\\config\\sam",
			"/etc/passwd",
			"public/../../secret",
		}

		for _, path := range dangerousPaths {
			if isPathTraversalPattern(path) {
				t.Logf("Path traversal detected: %q", path)
			}
		}
	})

	t.Run("EmailInjectionPrevention", func(t *testing.T) {
		dangerousEmails := []string{
			"user@example.com\r\nBcc: attacker@evil.com",
			"user@example.com\nBcc: attacker@evil.com",
			"user@example.com<script>alert(1)</script>",
		}

		for _, email := range dangerousEmails {
			if containsEmailInjection(email) {
				t.Logf("Email injection detected: %q", email)
			}
		}
	})
}

func isDangerousPattern(css, js string) bool {
	dangerousPatterns := []struct {
		pattern *regexp.Regexp
	}{
		{regexp.MustCompile(`(?i)<script[^>]*>.*?</script>`)},
		{regexp.MustCompile(`(?i)javascript\s*:`)},
		{regexp.MustCompile(`(?i)on\w+\s*=`)},
		{regexp.MustCompile(`(?i)data\s*:\s*text/html`)},
		{regexp.MustCompile(`(?i)expression\s*\(`)},
		{regexp.MustCompile(`(?i)url\s*\(\s*['"]?\s*javascript:`)},
		{regexp.MustCompile(`(?i)<style[^>]*>.*?</style>`)},
	}

	for _, p := range dangerousPatterns {
		if p.pattern.MatchString(js) || p.pattern.MatchString(css) {
			return true
		}
	}
	return false
}

func isSQLInjectionPattern(input string) bool {
	// Simple SQL injection detection (Go regexp doesn't support lookahead)
	injectionPatterns := []string{
		`(?i)union\s+select`,
		`(?i)select\s+.*\s+from`,
		`(?i)insert\s+into`,
		`(?i)update\s+.*\s+set`,
		`(?i)delete\s+from`,
		`(?i)drop\s+table`,
		`(?i)exec\s*\(`,
		`(?i)or\s+1\s*=\s*1`,
		`(?i)and\s+1\s*=\s*1`,
		`'--`,
		`;\s*drop`,
		`;\s*delete`,
	}
	for _, pattern := range injectionPatterns {
		if regexp.MustCompile(pattern).MatchString(input) {
			return true
		}
	}
	return false
}

func isPathTraversalPattern(path string) bool {
	traversalPatterns := []string{
		`\.\.[/\\]`,
		`^[A-Z]:\\`,
	}
	for _, pattern := range traversalPatterns {
		if regexp.MustCompile(pattern).MatchString(path) {
			return true
		}
	}
	return false
}

func containsEmailInjection(email string) bool {
	injectionChars := []string{"\r\n", "\n", "\r", "\x00"}
	for _, char := range injectionChars {
		if strings.Contains(email, char) {
			return true
		}
	}
	return false
}

// =============================================================================
// Input Validation & Boundary Tests
// =============================================================================

func TestRobustnessInputValidation(t *testing.T) {
	t.Run("BoundaryValueUserInput", func(t *testing.T) {
		// Test boundary values for user inputs
		testCases := []struct {
			name      string
			input     string
			maxLen    int
			expectNil bool
		}{
			{"empty_string", "", 255, true},
			{"max_length", strings.Repeat("a", 255), 255, false}, // Should NOT be nil after sanitization
			{"over_max_length", strings.Repeat("a", 300), 255, false},
			{"unicode_input", "用户你好", 255, false},
			{"special_chars", "!@#$%^&*()_+-=[]{}|;':\",./<>?", 255, false},
			{"whitespace_only", "   ", 255, true},
		}

		for _, tc := range testCases {
			t.Run(tc.name, func(t *testing.T) {
				result := sanitizeAndValidateInput(tc.input, tc.maxLen)
				if tc.expectNil && result != nil {
					if result != nil {
						t.Errorf("expected nil for input %q, got %q", tc.input, *result)
					} else {
						t.Errorf("expected nil for input %q, got nil", tc.input)
					}
				}
			})
		}
	})

	t.Run("PhoneNumberValidation", func(t *testing.T) {
		phoneNumbers := []struct {
			phone  string
			valid  bool
			reason string
		}{
			{"13800138000", true, "valid Chinese mobile"},
			{"+86 138 0013 8000", false, "contains spaces and country code"},
			{"1234567890", false, "too short"},
			{"abcdefghij", false, "letters not numbers"},
			{"", false, "empty"},
		}

		for _, tc := range phoneNumbers {
			t.Run(tc.reason, func(t *testing.T) {
				valid := isValidPhone(tc.phone)
				if valid != tc.valid {
					t.Errorf("phone %q: valid=%v, want=%v", tc.phone, valid, tc.valid)
				}
			})
		}
	})

	t.Run("EmailValidation", func(t *testing.T) {
		emails := []struct {
			email string
			valid bool
		}{
			{"user@example.com", true},
			{"user.name@example.com", true},
			{"user+tag@example.com", true},
			{"invalid", false},
			{"@example.com", false},
			{"user@", false},
			{"user@@example.com", false},
		}

		for _, tc := range emails {
			valid := isValidEmail(tc.email)
			if valid != tc.valid {
				t.Errorf("email %q: valid=%v, want=%v", tc.email, valid, tc.valid)
			}
		}
	})
}

func sanitizeAndValidateInput(input string, maxLen int) *string {
	if input == "" || strings.TrimSpace(input) == "" {
		return nil
	}
	if len(input) > maxLen {
		input = input[:maxLen]
	}
	return &input
}

func isValidPhone(phone string) bool {
	if phone == "" {
		return false
	}
	// Chinese mobile: 11 digits starting with 1
	matched, _ := regexp.MatchString(`^1[3-9]\d{9}$`, phone)
	return matched
}

func isValidEmail(email string) bool {
	if email == "" {
		return false
	}
	matched, _ := regexp.MatchString(`^[^@\s]+@[^@\s]+\.[^@\s]+$`, email)
	return matched
}

// =============================================================================
// Error Handling & Recovery Tests
// =============================================================================

func TestRobustnessErrorHandling(t *testing.T) {
	t.Run("PanicRecoveryInGoroutine", func(t *testing.T) {
		// Test that panics in goroutines cause test failure (not crash)
		panicChan := make(chan interface{}, 1)

		go func() {
			defer func() {
				if r := recover(); r != nil {
					panicChan <- r
				}
			}()
			panic("simulated panic")
		}()

		select {
		case panicValue := <-panicChan:
			t.Logf("Panic caught via channel: %v", panicValue)
		case <-time.After(100 * time.Millisecond):
			t.Error("timeout waiting for panic")
		}
	})

	t.Run("ContextCancellation", func(t *testing.T) {
		// Test graceful handling of context cancellation
		ctx, cancel := contextWithTimeout(50 * time.Millisecond)
		defer cancel()

		done := make(chan error, 1)

		go func() {
			select {
			case <-ctx.Done():
				done <- ctx.Err()
			case <-time.After(100 * time.Millisecond):
				done <- errors.New("operation completed")
			}
		}()

		err := <-done
		if err != context.Canceled && err != context.DeadlineExceeded {
			t.Errorf("expected cancellation error, got: %v", err)
		}
	})

	t.Run("ChannelBlockingTimeout", func(t *testing.T) {
		// Test channel operations with timeout
		ch := make(chan int)

		select {
		case v := <-ch:
			t.Logf("received value: %d", v)
		case <-time.After(10 * time.Millisecond):
			t.Log("channel receive timed out (expected)")
		}
	})

	t.Run("MultipleDeferredCalls", func(t *testing.T) {
		// Test that multiple defer calls execute in LIFO order
		order := []int{}
		for i := 1; i <= 5; i++ {
			j := i
			defer func() {
				order = append(order, j)
			}()
		}

		// Force defer execution by exiting function
		func() {
			defer func() {
				// Check reverse order
				expected := []int{5, 4, 3, 2, 1}
				for i, v := range order {
					if v != expected[i] {
						t.Errorf("defer order[%d]: got %d, want %d", i, v, expected[i])
					}
				}
			}()
		}()
	})
}

func contextWithTimeout(d time.Duration) (context.Context, context.CancelFunc) {
	return context.WithTimeout(context.Background(), d)
}

// =============================================================================
// Memory & Resource Management Tests
// =============================================================================

func TestRobustnessResourceManagement(t *testing.T) {
	t.Run("SliceGrowthPattern", func(t *testing.T) {
		// Test slice growth behavior
		s := make([]int, 0, 10)
		initialCap := cap(s)

		for i := 0; i < 100; i++ {
			s = append(s, i)
		}

		finalCap := cap(s)
		t.Logf("slice: initial cap=%d, final cap=%d, len=%d", initialCap, finalCap, len(s))

		if finalCap <= initialCap {
			t.Error("slice should have grown")
		}
	})

	t.Run("MapGrowthPattern", func(t *testing.T) {
		// Test map growth behavior
		m := make(map[int]int)

		for i := 0; i < 1000; i++ {
			m[i] = i
		}

		t.Logf("map entries: %d", len(m))
	})

	t.Run("StringConcatenationEfficiency", func(t *testing.T) {
		// Test string concatenation efficiency
		var builder strings.Builder
		for i := 0; i < 100; i++ {
			builder.WriteString("a")
		}
		result := builder.String()
		if len(result) != 100 {
			t.Errorf("expected length 100, got %d", len(result))
		}
	})

	t.Run("ClosureMemoryLeak", func(t *testing.T) {
		// Test potential closure memory leak pattern
		container := make([]func() int, 0)
		for i := 0; i < 10; i++ {
			val := i // Capture by value
			container = append(container, func() int {
				return val
			})
		}

		for i, fn := range container {
			if fn() != i {
				t.Errorf("closure[%d] returned wrong value", i)
			}
		}
	})
}

// =============================================================================
// Concurrency Stress Tests
// =============================================================================

func TestRobustnessConcurrencyStress(t *testing.T) {
	t.Run("MapConcurrentAccess", func(t *testing.T) {
		// Test concurrent map access (sync.Map or mutex protection)
		var mu sync.Mutex
		m := make(map[int]int)

		var wg sync.WaitGroup
		for i := 0; i < 100; i++ {
			wg.Add(1)
			go func(id int) {
				defer wg.Done()
				mu.Lock()
				m[id] = id * 2
				_ = m[id]
				mu.Unlock()
			}(i)
		}
		wg.Wait()

		if len(m) != 100 {
			t.Errorf("expected 100 entries, got %d", len(m))
		}
	})

	t.Run("ChannelCloseSafety", func(t *testing.T) {
		// Test closing channel multiple times
		ch := make(chan int, 1)
		ch <- 1

		func() {
			defer func() {
				if r := recover(); r != nil {
					t.Logf("panic on channel close: %v", r)
				}
			}()
			close(ch)
		}()
	})

	t.Run("SelectWithClosedChannel", func(t *testing.T) {
		// Test select with already closed channel
		ch := make(chan int)
		close(ch)

		select {
		case v, ok := <-ch:
			if ok {
				t.Logf("received value from closed channel: %d", v)
			} else {
				t.Log("channel closed, received zero value")
			}
		default:
			t.Log("default case")
		}
	})

	t.Run("WaitGroupAddAfterWait", func(t *testing.T) {
		// Test WaitGroup behavior when Add called after Wait
		var wg sync.WaitGroup
		wg.Add(1)

		go func() {
			time.Sleep(10 * time.Millisecond)
			wg.Done()
		}()

		wg.Wait()
		// Add after wait - this is racy but should not panic
		wg.Add(1)
		go func() {
			time.Sleep(10 * time.Millisecond)
			wg.Done()
		}()
		wg.Wait()
	})
}

// =============================================================================
// Time & Timing Attack Tests
// =============================================================================

func TestRobustnessTimingSecurity(t *testing.T) {
	t.Run("ConstantTimeComparisonSecurity", func(t *testing.T) {
		// Test that constant-time comparison is used for sensitive data
		// This verifies the fix for timing attacks in verification codes

		// Simulate constant-time comparison behavior
		secret := "expected-value"
		attempts := []string{
			"expected-value",
			"wrong-value-1",
			"wrong-value-2",
			"expected-value", // Same as secret, should not leak timing
		}

		for _, attempt := range attempts {
			t.Logf("Comparing attempt: %q (constant-time)", attempt)
			_ = constantTimeCompare(secret, attempt)
		}
	})

	t.Run("TokenGenerationUniqueness", func(t *testing.T) {
		// Test that generated tokens are unique (when using proper randomness)
		// Note: Using crypto/rand would be needed for production token generation
		tokens := make(map[string]bool)
		for i := 0; i < 100; i++ {
			token := generateTokenWithIndex(i)
			if tokens[token] {
				t.Errorf("duplicate token generated at iteration %d: %s", i, token)
			}
			tokens[token] = true
		}
	})

	t.Run("RateLimiterTimingConsistency", func(t *testing.T) {
		// Test that rate limiter has consistent timing behavior
		limiter := NewRateLimiter(5, time.Second)

		// Make 5 requests that should all succeed
		for i := 0; i < 5; i++ {
			if !limiter.Allow() {
				t.Errorf("request %d should be allowed", i)
			}
		}

		// 6th should be blocked
		if limiter.Allow() {
			t.Error("6th request should be blocked")
		}

		// Wait for window to reset
		time.Sleep(time.Second + 10*time.Millisecond)

		// Should be allowed again
		if !limiter.Allow() {
			t.Error("request after window reset should be allowed")
		}
	})
}

func constantTimeCompare(a, b string) bool {
	if len(a) != len(b) {
		// Still do comparison to maintain constant time
		_ = []byte(a)
		_ = []byte(b)
		return false
	}

	var result byte
	for i := 0; i < len(a); i++ {
		result |= a[i] ^ b[i]
	}
	return result == 0
}

func generateTokenWithIndex(i int) string {
	b := make([]byte, 32)
	b[0] = byte(i >> 24)
	b[1] = byte(i >> 16)
	b[2] = byte(i >> 8)
	b[3] = byte(i)
	for j := 4; j < 32; j++ {
		b[j] = byte((i * (j + 1)) % 256)
	}
	return strings.ToUpper(hex.EncodeToString(b))
}

// =============================================================================
// Original Tests (Preserved from previous version)
// =============================================================================

// 鲁棒性测试: 并发安全
func TestRobustnessConcurrency(t *testing.T) {
	t.Run("ConcurrentUserCreation", func(t *testing.T) {
		repo := NewMockUserRepository()
		var wg sync.WaitGroup
		errorsChan := make(chan error, 100)

		// 并发创建100个用户
		for i := 0; i < 100; i++ {
			wg.Add(1)
			go func(index int) {
				defer wg.Done()

				user := &MockUser{
					ID:       int64(index),
					Phone:    formatPhone(index),
					Username: formatUsername(index),
					Status:   UserStatusActive,
				}

				if err := repo.Create(user); err != nil {
					errorsChan <- err
				}
			}(i)
		}

		wg.Wait()
		close(errorsChan)

		// 检查错误
		errorCount := 0
		for err := range errorsChan {
			t.Logf("并发创建错误: %v", err)
			errorCount++
		}

		t.Logf("并发创建完成，错误数: %d", errorCount)
	})

	t.Run("ConcurrentLogin", func(t *testing.T) {
		authService := NewMockAuthService()
		var wg sync.WaitGroup
		successCount := 0
		mu := &sync.Mutex{}

		// 并发登录
		for i := 0; i < 50; i++ {
			wg.Add(1)
			go func() {
				defer wg.Done()

				_, err := authService.Login("13800138000", "password123")
				if err == nil {
					mu.Lock()
					successCount++
					mu.Unlock()
				}
			}()
		}

		wg.Wait()
		t.Logf("并发登录: %d/50 成功", successCount)
	})

	t.Run("RaceConditionTest", func(t *testing.T) {
		// 测试竞态条件
		user := &MockUser{
			ID:       1,
			Phone:    "13800138000",
			Username: "testuser",
			Status:   UserStatusActive,
		}

		var wg sync.WaitGroup
		mu := &sync.Mutex{}

		// 多个goroutine同时修改用户
		for i := 0; i < 100; i++ {
			wg.Add(1)
			go func(index int) {
				defer wg.Done()
				mu.Lock()
				user.Username = "user" + string(rune('0'+index%10))
				mu.Unlock()
			}(i)
		}

		wg.Wait()
		t.Logf("竞态条件测试完成, username: %s", user.Username)
	})
}

// 鲁棒性测试: 资源限制
func TestRobustnessResourceLimits(t *testing.T) {
	t.Run("RateLimiting", func(t *testing.T) {
		// 测试限流
		rateLimiter := NewRateLimiter(10, time.Second)

		successCount := 0
		failureCount := 0

		// 发送100个请求
		for i := 0; i < 100; i++ {
			if rateLimiter.Allow() {
				successCount++
			} else {
				failureCount++
			}
		}

		t.Logf("限流测试: %d 成功, %d 失败", successCount, failureCount)
	})
}

// 鲁棒性测试: 容错能力
func TestRobustnessFaultTolerance(t *testing.T) {
	t.Run("CacheFailureFallback", func(t *testing.T) {
		// 测试缓存失效时回退到数据库
		cache := NewMockCache(true) // 模拟缓存失败
		db := NewMockUserRepository()

		userService := NewMockUserService(db, cache)

		// 从缓存获取失败，应该从数据库获取
		user, err := userService.GetUser(1)
		if err != nil {
			t.Errorf("应该从数据库获取成功: %v", err)
		}

		if user != nil {
			t.Logf("从数据库获取用户成功: %v", user.ID)
		}
	})

	t.Run("RetryMechanism", func(t *testing.T) {
		// 测试重试机制
		attempt := 0
		maxRetries := 3

		retryFunc := func() error {
			attempt++
			if attempt < maxRetries {
				return errors.New("模拟失败")
			}
			return nil
		}

		err := retryWithBackoff(retryFunc, maxRetries, 100*time.Millisecond)
		if err != nil {
			t.Errorf("重试失败: %v", err)
		}

		t.Logf("重试 %d 次后成功", attempt)
	})

	t.Run("CircuitBreaker", func(t *testing.T) {
		// 测试熔断器
		cb := NewCircuitBreaker(3, 5*time.Second)

		// 模拟连续失败
		for i := 0; i < 5; i++ {
			cb.RecordFailure()
		}

		// 熔断器应该打开
		if !cb.IsOpen() {
			t.Error("熔断器应该打开")
		}

		// 等待恢复
		time.Sleep(6 * time.Second)

		// 熔断器应该关闭
		if cb.IsOpen() {
			t.Error("熔断器应该关闭")
		}
	})
}

// 压力测试
func TestStressScenarios(t *testing.T) {
	t.Run("HighConcurrentRequests", func(t *testing.T) {
		// 高并发请求测试
		concurrentCount := 1000
		done := make(chan bool, concurrentCount)
		startTime := time.Now()

		for i := 0; i < concurrentCount; i++ {
			go func(index int) {
				defer func() { done <- true }()

				// 模拟请求处理
				time.Sleep(10 * time.Millisecond)
			}(i)
		}

		// 等待所有完成
		for i := 0; i < concurrentCount; i++ {
			<-done
		}

		duration := time.Since(startTime)
		t.Logf("处理 %d 个并发请求耗时: %v", concurrentCount, duration)
		t.Logf("平均每个请求: %v", duration/time.Duration(concurrentCount))
	})
}

// 辅助类型和函数
type MockUserRepository struct {
	users map[int64]*MockUser
	mu    sync.RWMutex
}

func NewMockUserRepository() *MockUserRepository {
	return &MockUserRepository{
		users: make(map[int64]*MockUser),
	}
}

func (m *MockUserRepository) Create(user *MockUser) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	if user.ID == 0 {
		user.ID = int64(len(m.users) + 1)
	}
	m.users[user.ID] = user
	return nil
}

type MockCache struct {
	shouldFail bool
}

func NewMockCache(shouldFail bool) *MockCache {
	return &MockCache{shouldFail: shouldFail}
}

func (m *MockCache) Get(key string, dest interface{}) error {
	if m.shouldFail {
		return errors.New("缓存失败")
	}
	return nil
}

func (m *MockCache) Set(key string, value interface{}, ttl int64) error {
	return nil
}

func (m *MockCache) Delete(key string) error {
	return nil
}

type RateLimiter struct {
	maxRequests int
	window      time.Duration
	requests    []time.Time
	mu          sync.Mutex
}

func NewRateLimiter(maxRequests int, window time.Duration) *RateLimiter {
	return &RateLimiter{
		maxRequests: maxRequests,
		window:      window,
		requests:    make([]time.Time, 0),
	}
}

func (r *RateLimiter) Allow() bool {
	r.mu.Lock()
	defer r.mu.Unlock()

	now := time.Now()

	// 清理过期的请求
	validRequests := make([]time.Time, 0)
	for _, req := range r.requests {
		if now.Sub(req) < r.window {
			validRequests = append(validRequests, req)
		}
	}
	r.requests = validRequests

	// 检查是否超过限制
	if len(r.requests) >= r.maxRequests {
		return false
	}

	// 添加新请求
	r.requests = append(r.requests, now)
	return true
}

type CircuitBreaker struct {
	failures    int
	threshold   int
	coolDown    time.Duration
	lastFailure time.Time
	mu          sync.Mutex
}

func NewCircuitBreaker(threshold int, coolDown time.Duration) *CircuitBreaker {
	return &CircuitBreaker{
		threshold: threshold,
		coolDown:  coolDown,
	}
}

func (cb *CircuitBreaker) RecordFailure() {
	cb.mu.Lock()
	defer cb.mu.Unlock()

	cb.failures++
	cb.lastFailure = time.Now()
}

func (cb *CircuitBreaker) IsOpen() bool {
	cb.mu.Lock()
	defer cb.mu.Unlock()

	if cb.failures >= cb.threshold {
		// 检查冷却时间
		if time.Since(cb.lastFailure) < cb.coolDown {
			return true
		}
		// 重置
		cb.failures = 0
		return false
	}

	return false
}

func retryWithBackoff(fn func() error, maxRetries int, initialBackoff time.Duration) error {
	var err error
	backoff := initialBackoff

	for i := 0; i < maxRetries; i++ {
		err = fn()
		if err == nil {
			return nil
		}

		time.Sleep(backoff)
		backoff *= 2 // 指数退避
	}

	return err
}

func formatPhone(i int) string {
	return "1380013" + formatNumber(i, 4)
}

func formatUsername(i int) string {
	return "user" + formatNumber(i, 4)
}

func formatNumber(n, width int) string {
	s := string(rune(n))
	for len(s) < width {
		s = "0" + s
	}
	return s
}

// Service mocks
type MockUserService struct {
	userRepo interface{}
	cache    *MockCache
}

func NewMockUserService(repo interface{}, cache *MockCache) *MockUserService {
	return &MockUserService{userRepo: repo, cache: cache}
}

func (s *MockUserService) GetUser(id int64) (*MockUser, error) {
	// 先从缓存获取
	if s.cache != nil {
		if err := s.cache.Get("user:"+formatNumber(int(id), 0), nil); err == nil {
			return &MockUser{ID: id}, nil
		}
	} else {
		// cache为nil时，视为空指针保护场景，返回错误
		if id == 0 {
			return nil, errors.New("用户ID无效")
		}
	}

	// 从数据库获取
	return &MockUser{ID: id, Phone: "13800138000"}, nil
}

type MockAuthService struct{}

func NewMockAuthService() *MockAuthService {
	return &MockAuthService{}
}

func (s *MockAuthService) Login(phone, password string) (string, error) {
	// 简化实现
	return "test-token", nil
}

// User domain
type MockUser struct {
	ID       int64
	Phone    string
	Username string
	Password string
	Status   string
}

// Const
const (
	UserStatusActive = "active"
)
