/**
 * Organization Module Integration Tests
 * 
 * 完整业务流程集成测试
 * 
 * 测试场景:
 * 1. 完整的用户生命周期 (创建→激活→停用→删除)
 * 2. 组织-部门-用户完整链路
 * 3. 多部门归属完整流程
 * 4. 权限系统集成测试
 * 5. 工作流角色解析集成测试
 * 
 * 基于文档: docs/modules/organization/09-test-scenarios.md (Section 5)
 */

import { Test, TestingModule } from '@nestjs/testing';
import { AppModule } from '@/app.module';
import { PrismaService } from '@/prisma/prisma.service';
import { UsersService } from '@/modules/organization/users/users.service';
import { DepartmentsService } from '@/modules/organization/departments/departments.service';
import { OrganizationsService } from '@/modules/organization/organizations/organizations.service';
import { UserDepartmentsService } from '@/modules/organization/user-departments/user-departments.service';
import { RolesService } from '@/modules/organization/roles/roles.service';

describe('Organization Module Integration Tests', () => {
  let module: TestingModule;
  let prisma: PrismaService;
  let usersService: UsersService;
  let departmentsService: DepartmentsService;
  let organizationsService: OrganizationsService;
  let userDepartmentsService: UserDepartmentsService;
  let rolesService: RolesService;

  // 测试数据
  const testData = {
    organization: null as any,
    departments: [] as any[],
    users: [] as any[],
    roles: [] as any[],
  };

  beforeAll(async () => {
    module = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    prisma = module.get<PrismaService>(PrismaService);
    usersService = module.get<UsersService>(UsersService);
    departmentsService = module.get<DepartmentsService>(DepartmentsService);
    organizationsService = module.get<OrganizationsService>(OrganizationsService);
    userDepartmentsService = module.get<UserDepartmentsService>(UserDepartmentsService);
    rolesService = module.get<RolesService>(RolesService);
  }, 30000);

  afterAll(async () => {
    await cleanupTestData();
    await module.close();
  }, 30000);

  async function cleanupTestData() {
    try {
      // 删除用户部门关联
      if (testData.users.length > 0) {
        await prisma.userDepartment.deleteMany({
          where: {
            userId: { in: testData.users.map(u => u.id) },
          },
        });

        // 删除用户角色
        await prisma.userRole.deleteMany({
          where: {
            userId: { in: testData.users.map(u => u.id) },
          },
        });

        // 删除用户
        await prisma.user.deleteMany({
          where: {
            id: { in: testData.users.map(u => u.id) },
          },
        });
      }

      // 删除部门 (从子到父)
      if (testData.departments.length > 0) {
        const departmentIds = testData.departments.map(d => d.id);
        await prisma.department.deleteMany({
          where: { id: { in: departmentIds } },
        });
      }

      // 删除组织
      if (testData.organization) {
        await prisma.organization.delete({
          where: { id: testData.organization.id },
        });
      }

      console.log('✅ Test data cleaned up');
    } catch (error) {
      console.error('Error during cleanup:', error);
    }
  }

  describe('[集成测试 5.1] 完整的用户生命周期', () => {
    let testUser: any;

    it('第1步: 创建新用户', async () => {
      const timestamp = Date.now();
      const dto = {
        username: `integration_test_${timestamp}`,
        email: `integration_test_${timestamp}@test.com`,
        displayName: 'Integration Test User',
        password: 'Test@123456',
        status: 'ACTIVE' as const,
      };

      testUser = await usersService.create(dto);

      expect(testUser).toBeDefined();
      expect(testUser.id).toBeDefined();
      expect(testUser.status).toBe('ACTIVE');
      expect(testUser.source).toBe('LOCAL');

      testData.users.push(testUser);
    });

    it('第2步: 查询用户详情', async () => {
      const user = await usersService.findById(testUser.id);

      expect(user).toBeDefined();
      expect(user.id).toBe(testUser.id);
      expect(user.username).toBe(testUser.username);
    });

    it('第3步: 更新用户信息', async () => {
      const updatedUser = await usersService.update(testUser.id, {
        displayName: 'Updated Display Name',
        phone: '+86 138-0000-0000',
      });

      expect(updatedUser.displayName).toBe('Updated Display Name');
      expect(updatedUser.phone).toBe('+86 138-0000-0000');
    });

    it('第4步: 停用用户', async () => {
      const suspendedUser = await usersService.updateStatus(testUser.id, {
        status: 'SUSPENDED' as const,
        reason: '集成测试',
      });

      expect(suspendedUser.status).toBe('SUSPENDED');
    });

    it('第5步: 重新激活用户', async () => {
      const activeUser = await usersService.updateStatus(testUser.id, {
        status: 'ACTIVE' as const,
        reason: '恢复激活',
      });

      expect(activeUser.status).toBe('ACTIVE');
    });

    it('第6步: 终止用户', async () => {
      const terminatedUser = await usersService.updateStatus(testUser.id, {
        status: 'TERMINATED' as const,
        reason: '测试完成',
      });

      expect(terminatedUser.status).toBe('TERMINATED');
    });

    it('第7步: 软删除用户', async () => {
      await usersService.remove(testUser.id);

      const deletedUser = await usersService.findById(testUser.id);
      expect(deletedUser).toBeNull();

      const withDeleted = await usersService.findById(testUser.id, {
        includeDeleted: true,
      });
      expect(withDeleted).toBeDefined();
      expect(withDeleted.deletedAt).toBeDefined();
    });
  });

  describe('[集成测试 5.2] 组织-部门-用户完整链路', () => {
    it('第1步: 创建组织', async () => {
      const timestamp = Date.now();
      testData.organization = await organizationsService.create({
        name: `Test Organization ${timestamp}`,
        shortName: `TEST-ORG-${timestamp}`,
        legalName: 'Test Org Legal Name',
        status: 'ACTIVE' as const,
      });

      expect(testData.organization).toBeDefined();
      expect(testData.organization.id).toBeDefined();
    });

    it('第2步: 创建部门树', async () => {
      // 创建根部门
      const rootDept = await departmentsService.create({
        name: 'Root Department',
        code: `ROOT_DEPT_${Date.now()}`,
        organizationId: testData.organization.id,
      });
      testData.departments.push(rootDept);

      // 创建子部门
      const childDept = await departmentsService.create({
        name: 'Child Department',
        code: `CHILD_DEPT_${Date.now()}`,
        parentId: rootDept.id,
        organizationId: testData.organization.id,
      });
      testData.departments.push(childDept);

      // 创建孙部门
      const grandchildDept = await departmentsService.create({
        name: 'Grandchild Department',
        code: `GRAND_DEPT_${Date.now()}`,
        parentId: childDept.id,
        organizationId: testData.organization.id,
      });
      testData.departments.push(grandchildDept);

      expect(testData.departments).toHaveLength(3);
      expect(grandchildDept.parentId).toBe(childDept.id);
    });

    it('第3步: 在部门中创建用户', async () => {
      const timestamp = Date.now();
      
      // 创建经理
      const manager = await usersService.create({
        username: `manager_${timestamp}`,
        email: `manager_${timestamp}@test.com`,
        displayName: 'Test Manager',
        password: 'Test@123456',
      });
      testData.users.push(manager);

      // 创建员工
      const employee = await usersService.create({
        username: `employee_${timestamp}`,
        email: `employee_${timestamp}@test.com`,
        displayName: 'Test Employee',
        password: 'Test@123456',
      });
      testData.users.push(employee);

      expect(testData.users).toHaveLength(2);
    });

    it('第4步: 将用户分配到部门', async () => {
      const [manager, employee] = testData.users;
      const [rootDept, childDept] = testData.departments;

      // 经理分配到根部门
      const managerDept = await userDepartmentsService.addUserToDepartment({
        userId: manager.id,
        departmentId: rootDept.id,
        isPrimary: true,
      });

      expect(managerDept.userId).toBe(manager.id);
      expect(managerDept.departmentId).toBe(rootDept.id);
      expect(managerDept.isPrimary).toBe(true);

      // 员工分配到子部门，汇报给经理
      const employeeDept = await userDepartmentsService.addUserToDepartment({
        userId: employee.id,
        departmentId: childDept.id,
        managerId: manager.id,
        isPrimary: true,
      });

      expect(employeeDept.userId).toBe(employee.id);
      expect(employeeDept.managerId).toBe(manager.id);
    });

    it('第5步: 查询部门成员', async () => {
      const [rootDept, childDept] = testData.departments;

      const rootMembers = await departmentsService.getMembers(rootDept.id);
      expect(rootMembers.length).toBeGreaterThan(0);

      const childMembers = await departmentsService.getMembers(childDept.id);
      expect(childMembers.length).toBeGreaterThan(0);
    });

    it('第6步: 查询用户的上级', async () => {
      const [manager, employee] = testData.users;

      const employeeDept = await prisma.userDepartment.findFirst({
        where: {
          userId: employee.id,
          isPrimary: true,
        },
      });

      expect(employeeDept.managerId).toBe(manager.id);
    });

    it('第7步: 查询经理的下属', async () => {
      const [manager] = testData.users;

      const subordinates = await usersService.getSubordinates(manager.id);
      
      expect(subordinates.length).toBeGreaterThan(0);
      expect(subordinates[0].managerId).toBe(manager.id);
    });

    it('第8步: 查询组织统计', async () => {
      const stats = await organizationsService.getStatistics(testData.organization.id);

      expect(stats.departmentCount).toBe(testData.departments.length);
      expect(stats.userCount).toBeGreaterThan(0);
    });
  });

  describe('[集成测试 5.3] 多部门归属完整流程', () => {
    let multiDeptUser: any;
    let primaryDept: any;
    let secondaryDept: any;

    it('第1步: 创建测试用户', async () => {
      const timestamp = Date.now();
      multiDeptUser = await usersService.create({
        username: `multi_dept_${timestamp}`,
        email: `multi_dept_${timestamp}@test.com`,
        displayName: 'Multi-Department User',
        password: 'Test@123456',
      });

      testData.users.push(multiDeptUser);
      expect(multiDeptUser).toBeDefined();
    });

    it('第2步: 添加到主部门', async () => {
      primaryDept = testData.departments[0];

      const result = await userDepartmentsService.addUserToDepartment({
        userId: multiDeptUser.id,
        departmentId: primaryDept.id,
        isPrimary: true,
      });

      expect(result.isPrimary).toBe(true);
    });

    it('第3步: 添加到兼职部门', async () => {
      secondaryDept = testData.departments[1];

      const result = await userDepartmentsService.addUserToDepartment({
        userId: multiDeptUser.id,
        departmentId: secondaryDept.id,
        isPrimary: false,
      });

      expect(result.isPrimary).toBe(false);
    });

    it('第4步: 查询用户的所有部门', async () => {
      const departments = await userDepartmentsService.getUserDepartments(
        multiDeptUser.id
      );

      expect(departments.primaryDepartment).toBeDefined();
      expect(departments.primaryDepartment.departmentId).toBe(primaryDept.id);
      expect(departments.otherDepartments.length).toBeGreaterThan(0);
    });

    it('第5步: 切换主部门', async () => {
      await userDepartmentsService.setPrimaryDepartment(
        multiDeptUser.id,
        secondaryDept.id
      );

      const departments = await userDepartmentsService.getUserDepartments(
        multiDeptUser.id
      );

      expect(departments.primaryDepartment.departmentId).toBe(secondaryDept.id);
    });

    it('第6步: 更新部门归属信息', async () => {
      const updated = await userDepartmentsService.updateUserDepartment(
        multiDeptUser.id,
        secondaryDept.id,
        {
          title: 'Senior Engineer',
        }
      );

      expect(updated.title).toBe('Senior Engineer');
    });

    it('第7步: 移除非主部门', async () => {
      await userDepartmentsService.removeUserFromDepartment(
        multiDeptUser.id,
        primaryDept.id
      );

      const departments = await userDepartmentsService.getUserDepartments(
        multiDeptUser.id
      );

      const hasPrimaryDept = departments.otherDepartments.some(
        d => d.departmentId === primaryDept.id
      );
      expect(hasPrimaryDept).toBe(false);
    });
  });

  describe('[集成测试 5.4] 权限系统集成测试', () => {
    let testUser: any;
    let testRole: any;

    it('第1步: 创建测试角色', async () => {
      const timestamp = Date.now();
      testRole = await rolesService.create({
        code: `TEST_ROLE_${timestamp}`,
        name: 'Test Role',
        description: 'Integration test role',
      });

      testData.roles.push(testRole);
      expect(testRole).toBeDefined();
    });

    it('第2步: 为角色分配权限', async () => {
      // 获取一些测试权限
      const permissions = await prisma.permission.findMany({
        where: {
          resource: 'user',
          action: 'read',
        },
        take: 2,
      });

      if (permissions.length > 0) {
        await rolesService.assignPermissions(
          testRole.id,
          permissions.map(p => p.id)
        );

        const roleWithPermissions = await rolesService.findById(testRole.id);
        expect(roleWithPermissions.permissions.length).toBeGreaterThan(0);
      }
    });

    it('第3步: 为用户分配角色', async () => {
      testUser = testData.users[0];

      await rolesService.assignUsersToRole(testRole.id, [testUser.id], {
        organizationId: testData.organization.id,
      });

      const userRoles = await prisma.userRole.findMany({
        where: {
          userId: testUser.id,
          roleId: testRole.id,
        },
      });

      expect(userRoles.length).toBeGreaterThan(0);
      expect(userRoles[0].organizationId).toBe(testData.organization.id);
    });

    it('第4步: 查询用户权限', async () => {
      const userPermissions = await usersService.getPermissions(testUser.id);

      expect(userPermissions).toBeDefined();
      expect(userPermissions.userId).toBe(testUser.id);
      expect(Array.isArray(userPermissions.permissions)).toBe(true);
      expect(Array.isArray(userPermissions.roles)).toBe(true);
    });

    it('第5步: 移除用户角色', async () => {
      await rolesService.removeUserFromRole(testRole.id, testUser.id);

      const userRoles = await prisma.userRole.findMany({
        where: {
          userId: testUser.id,
          roleId: testRole.id,
        },
      });

      expect(userRoles).toHaveLength(0);
    });

    it('第6步: 删除测试角色', async () => {
      await rolesService.remove(testRole.id);

      const deletedRole = await rolesService.findById(testRole.id);
      expect(deletedRole).toBeNull();
    });
  });

  describe('[集成测试 5.5] v2.1 组织级权限隔离集成', () => {
    let user: any;
    let role1: any;
    let role2: any;
    let org2: any;

    it('第1步: 准备第二个组织', async () => {
      const timestamp = Date.now();
      org2 = await organizationsService.create({
        name: `Test Org 2 ${timestamp}`,
        shortName: `TEST-ORG2-${timestamp}`,
        status: 'ACTIVE' as const,
      });

      expect(org2).toBeDefined();
    });

    it('第2步: 创建两个角色', async () => {
      const timestamp = Date.now();
      
      role1 = await rolesService.create({
        code: `ROLE1_${timestamp}`,
        name: 'Role 1',
        description: 'Test role 1',
      });

      role2 = await rolesService.create({
        code: `ROLE2_${timestamp}`,
        name: 'Role 2',
        description: 'Test role 2',
      });

      testData.roles.push(role1, role2);
    });

    it('第3步: 为用户在不同组织分配不同角色', async () => {
      user = testData.users[0];

      // 在组织1分配角色1
      await prisma.userRole.create({
        data: {
          userId: user.id,
          roleId: role1.id,
          organizationId: testData.organization.id,
          assignedBy: null,
        },
      });

      // 在组织2分配角色2
      await prisma.userRole.create({
        data: {
          userId: user.id,
          roleId: role2.id,
          organizationId: org2.id,
          assignedBy: null,
        },
      });

      const allRoles = await prisma.userRole.findMany({
        where: { userId: user.id },
      });

      expect(allRoles.length).toBeGreaterThanOrEqual(2);
    });

    it('第4步: 按组织查询用户角色', async () => {
      const org1Roles = await prisma.userRole.findMany({
        where: {
          userId: user.id,
          organizationId: testData.organization.id,
        },
      });

      const org2Roles = await prisma.userRole.findMany({
        where: {
          userId: user.id,
          organizationId: org2.id,
        },
      });

      expect(org1Roles.some(r => r.roleId === role1.id)).toBe(true);
      expect(org2Roles.some(r => r.roleId === role2.id)).toBe(true);
    });

    it('第5步: 验证权限隔离', async () => {
      // 组织1的角色不应出现在组织2的查询中
      const org1Roles = await prisma.userRole.findMany({
        where: {
          userId: user.id,
          organizationId: testData.organization.id,
        },
      });

      const org2Roles = await prisma.userRole.findMany({
        where: {
          userId: user.id,
          organizationId: org2.id,
        },
      });

      const org1RoleIds = org1Roles.map(r => r.roleId);
      const org2RoleIds = org2Roles.map(r => r.roleId);

      expect(org1RoleIds).not.toContain(role2.id);
      expect(org2RoleIds).not.toContain(role1.id);
    });

    it('清理: 删除第二个组织', async () => {
      // 删除用户角色
      await prisma.userRole.deleteMany({
        where: { organizationId: org2.id },
      });

      // 删除组织
      await prisma.organization.delete({
        where: { id: org2.id },
      });
    });
  });

  describe('[性能测试] 复杂查询性能', () => {
    it('应该高效查询组织的完整信息', async () => {
      const startTime = Date.now();

      await prisma.organization.findUnique({
        where: { id: testData.organization.id },
        include: {
          departments: {
            include: {
              members: {
                include: {
                  user: true,
                },
              },
            },
          },
        },
      });

      const endTime = Date.now();
      const duration = endTime - startTime;

      // 复杂查询应在200ms内完成
      expect(duration).toBeLessThan(200);
    });

    it('应该高效查询用户的所有权限', async () => {
      const user = testData.users[0];

      const startTime = Date.now();

      await usersService.getPermissions(user.id);

      const endTime = Date.now();
      const duration = endTime - startTime;

      // 权限查询应在100ms内完成
      expect(duration).toBeLessThan(100);
    });
  });
});

