/**
 * User Factory - 测试数据工厂
 * 
 * 用于生成测试用户数据
 * 
 * 基于文档: docs/modules/organization/09-test-scenarios.md - 测试工具和辅助函数
 * 版本: v2.1.1
 */

import { PrismaClient } from '@prisma/client';
import * as bcrypt from 'bcrypt';

const prisma = new PrismaClient();

/**
 * 生成随机字符串（增加唯一性，避免并行测试冲突）
 */
export function randomString(length: number = 12): string {
  const timestamp = Date.now().toString(36); // 时间戳转36进制
  const random = Math.random().toString(36).substring(2, 2 + length);
  return `${timestamp}_${random}`;
}

/**
 * 创建测试用户
 * 支持传入 password，会自动转换为 passwordHash
 */
export async function createTestUser(overrides: any = {}) {
  const defaultData: any = {
    username: `user_${randomString()}`,
    email: `${randomString()}@example.com`,
    displayName: `测试用户_${randomString()}`,
    status: 'ACTIVE',
    source: 'LOCAL',
    defaultRegion: 'CN',
    passwordHash: '$2b$10$defaulthash',
  };

  // 如果提供了 password，转换为 passwordHash
  if (overrides.password) {
    overrides.passwordHash = await bcrypt.hash(overrides.password, 10);
    delete overrides.password;
  }

  return await prisma.user.create({
    data: {
      ...defaultData,
      ...overrides,
    },
    include: {
      departmentMemberships: {
        include: {
          department: true,
          position: true,
        },
      },
      roles: {
        include: {
          role: {
            include: {
              permissions: {
                include: {
                  permission: true,
                },
              },
            },
          },
        },
      },
    },
  });
}

/**
 * 批量创建测试用户
 */
export async function createManyTestUsers(count: number) {
  const users = [];
  for (let i = 0; i < count; i++) {
    const user = await createTestUser({
      username: `user_${i}_${randomString(4)}`,
      email: `user${i}_${randomString(4)}@example.com`,
      displayName: `用户${i}`,
    });
    users.push(user);
  }
  return users;
}

/**
 * 创建 LDAP 用户（v2.1.1）
 */
export async function createLdapUser(overrides: any = {}) {
  return await createTestUser({
    source: 'LDAP',
    ldapDn: `CN=User${randomString()},OU=Users,DC=company,DC=com`,
    passwordHash: null,
    ...overrides,
  });
}

/**
 * 创建 Entra ID 用户（v2.1.1）
 */
export async function createEntraUser(overrides: any = {}) {
  return await createTestUser({
    source: 'ENTRA',
    externalId: `entra-${randomString()}`,
    externalSource: 'ENTRA_ID',
    passwordHash: null,
    ...overrides,
  });
}

// 全局变量：用于缓存管理员角色ID，避免重复初始化
let _cachedAdminRoleId: string | null = null;

/**
 * 确保管理员角色和权限已初始化
 * 使用缓存避免并发测试时的重复初始化
 */
