package service_test

import (
	"context"
	"strings"
	"testing"

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

// =============================================================================
// 边界值测试 - 使用TDD方法确保健壮性
// =============================================================================

// TestBoundary_UsernameLength 用户名长度边界测试
func TestBoundary_UsernameLength(t *testing.T) {
	env := setupTestEnv(t)
	ctx := context.Background()

	tests := []struct {
		name     string
		username string
		wantErr  bool
		errMsg   string
	}{
		{"空用户名", "", true, "用户名不能为空"},
		{"单字符", "a", false, ""},
		{"最小有效长度", "ab", false, ""},
		{"正常长度", "normaluser", false, ""},
		{"最大有效长度-50", strings.Repeat("a", 50), false, ""},
		{"超过最大长度-51", strings.Repeat("a", 51), true, "用户名长度超过限制"},
		{"超长字符串-1000", strings.Repeat("a", 1000), true, "用户名长度超过限制"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			user := &domain.User{
				Username: tt.username,
				Password: "$2a$10$dummy",
				Status:   domain.UserStatusActive,
			}
			err := env.userSvc.Create(ctx, user)

			if tt.wantErr {
				if err == nil {
					t.Errorf("期望错误但没有返回: %s", tt.errMsg)
				}
			} else {
				if err != nil {
					t.Errorf("不期望错误但返回: %v", err)
				}
			}
		})
	}
}

// TestBoundary_EmailFormat 邮箱格式边界测试
func TestBoundary_EmailFormat(t *testing.T) {
	env := setupTestEnv(t)
	ctx := context.Background()

	tests := []struct {
		name    string
		email   string
		wantOK  bool
		comment string
	}{
		{"空邮箱", "", true, "邮箱为可选字段"},
		{"正常邮箱", "user@example.com", true, "标准格式"},
		{"带子域名", "user@mail.example.com", true, "多级域名"},
		{"带加号", "user+tag@example.com", true, "Gmail风格"},
		{"无@符号", "userexample.com", false, "缺少@"},
		{"无域名", "user@", false, "缺少域名"},
		{"无用户名", "@example.com", false, "缺少用户名"},
		{"多个@", "user@@example.com", false, "多个@符号"},
		{"空格", "user @example.com", false, "包含空格"},
		{"超长邮箱", strings.Repeat("a", 100) + "@example.com", false, "超过长度限制"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			user := &domain.User{
				Username: "test_" + strings.ReplaceAll(tt.name, " ", "_"),
				Email:    strPtr(tt.email),
				Password: "$2a$10$dummy",
				Status:   domain.UserStatusActive,
			}
			err := env.userSvc.Create(ctx, user)

			if tt.wantOK {
				if err != nil {
					t.Errorf("邮箱 '%s' 应该被接受但返回错误: %v (%s)", tt.email, err, tt.comment)
				}
			} else {
				if err == nil {
					t.Errorf("邮箱 '%s' 应该被拒绝但接受了 (%s)", tt.email, tt.comment)
				}
			}
		})
	}
}

// TestBoundary_PasswordStrength 密码强度边界测试
func TestBoundary_PasswordStrength(t *testing.T) {
	tests := []struct {
		name     string
		password string
		wantOK   bool
		comment  string
	}{
		{"空密码", "", false, "必须设置密码"},
		{"仅数字", "12345678", false, "需要复杂度"},
		{"仅小写", "abcdefgh", false, "需要大写"},
		{"仅大写", "ABCDEFGH", false, "需要小写"},
		{"字母数字", "Password12", false, "需要特殊字符"},
		{"最小有效密码", "Pass123!", true, "8位，包含大小写数字特殊字符"},
		{"强密码", "Str0ng@Pass!", true, "12位，高复杂度"},
		{"超长密码", strings.Repeat("Aa1!", 50), true, "200字符"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// 密码验证通常在handler层，这里验证服务层行为
			if tt.wantOK {
				t.Logf("✓ 密码 '%s' 符合强度要求 (%s)", tt.password[:min(10, len(tt.password))], tt.comment)
			} else {
				t.Logf("✗ 密码 '%s' 不符合强度要求 (%s)", tt.password, tt.comment)
			}
		})
	}
}

// TestBoundary_PaginationParams 分页参数边界测试
func TestBoundary_PaginationParams(t *testing.T) {
	env := setupTestEnv(t)
	ctx := context.Background()

	// 先创建一些测试数据
	for i := 0; i < 15; i++ {
		user := &domain.User{
			Username: "pageuser_" + strings.Repeat("0", 2-len(string(rune('0'+i)))) + string(rune('0'+i)),
			Password: "$2a$10$dummy",
			Status:   domain.UserStatusActive,
		}
		env.userSvc.Create(ctx, user)
	}

	tests := []struct {
		name      string
		page      int
		pageSize  int
		wantCount int
		wantTotal int64
	}{
		{"第一页", 1, 10, 10, 15},
		{"第二页", 2, 10, 5, 15},
		{"空页", 3, 10, 0, 15},
		{"页面大小1", 1, 1, 1, 15},
		{"大页面", 1, 100, 15, 15},
		{"零页-应默认为1", 0, 10, 10, 15},
		{"负页-应默认为1", -1, 10, 10, 15},
		{"零页面大小-应默认", 1, 0, 10, 15},
		{"负页面大小-应默认", 1, -10, 10, 15},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			users, total, err := env.userSvc.List(ctx, (tt.page-1)*tt.pageSize, tt.pageSize)
			if err != nil {
				t.Fatalf("List失败: %v", err)
			}

			if len(users) != tt.wantCount {
				t.Errorf("期望 %d 条记录，得到 %d", tt.wantCount, len(users))
			}
			if total < tt.wantTotal {
				t.Errorf("总数至少应为 %d，得到 %d", tt.wantTotal, total)
			}
		})
	}
}

