/**
 * Workflow Roles API Integration Tests
 * 
 * 基于 HTTP API 的真正集成测试
 * 
 * 测试内容：
 * - 流程角色 CRUD 操作
 * - 组织关系规则创建
 * - 固定用户规则创建
 * - 用户分配（FIXED_USERS 类型）
 * - v2.1.18 连续部门主管链解析
 * 
 * 基于文档: docs/modules/organization/07-api.md (Section 6: 流程角色管理)
 * 
 * 注意: resolve 接口为服务间调用接口，需要特殊鉴权，不在此测试
 * 
 * @version v2.1.18
 */

import { INestApplication } from '@nestjs/common';
import request from 'supertest';
import { PrismaService } from '@/core/database/prisma/prisma.service';
import { cleanupDatabase } from '../../helpers/cleanup.helper';
import { createTestApp } from '../../helpers/app.helper';
import { setupIntegrationTest, createTestOrganization } from '../../helpers/test-setup.helper';

describe('Workflow Roles API Integration Tests', () => {
  let app: INestApplication;
  let prisma: PrismaService;
  let adminToken: string;
  let organizationId: string;
  let rootDepartmentId: string;

  beforeAll(async () => {
    app = await createTestApp();
    prisma = app.get<PrismaService>(PrismaService);
  });

  beforeEach(async () => {
    // 🎯 使用统一的测试设置 helper（自动清理、创建管理员、登录）
    const context = await setupIntegrationTest(app, prisma);
    adminToken = context.adminToken;

    // 创建测试组织（自动创建根部门）
    const org = await createTestOrganization(app, adminToken, prisma, {
      name: 'Test Organization',
    });
    organizationId = org.organizationId;
    rootDepartmentId = org.rootDepartmentId;
  });

  afterAll(async () => {
    // 最终清理和关闭应用
    await cleanupDatabase(prisma);
    await app.close();
  });

  /**
   * 🔧 辅助函数：创建测试流程角色
   * 简化重复的流程角色创建逻辑
   */
  async function createTestWorkflowRole(roleData: {
    name: string;
    code?: string;
    description?: string;
    ruleType: 'ORGANIZATION_RELATION' | 'FIXED_USERS';
    ruleConfig?: any;
  }) {
    const uniqueId = `${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
    const code = roleData.code ? `${roleData.code}_${uniqueId}` : `WF_ROLE_${uniqueId}`;

    const response = await request(app.getHttpServer())
      .post('/api/v1/workflow-roles')
      .set('Authorization', `Bearer ${adminToken}`)
      .send({
        code,
        name: `${roleData.name}_${uniqueId}`,
        description: roleData.description,
        ruleType: roleData.ruleType,
        ruleConfig: roleData.ruleConfig || {},
      })
      .expect(201);

    return {
      workflowRoleId: response.body.data.id,
      code,
      roleData: response.body.data,
    };
  }

  describe('GET /api/v1/workflow-roles - 查询流程角色列表', () => {
    let createdRoleName: string;

    beforeEach(async () => {
      // 🎯 使用辅助函数创建测试流程角色
      const role = await createTestWorkflowRole({
        name: '测试直属上级',
        code: 'WF_DIRECT_MGR',
        description: '解析发起人的直属上级',
        ruleType: 'ORGANIZATION_RELATION',
        ruleConfig: {
          relation: 'manager',
        },
      });
      createdRoleName = role.roleData.name;
    });

    it('[API-WF-001] 应该返回流程角色列表', async () => {
      const response = await request(app.getHttpServer())
        .get('/api/v1/workflow-roles')
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(200);

      expect(response.body.success).toBe(true);
      expect(Array.isArray(response.body.data)).toBe(true);
      expect(response.body.data.length).toBeGreaterThan(0);
      expect(response.body.data[0]).toHaveProperty('id');
      expect(response.body.data[0]).toHaveProperty('code');
      expect(response.body.data[0]).toHaveProperty('name');
      expect(response.body.data[0]).toHaveProperty('ruleType');
    });

    it('[API-WF-002] 应该支持关键字搜索', async () => {
      const response = await request(app.getHttpServer())
        .get('/api/v1/workflow-roles')
        .set('Authorization', `Bearer ${adminToken}`)
        .query({ keyword: '测试直属上级' })
        .expect(200);

      expect(response.body.success).toBe(true);
      expect(response.body.data.length).toBeGreaterThan(0);
      expect(response.body.data[0].name).toContain('测试直属上级');
    });
  });

  describe('POST /api/v1/workflow-roles - 创建流程角色', () => {
    it('[API-WF-003] 应该成功创建组织关系类型流程角色', async () => {
      const uniqueSuffix = `${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
      const createDto = {
        code: `WF_TEST_ORGREL_${uniqueSuffix}`,
        name: `测试组织关系角色_${uniqueSuffix}`,
        description: '解析发起人的直属上级',
        ruleType: 'ORGANIZATION_RELATION',
        ruleConfig: {
          relation: 'manager',
          fallbackType: 'UP_CHAIN',
          fallbackConfig: { maxLevel: 2 },
        },
      };

      const response = await request(app.getHttpServer())
        .post('/api/v1/workflow-roles')
        .set('Authorization', `Bearer ${adminToken}`)
        .send(createDto)
        .expect(201);

      expect(response.body.success).toBe(true);
      expect(response.body.data).toHaveProperty('id');
      expect(response.body.data.code).toBe(createDto.code);
      expect(response.body.data.name).toBe(createDto.name);
      expect(response.body.data.ruleType).toBe('ORGANIZATION_RELATION');

      // 验证数据库
      const workflowRole = await prisma.workflowRole.findUnique({
        where: { id: response.body.data.id },
      });

      expect(workflowRole).toBeDefined();
      expect(workflowRole!.code).toBe(createDto.code);
    });

    it('[API-WF-004] 应该成功创建固定用户类型流程角色', async () => {
      const uniqueSuffix = `${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
      const createDto = {
        code: `WF_TEST_FIXED_${uniqueSuffix}`,
        name: `测试固定用户角色_${uniqueSuffix}`,
        description: '财务部门固定审批人',
        ruleType: 'FIXED_USERS',
        ruleConfig: {},
      };

      const response = await request(app.getHttpServer())
        .post('/api/v1/workflow-roles')
        .set('Authorization', `Bearer ${adminToken}`)
        .send(createDto)
        .expect(201);

      expect(response.body.success).toBe(true);
      expect(response.body.data.ruleType).toBe('FIXED_USERS');

      // 验证数据库
      const workflowRole = await prisma.workflowRole.findUnique({
        where: { id: response.body.data.id },
      });

      expect(workflowRole).toBeDefined();
    });

    it('[API-WF-005] 应该成功创建连续部门主管链类型 (v2.1.18 ⭐)', async () => {
      const uniqueSuffix = `${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
      const createDto = {
        code: `WF_TEST_CHAIN_${uniqueSuffix}`,
        name: `测试部门主管链_${uniqueSuffix}`,
        description: '从用户部门到顶级部门的所有主管',
        ruleType: 'ORGANIZATION_RELATION',
        ruleConfig: {
          relation: 'departmentHeadChain',
          stopAtLevel: 1, // 在一级部门停止
        },
      };

      const response = await request(app.getHttpServer())
        .post('/api/v1/workflow-roles')
        .set('Authorization', `Bearer ${adminToken}`)
        .send(createDto)
        .expect(201);

      expect(response.body.success).toBe(true);
      expect(response.body.data.code).toBe(createDto.code);
      expect(response.body.data.ruleConfig).toHaveProperty('stopAtLevel', 1);
    });

    it('[API-WF-006] 代码必须以 WF_ 开头', async () => {
      const response = await request(app.getHttpServer())
        .post('/api/v1/workflow-roles')
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          code: 'INVALID_CODE', // 没有 WF_ 前缀
          name: '无效角色',
          ruleType: 'FIXED_USERS',
          ruleConfig: {},
        })
        .expect(400);

      expect(response.body.success).toBe(false);
      // 验证错误消息或详情中包含 WF_ 相关信息
      const errorStr = JSON.stringify(response.body.error);
      expect(errorStr).toContain('WF_');
    });

    it('[API-WF-007] 代码重复应返回409', async () => {
      const uniqueSuffix = `${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
      const duplicateCode = `WF_TEST_DUP_${uniqueSuffix}`;

      // 先创建一个流程角色
      await request(app.getHttpServer())
        .post('/api/v1/workflow-roles')
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          code: duplicateCode,
          name: `测试角色A_${uniqueSuffix}`,
          ruleType: 'FIXED_USERS',
          ruleConfig: {},
        })
        .expect(201);

      // 尝试创建相同代码的角色
      const response = await request(app.getHttpServer())
        .post('/api/v1/workflow-roles')
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          code: duplicateCode, // 相同代码
          name: `测试角色B_${uniqueSuffix}`,
          ruleType: 'FIXED_USERS',
          ruleConfig: {},
        })
        .expect(409);

      expect(response.body.success).toBe(false);
    });
  });

  describe('GET /api/v1/workflow-roles/:id - 查询流程角色详情', () => {
    let workflowRoleId: string;
    let createdRoleCode: string;

    beforeEach(async () => {
      // 🎯 使用辅助函数创建测试流程角色
      const role = await createTestWorkflowRole({
        name: '测试详情角色',
        code: 'WF_DETAIL',
        ruleType: 'ORGANIZATION_RELATION',
        ruleConfig: {
          relation: 'manager',
        },
      });
      workflowRoleId = role.workflowRoleId;
      createdRoleCode = role.code;
    });

    it('[API-WF-008] 应该返回流程角色详情', async () => {
      const response = await request(app.getHttpServer())
        .get(`/api/v1/workflow-roles/${workflowRoleId}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(200);

      expect(response.body.success).toBe(true);
      expect(response.body.data).toHaveProperty('id', workflowRoleId);
      expect(response.body.data.code).toBe(createdRoleCode);
      expect(response.body.data).toHaveProperty('ruleConfig');
    });

    it('[API-WF-009] 流程角色不存在应返回404', async () => {
      // 使用有效的UUID格式但不存在的ID
      const response = await request(app.getHttpServer())
        .get('/api/v1/workflow-roles/00000000-0000-0000-0000-000000000000')
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(404);

      expect(response.body.success).toBe(false);
    });
  });

  describe('PATCH /api/v1/workflow-roles/:id - 更新流程角色', () => {
    let workflowRoleId: string;

    beforeEach(async () => {
      // 🎯 使用辅助函数创建测试流程角色
      const role = await createTestWorkflowRole({
        name: '测试角色',
        code: 'WF_TEST',
        ruleType: 'FIXED_USERS',
      });
      workflowRoleId = role.workflowRoleId;
    });

    it('[API-WF-010] 应该成功更新流程角色', async () => {
      const updateDto = {
        name: '更新后的角色',
        description: '新的描述',
      };

      const response = await request(app.getHttpServer())
        .put(`/api/v1/workflow-roles/${workflowRoleId}`)  // ✅ 使用 PUT
        .set('Authorization', `Bearer ${adminToken}`)
        .send(updateDto)
        .expect(200);

      expect(response.body.success).toBe(true);
      expect(response.body.data.name).toBe('更新后的角色');
      expect(response.body.data.description).toBe('新的描述');

      // 验证数据库
      const workflowRole = await prisma.workflowRole.findUnique({
        where: { id: workflowRoleId },
      });

      expect(workflowRole!.name).toBe('更新后的角色');
    });

    it('[API-WF-011] 不能修改流程角色代码', async () => {
      const response = await request(app.getHttpServer())
        .put(`/api/v1/workflow-roles/${workflowRoleId}`)  // ✅ 使用 PUT
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          code: 'WF_NEW_CODE', // 尝试修改代码
        })
        .expect(400);

      expect(response.body.success).toBe(false);
    });
  });

  describe('DELETE /api/v1/workflow-roles/:id - 删除流程角色', () => {
    let workflowRoleId: string;

    beforeEach(async () => {
      // 🎯 使用辅助函数创建测试流程角色
      const role = await createTestWorkflowRole({
        name: '测试角色',
        code: 'WF_TEST',
        ruleType: 'FIXED_USERS',
      });
      workflowRoleId = role.workflowRoleId;
    });

    it('[API-WF-012] 应该成功删除流程角色', async () => {
      await request(app.getHttpServer())
        .delete(`/api/v1/workflow-roles/${workflowRoleId}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(200);

      // 验证已删除
      const workflowRole = await prisma.workflowRole.findUnique({
        where: { id: workflowRoleId },
      });

      expect(workflowRole).toBeNull();
    });
  });

  describe('POST /api/v1/workflow-roles/:id/users - 分配用户（FIXED_USERS 类型）', () => {
    let workflowRoleId: string;
    let userId: string;

    beforeEach(async () => {
      // 🎯 使用辅助函数创建 FIXED_USERS 类型流程角色
      const role = await createTestWorkflowRole({
        name: '财务审批人',
        code: 'WF_FINANCE_APPROVER',
        ruleType: 'FIXED_USERS',
      });
      workflowRoleId = role.workflowRoleId;

      // 创建用户
      const userResponse = await request(app.getHttpServer())
        .post('/api/v1/users')
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          username: 'finance',
          email: 'finance@example.com',
          password: 'Test@123',
          displayName: 'Finance User',
        });

      userId = userResponse.body.data.id;
    });

    it('[API-WF-013] 应该成功分配用户到固定用户类型流程角色', async () => {
      const response = await request(app.getHttpServer())
        .post(`/api/v1/workflow-roles/${workflowRoleId}/users`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          userIds: [userId],
        })
        .expect(200);  // ✅ 关联操作返回 200

      expect(response.body.success).toBe(true);
      expect(response.body.data).toHaveLength(1);
      expect(response.body.data[0].id).toBe(userId);

      // 验证数据库
      const assignments = await prisma.workflowRoleUser.findMany({
        where: {
          workflowRoleId,
          userId,
        },
      });

      expect(assignments).toHaveLength(1);
    });

    it('[API-WF-014] 非 FIXED_USERS 类型不能分配用户', async () => {
      // 🎯 使用辅助函数创建 ORGANIZATION_RELATION 类型流程角色
      const orgRole = await createTestWorkflowRole({
        name: '上级',
        code: 'WF_MANAGER',
        ruleType: 'ORGANIZATION_RELATION',
        ruleConfig: {
          relation: 'manager',
        },
      });

      // 尝试分配用户
      const response = await request(app.getHttpServer())
        .post(`/api/v1/workflow-roles/${orgRole.workflowRoleId}/users`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          userIds: [userId],
        })
        .expect(400);

      expect(response.body.success).toBe(false);
      expect(response.body.error.message).toContain('FIXED_USERS');
    });

    it('[API-WF-015] 重复分配应幂等', async () => {
      // 第一次分配
      await request(app.getHttpServer())
        .post(`/api/v1/workflow-roles/${workflowRoleId}/users`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          userIds: [userId],
        })
        .expect(200);

      // 第二次分配相同用户
      const response = await request(app.getHttpServer())
        .post(`/api/v1/workflow-roles/${workflowRoleId}/users`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          userIds: [userId],
        })
        .expect(200);

      expect(response.body.success).toBe(true);

      // 验证数据库中只有一条记录
      const assignments = await prisma.workflowRoleUser.findMany({
        where: {
          workflowRoleId,
          userId,
        },
      });

      expect(assignments).toHaveLength(1);
    });
  });

  describe('完整业务流程测试', () => {
    it('[API-WF-FLOW-001] 应该完成完整的流程角色创建和用户分配流程', async () => {
      // 1. 🎯 使用辅助函数创建流程角色
      const { workflowRoleId, code: createdCode } = await createTestWorkflowRole({
        name: '测试流程审批人',
        code: 'WF_FLOW_APPROVER',
        description: '财务部门固定审批人',
        ruleType: 'FIXED_USERS',
      });

      // 2. 创建用户
      const user1Response = await request(app.getHttpServer())
        .post('/api/v1/users')
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          username: 'finance1',
          email: 'finance1@example.com',
          password: 'Test@123',
          displayName: 'Finance User 1',
        });

      const user2Response = await request(app.getHttpServer())
        .post('/api/v1/users')
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          username: 'finance2',
          email: 'finance2@example.com',
          password: 'Test@123',
          displayName: 'Finance User 2',
        });

      // 3. 分配用户
      const assignResponse = await request(app.getHttpServer())
        .post(`/api/v1/workflow-roles/${workflowRoleId}/users`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          userIds: [user1Response.body.data.id, user2Response.body.data.id],
        })
        .expect(200);  // ✅ 关联操作返回 200

      expect(assignResponse.body.success).toBe(true);

      // 4. 查询流程角色详情
      const detailResponse = await request(app.getHttpServer())
        .get(`/api/v1/workflow-roles/${workflowRoleId}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(200);

      expect(detailResponse.body.data.code).toBe(createdCode);

      // 5. 更新流程角色
      await request(app.getHttpServer())
        .put(`/api/v1/workflow-roles/${workflowRoleId}`)  // ✅ 使用 PUT
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          description: '更新后的描述',
        })
        .expect(200);

      // 6. 查询列表
      const listResponse = await request(app.getHttpServer())
        .get('/api/v1/workflow-roles')
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(200);

      expect(listResponse.body.data.length).toBeGreaterThan(0);

      console.log('✅ 流程角色创建和用户分配完整流程测试通过');
    });
  });
});

