/**
 * Organizations API Integration Tests
 * 
 * 基于 HTTP API 的真正集成测试
 * 
 * 测试内容：
 * - HTTP 请求/响应
 * - 状态码验证
 * - DTO 验证
 * - 认证和授权
 * - 数据库状态验证
 * 
 * 基于文档: docs/modules/organization/07-api.md (Section 2: 组织管理)
 * 
 * @version v2.1.2 (优化版 - 使用 test-setup.helper)
 */

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

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

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

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

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

  describe('POST /api/v1/organizations - 创建组织', () => {
    it('[API-ORG-001] 应该成功创建组织并返回201', async () => {
      const createDto = {
        code: 'FF_CHINA',
        name: 'FF China',
        legalName: '法拉第未来（中国）有限公司',
        taxId: '91110000MA001234XX',
        address: '北京市朝阳区',
      };

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

      // 验证响应格式
      expect(response.body).toHaveProperty('success', true);
      expect(response.body).toHaveProperty('data');
      expect(response.body.data).toHaveProperty('id');
      expect(response.body.data.code).toBe('FF_CHINA');
      expect(response.body.data.name).toBe('FF China');

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

      expect(org).toBeDefined();
      expect(org!.code).toBe('FF_CHINA');
      expect(org!.legalName).toBe('法拉第未来（中国）有限公司');

      // v2.1.17: 验证根部门自动创建
      const rootDept = await prisma.department.findFirst({
        where: {
          organizationId: org!.id,
          parentId: null,
        },
      });

      expect(rootDept).toBeDefined();
      expect(rootDept!.name).toBe('FF China');
    });

    it('[API-ORG-002] 组织代码重复应返回409', async () => {
      // 先创建一个组织
      await request(app.getHttpServer())
        .post('/api/v1/organizations')
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          code: 'FF_CHINA',
          name: 'FF China',
        })
        .expect(201);

      // 尝试创建相同代码的组织
      const response = await request(app.getHttpServer())
        .post('/api/v1/organizations')
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          code: 'FF_CHINA',
          name: 'FF China 2',
        })
        .expect(409);

      expect(response.body.success).toBe(false);
      expect(response.body.error).toBeDefined();
      expect(response.body.error.code).toContain('ORG');
    });

    it('[API-ORG-003] 缺少必填字段应返回400', async () => {
      const response = await request(app.getHttpServer())
        .post('/api/v1/organizations')
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          // 缺少 code 和 name
          legalName: 'Test Company',
        })
        .expect(400);

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

    it('[API-ORG-004] 未授权访问应返回401', async () => {
      await request(app.getHttpServer())
        .post('/api/v1/organizations')
        .send({
          code: 'FF_CHINA',
          name: 'FF China',
        })
        .expect(401);
    });
  });

  describe('GET /api/v1/organizations - 查询组织列表', () => {
    beforeEach(async () => {
      // 创建测试数据（使用 Promise.all 并行创建）
      await Promise.all([
        request(app.getHttpServer())
          .post('/api/v1/organizations')
          .set('Authorization', `Bearer ${adminToken}`)
          .send({ code: 'FF_CN', name: 'FF China' }),
        request(app.getHttpServer())
          .post('/api/v1/organizations')
          .set('Authorization', `Bearer ${adminToken}`)
          .send({ code: 'FF_US', name: 'FF USA' }),
      ]);
    });

    it('[API-ORG-005] 应该返回组织列表（分页）', async () => {
      const response = await request(app.getHttpServer())
        .get('/api/v1/organizations')
        .set('Authorization', `Bearer ${adminToken}`)
        .query({ page: 1, pageSize: 10 })
        .expect(200);

      expect(response.body.success).toBe(true);
      expect(response.body.data).toHaveProperty('items');
      expect(response.body.data).toHaveProperty('total');
      expect(response.body.data).toHaveProperty('page');
      expect(response.body.data).toHaveProperty('pageSize');
      expect(Array.isArray(response.body.data.items)).toBe(true);
      expect(response.body.data.items.length).toBeGreaterThan(0);
    });

    it('[API-ORG-006] 应该支持关键字搜索', async () => {
      const response = await request(app.getHttpServer())
        .get('/api/v1/organizations')
        .set('Authorization', `Bearer ${adminToken}`)
        .query({ keyword: 'China' })
        .expect(200);

      expect(response.body.success).toBe(true);
      expect(response.body.data.items.length).toBeGreaterThan(0);
      
      // 验证结果中包含匹配的组织（不依赖排序）
      const hasChina = response.body.data.items.some((item: any) => 
        item.name.includes('China') || item.code.includes('China')
      );
      expect(hasChina).toBe(true);
    });
  });

  describe('GET /api/v1/organizations/:id - 查询组织详情', () => {
    let organizationId: string;

    beforeEach(async () => {
      // 🎯 使用 helper 创建测试组织
      const org = await createTestOrganization(app, adminToken, prisma, {
        name: 'FF China',
      });
      organizationId = org.organizationId;
    });

    it('[API-ORG-007] 应该返回组织详情', async () => {
      const response = await request(app.getHttpServer())
        .get(`/api/v1/organizations/${organizationId}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(200);

      expect(response.body.success).toBe(true);
      expect(response.body.data).toHaveProperty('id', organizationId);
      expect(response.body.data).toHaveProperty('code');
      expect(response.body.data).toHaveProperty('name');
      expect(response.body.data).toHaveProperty('status');
    });

    it('[API-ORG-008] 无效ID格式应返回400', async () => {
      // 无效的UUID格式应该返回400（Bad Request）
      const response = await request(app.getHttpServer())
        .get('/api/v1/organizations/non-existent-id')
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(400);

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

    it('[API-ORG-008-2] 有效UUID但组织不存在应返回404', async () => {
      // 有效的UUID格式但资源不存在应该返回404（Not Found）
      const validUuid = '00000000-0000-0000-0000-000000000000';
      const response = await request(app.getHttpServer())
        .get(`/api/v1/organizations/${validUuid}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(404);

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

  describe('PATCH /api/v1/organizations/:id - 更新组织', () => {
    let organizationId: string;

    beforeEach(async () => {
      // 🎯 使用 helper 创建测试组织
      const org = await createTestOrganization(app, adminToken, prisma, {
        name: 'FF China',
      });
      organizationId = org.organizationId;
    });

    it('[API-ORG-009] 应该成功更新组织信息', async () => {
      const updateDto = {
        name: 'FF China Updated',
        address: '北京市海淀区',
      };

      const response = await request(app.getHttpServer())
        .patch(`/api/v1/organizations/${organizationId}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send(updateDto)
        .expect(200);

      expect(response.body.success).toBe(true);
      expect(response.body.data.name).toBe('FF China Updated');
      expect(response.body.data.address).toBe('北京市海淀区');

      // 验证数据库更新
      const org = await prisma.organization.findUnique({
        where: { id: organizationId },
      });

      expect(org!.name).toBe('FF China Updated');
      expect(org!.address).toBe('北京市海淀区');
    });

    it('[API-ORG-010] 不能修改组织代码', async () => {
      const response = await request(app.getHttpServer())
        .patch(`/api/v1/organizations/${organizationId}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          code: 'NEW_CODE', // 尝试修改代码
        })
        .expect(400);

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

  describe('DELETE /api/v1/organizations/:id - 删除组织', () => {
    let organizationId: string;

    beforeEach(async () => {
      // 🎯 使用 helper 创建测试组织
      const org = await createTestOrganization(app, adminToken, prisma, {
        name: 'FF China',
      });
      organizationId = org.organizationId;
    });

    it('[API-ORG-011] 应该成功软删除组织（无用户时）', async () => {
      await request(app.getHttpServer())
        .delete(`/api/v1/organizations/${organizationId}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(200);

      // 验证软删除（deletedAt 不为 null）
      const org = await prisma.organization.findFirst({
        where: { id: organizationId },
      });

      expect(org).toBeDefined();
      expect(org!.deletedAt).not.toBeNull();

      // 验证根部门也被删除
      const rootDept = await prisma.department.findFirst({
        where: {
          organizationId: organizationId,
          parentId: null,
        },
      });

      expect(rootDept!.deletedAt).not.toBeNull();
    });

    it('[API-ORG-012] 有用户时不能删除组织', async () => {
      // 获取组织的根部门
      const rootDept = await prisma.department.findFirst({
        where: {
          organizationId: organizationId,
          parentId: null,
        },
      });

      // 创建用户并分配到组织的根部门
      await request(app.getHttpServer())
        .post('/api/v1/users')
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          username: 'testuser',
          email: 'test@example.com',
          password: 'Test@123',
          displayName: 'Test User',
          departmentId: rootDept!.id, // 分配到根部门
        });

      // 尝试删除（应该失败）
      const response = await request(app.getHttpServer())
        .delete(`/api/v1/organizations/${organizationId}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(400);

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

  describe('GET /api/v1/organizations/:id/stats - 组织统计', () => {
    let organizationId: string;

    beforeEach(async () => {
      // 🎯 使用 helper 创建测试组织
      const org = await createTestOrganization(app, adminToken, prisma, {
        name: 'FF China',
      });
      organizationId = org.organizationId;
    });

    it('[API-ORG-013] 应该返回组织统计信息', async () => {
      const response = await request(app.getHttpServer())
        .get(`/api/v1/organizations/${organizationId}/stats`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(200);

      expect(response.body.success).toBe(true);
      expect(response.body.data).toHaveProperty('totalDepartments');
      expect(response.body.data).toHaveProperty('totalUsers');
      expect(response.body.data).toHaveProperty('activeUsers');
      expect(response.body.data).toHaveProperty('totalRegions');

      // 新建组织应该有1个根部门，0个用户
      expect(response.body.data.totalDepartments).toBe(1);
      expect(response.body.data.totalUsers).toBe(0);
    });
  });

  describe('POST /api/v1/organizations/:id/regions - 添加区域', () => {
    let organizationId: string;
    let regionId: string;

    beforeEach(async () => {
      // 🎯 并行创建组织和区域
      const [org, regionResponse] = await Promise.all([
        createTestOrganization(app, adminToken, prisma, { name: 'FF China' }),
        request(app.getHttpServer())
          .post('/api/v1/regions')
          .set('Authorization', `Bearer ${adminToken}`)
          .send({
            code: 'CN',
            name: '中国',
            timezone: 'Asia/Shanghai',
            currency: 'CNY',
          }),
      ]);

      organizationId = org.organizationId;
      regionId = regionResponse.body.data.id;
    });

    it('[API-ORG-014] 应该成功添加区域到组织', async () => {
      const response = await request(app.getHttpServer())
        .post(`/api/v1/organizations/${organizationId}/regions`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          regionIds: [regionId],
          primaryRegionId: regionId,
        })
        .expect(200); // POST 添加关联返回 200（不是创建新资源，而是建立关联）

      expect(response.body.success).toBe(true);
      expect(response.body.data).toHaveProperty('organizationRegions');
      expect(response.body.data.organizationRegions).toHaveLength(1);
      expect(response.body.data.organizationRegions[0].regionId).toBe(regionId);

      // 验证数据库
      const orgRegion = await prisma.organizationRegion.findFirst({
        where: {
          organizationId,
          regionId,
        },
      });

      expect(orgRegion).toBeDefined();
    });
  });

  describe('完整业务流程测试', () => {
    it('[API-ORG-FLOW-001] 应该完成完整的组织创建和配置流程', async () => {
      // 1. 创建组织
      const orgResponse = await request(app.getHttpServer())
        .post('/api/v1/organizations')
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          code: 'FF_CHINA',
          name: 'FF China',
          legalName: '法拉第未来（中国）有限公司',
          taxId: '91110000MA001234XX',
        })
        .expect(201);

      const organizationId = orgResponse.body.data.id;

      // 2. 验证组织创建成功
      expect(orgResponse.body.data).toHaveProperty('id');
      expect(orgResponse.body.data.status).toBe('ACTIVE');

      // 3. 创建区域
      const regionResponse = await request(app.getHttpServer())
        .post('/api/v1/regions')
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          code: 'CN',
          name: '中国',
          timezone: 'Asia/Shanghai',
          currency: 'CNY',
        });

      const regionId = regionResponse.body.data.id;

      // 4. 添加区域到组织
      await request(app.getHttpServer())
        .post(`/api/v1/organizations/${organizationId}/regions`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send({
          regionIds: [regionId],
          primaryRegionId: regionId,
        })
        .expect(200);

      // 5. 查询组织详情，验证区域关联
      const detailResponse = await request(app.getHttpServer())
        .get(`/api/v1/organizations/${organizationId}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(200);

      expect(detailResponse.body.data.primaryRegionId).toBe(regionId);

      // 6. 查询统计信息
      const statsResponse = await request(app.getHttpServer())
        .get(`/api/v1/organizations/${organizationId}/stats`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(200);

      expect(statsResponse.body.data.totalDepartments).toBe(1); // 根部门
      expect(statsResponse.body.data.totalRegions).toBe(1);

      console.log('✅ 组织创建和配置完整流程测试通过');
    });
  });
});