// TestBoundary_StatusTransition 状态转换边界测试
func TestBoundary_StatusTransition(t *testing.T) {
	env := setupTestEnv(t)
	ctx := context.Background()

	tests := []struct {
		name       string
		fromStatus domain.UserStatus
		toStatus   domain.UserStatus
		wantOK     bool
	}{
		{"激活->禁用", domain.UserStatusActive, domain.UserStatusDisabled, true},
		{"激活->锁定", domain.UserStatusActive, domain.UserStatusLocked, true},
		{"激活->未激活", domain.UserStatusActive, domain.UserStatusInactive, true},
		{"禁用->激活", domain.UserStatusDisabled, domain.UserStatusActive, true},
		{"锁定->激活", domain.UserStatusLocked, domain.UserStatusActive, true},
		{"未激活->激活", domain.UserStatusInactive, domain.UserStatusActive, true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			user := &domain.User{
				Username: "status_" + strings.ReplaceAll(tt.name, "->", "_"),
				Password: "$2a$10$dummy",
				Status:   tt.fromStatus,
			}
			if err := env.userSvc.Create(ctx, user); err != nil {
				t.Fatalf("创建用户失败: %v", err)
			}

			err := env.userSvc.UpdateStatus(ctx, user.ID, tt.toStatus)
			if tt.wantOK && err != nil {
				t.Errorf("状态转换 %v->%v 应该成功但失败: %v", tt.fromStatus, tt.toStatus, err)
			}
			if !tt.wantOK && err == nil {
				t.Errorf("状态转换 %v->%v 应该失败但成功", tt.fromStatus, tt.toStatus)
			}
		})
	}
}

// TestBoundary_UserID 用户ID边界测试
func TestBoundary_UserID(t *testing.T) {
	env := setupTestEnv(t)
	ctx := context.Background()

	// 先创建一个有效用户
	user := &domain.User{
		Username: "valid_user_for_id_test",
		Password: "$2a$10$dummy",
		Status:   domain.UserStatusActive,
	}
	env.userSvc.Create(ctx, user)

	tests := []struct {
		name    string
		userID  int64
		wantErr bool
	}{
		{"零ID", 0, true},
		{"负ID", -1, true},
		{"有效ID", user.ID, false},
		{"超大ID", 9223372036854775807, true}, // int64 max
		{"不存在的ID", 999999999, true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			_, err := env.userSvc.GetByID(ctx, tt.userID)
			if tt.wantErr && err == nil {
				t.Error("期望错误但没有返回")
			}
			if !tt.wantErr && err != nil {
				t.Errorf("不期望错误但返回: %v", err)
			}
		})
	}
}

// TestBoundary_BatchOperations 批量操作边界测试
func TestBoundary_BatchOperations(t *testing.T) {
	env := setupTestEnv(t)
	ctx := context.Background()

	// 创建测试用户
	var userIDs []int64
	for i := 0; i < 5; i++ {
		user := &domain.User{
			Username: "batch_user_" + string(rune('0'+i)),
			Password: "$2a$10$dummy",
			Status:   domain.UserStatusActive,
		}
		env.userSvc.Create(ctx, user)
		userIDs = append(userIDs, user.ID)
	}

	tests := []struct {
		name    string
		ids     []int64
		wantErr bool
	}{
		{"空ID列表", []int64{}, false},
		{"单个ID", []int64{userIDs[0]}, false},
		{"多个ID", userIDs[:3], false},
		{"重复ID", []int64{userIDs[0], userIDs[0], userIDs[1], userIDs[1]}, false}, // 应该去重
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// 批量状态更新
			_, err := env.userSvc.BatchUpdateStatus(ctx, &service.BatchUpdateStatusRequest{
				IDs:    tt.ids,
				Status: domain.UserStatusInactive,
			})
			if tt.wantErr && err == nil {
				t.Error("期望错误但没有返回")
			}
			if !tt.wantErr && err != nil {
				t.Errorf("不期望错误但返回: %v", err)
			}
		})
	}
}

// TestBoundary_StringLength 字符串长度边界测试
func TestBoundary_StringLength(t *testing.T) {
	env := setupTestEnv(t)
	ctx := context.Background()

	tests := []struct {
		name      string
		nickname  string
		region    string
		bio       string
		wantError bool
	}{
		{"正常长度", "正常昵称", "北京", "这是个人简介", false},
		{"空字符串", "", "", "", false},
		{"最大昵称长度50", strings.Repeat("测", 50), "", "", false},
		{"超过昵称长度", strings.Repeat("测", 51), "", "", true},
		{"最大简介长度500", "", "", strings.Repeat("测", 500), false},
		{"超过简介长度", "", "", strings.Repeat("测", 501), true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			user := &domain.User{
				Username: "str_test_" + strings.ReplaceAll(tt.name, " ", "_"),
				Password: "$2a$10$dummy",
				Status:   domain.UserStatusActive,
				Nickname: tt.nickname,
				Region:   tt.region,
				Bio:      tt.bio,
			}
			err := env.userSvc.Create(ctx, user)

			if tt.wantError && err == nil {
				t.Error("期望错误但没有返回")
			}
			if !tt.wantError && err != nil {
				t.Errorf("不期望错误但返回: %v", err)
			}
		})
	}
}

// 辅助函数
func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}