async function ensureAdminRoleAndPermissions(): Promise<string> {
  // 如果已经缓存了角色ID，直接返回
  if (_cachedAdminRoleId) {
    const roleExists = await prisma.role.findUnique({
      where: { id: _cachedAdminRoleId },
    });
    if (roleExists) {
      return _cachedAdminRoleId;
    }
    // 如果角色不存在（可能被清理了），重置缓存
    _cachedAdminRoleId = null;
  }

  // 创建或获取管理员角色
  const adminRole = await prisma.role.upsert({
    where: { code: 'Administrator' },
    create: {
      code: 'Administrator',
      name: '系统管理员',
      description: 'System administrator with full access',
      isBuiltIn: true,
      enabled: true,
    },
    update: {
      enabled: true, // 确保启用
    },
  });

  // 创建管理员所需的所有权限
  const permissions = [
    { resource: 'organization', action: 'read' },
    { resource: 'organization', action: 'create' },
    { resource: 'organization', action: 'update' },
    { resource: 'organization', action: 'delete' },
    { resource: 'user', action: 'read' },
    { resource: 'user', action: 'create' },
    { resource: 'user', action: 'update' },
    { resource: 'user', action: 'delete' },
    { resource: 'department', action: 'read' },
    { resource: 'department', action: 'create' },
    { resource: 'department', action: 'update' },
    { resource: 'department', action: 'delete' },
    { resource: 'role', action: 'read' },
    { resource: 'role', action: 'create' },
    { resource: 'role', action: 'update' },
    { resource: 'role', action: 'delete' },
    { resource: 'permission', action: 'read' },
    { resource: 'permission', action: 'assign' },
    { resource: 'region', action: 'read' },
    { resource: 'region', action: 'create' },
    { resource: 'region', action: 'update' },
    { resource: 'region', action: 'delete' },
    { resource: 'position', action: 'read' },
    { resource: 'position', action: 'create' },
    { resource: 'position', action: 'update' },
    { resource: 'position', action: 'delete' },
    { resource: 'workflow-role', action: 'read' },
    { resource: 'workflow-role', action: 'create' },
    { resource: 'workflow-role', action: 'update' },
    { resource: 'workflow-role', action: 'delete' },
    // AI 工具授权（v2.2 权限 MVP）
    { resource: 'ai_tool', action: 'read' },
    { resource: 'ai_tool', action: 'manage' },
    // AI 流程图生成器
    { resource: 'flow', action: 'create' },
    { resource: 'flow', action: 'read' },
    { resource: 'flow', action: 'update' },
    { resource: 'flow', action: 'delete' },
    { resource: 'flow', action: 'share' },
  ];

  for (const perm of permissions) {
    const permission = await prisma.permission.upsert({
      where: {
        resource_action: {
          resource: perm.resource,
          action: perm.action,
        },
      },
      create: {
        resource: perm.resource,
        action: perm.action,
        module: 'organization',
        isBuiltIn: true,
      },
      update: {},
    });

    // 分配权限给管理员角色
    await prisma.rolePermission.upsert({
      where: {
        roleId_permissionId: {
          roleId: adminRole.id,
          permissionId: permission.id,
        },
      },
      create: {
        roleId: adminRole.id,
        permissionId: permission.id,
      },
      update: {},
    });
  }

  // 缓存角色ID
  _cachedAdminRoleId = adminRole.id;
  return adminRole.id;
}

/**
 * 创建管理员用户（包含管理员角色和权限）
 * 用于集成测试，确保有足够权限执行所有操作
 * 
 * v2.1: 不支持全局管理员，管理员需要绑定到测试组织
 */
export async function createAdminUser(overrides: any = {}) {
  // 确保管理员角色和权限已初始化
  const adminRoleId = await ensureAdminRoleAndPermissions();

  // v2.1: 创建或获取测试组织（用于绑定管理员）
  const testOrg = await prisma.organization.upsert({
    where: { code: 'TEST_ADMIN_ORG' },
    create: {
      code: 'TEST_ADMIN_ORG',
      name: 'Test Admin Organization',
      status: 'ACTIVE',
    },
    update: {},
  });

  // 创建用户
  const user = await createTestUser({
    username: `admin_${randomString()}`,
    email: `admin_${randomString()}@example.com`,
    password: 'Admin@123',
    ...overrides,
  });

  // v2.1: 分配管理员角色到测试组织（不再支持全局管理员）
  await prisma.userRole.create({
    data: {
      userId: user.id,
      roleId: adminRoleId,
      organizationId: testOrg.id, // 必须绑定到组织
    },
  });

  return user;
}

/**
 * 清理测试用户
 */
export async function cleanupTestUsers() {
  await prisma.userRole.deleteMany({});
  await prisma.userDepartment.deleteMany({});
  await prisma.user.deleteMany({});
}


