/**
 * Dingtalk Quota Overview — includeAllStatuses 集成测试
 *
 * 验证 getQuotaOverview 的 status 过滤行为：
 *   - 默认 includeAllStatuses=false: items 仅含正常员工，summary.employeeCount 仅计正常
 *   - includeAllStatuses=true: items 含顾问 / 停薪留职 / 已离职，summary.employeeCount 计全部
 *   - allEmployees（下拉用）始终仅含正常员工
 *   - items[*].status 透传后端 dingtalk_employees.status；快照引用员工不存在时回退为 '未知'
 */

import { INestApplication } from '@nestjs/common';
import { PrismaService } from '@/core/database/prisma/prisma.service';
import { AnnualLeaveInsightService } from '@/modules/organization/dingtalk/annual-leave-insight.service';
import { createTestApp } from '../../helpers/app.helper';

const PREFIX = 't_quotaov_';

describe('Dingtalk QuotaOverview includeAllStatuses 集成测试', () => {
  let app: INestApplication;
  let prisma: PrismaService;
  let svc: AnnualLeaveInsightService;
  let normalId: string;
  let consultantId: string;
  let terminatedId: string;
  let orphanId: string;

  const seedSnapshot = async (userId: string, name: string) => {
    await (prisma as any).dingtalkLeaveQuotaSnapshot.create({
      data: {
        userId,
        employeeName: name,
        employeeNumber: `${name}-num`,
        leaveCode: '2025_AL',
        leaveType: '2025年年假',
        quotaCycle: '2025',
        totalDays: 10,
        usedDays: 0,
        remainingDays: 10,
        snapshotAt: new Date(),
      },
    });
  };

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

  beforeEach(async () => {
    const ts = `${Date.now()}_${Math.floor(Math.random() * 1e6)}`;
    normalId = `${PREFIX}normal_${ts}`;
    consultantId = `${PREFIX}consultant_${ts}`;
    terminatedId = `${PREFIX}terminated_${ts}`;
    orphanId = `${PREFIX}orphan_${ts}`;

    await (prisma as any).dingtalkEmployee.createMany({
      data: [
        { userId: normalId, name: 'A正常', status: '正常' },
        { userId: consultantId, name: 'B顾问', status: '顾问' },
        { userId: terminatedId, name: 'C离职', status: '已离职' },
      ],
    });

    await seedSnapshot(normalId, 'A正常');
    await seedSnapshot(consultantId, 'B顾问');
    await seedSnapshot(terminatedId, 'C离职');
    // 数据漂移：快照引用了不在 dingtalk_employees 表里的 userId
    await seedSnapshot(orphanId, 'D漂移');
  });

  afterEach(async () => {
    await (prisma as any).dingtalkLeaveQuotaSnapshot.deleteMany({
      where: { userId: { startsWith: PREFIX } },
    });
    await (prisma as any).dingtalkEmployee.deleteMany({
      where: { userId: { startsWith: PREFIX } },
    });
  });

  afterAll(async () => {
    await (prisma as any).dingtalkLeaveQuotaSnapshot.deleteMany({
      where: { userId: { startsWith: PREFIX } },
    });
    await (prisma as any).dingtalkEmployee.deleteMany({
      where: { userId: { startsWith: PREFIX } },
    });
    await app.close();
  });

  describe('[QUOTAOV-001] 默认 includeAllStatuses=false', () => {
    it('items 仅含 status=正常 员工，allEmployees 也仅含正常', async () => {
      const result = await svc.getQuotaOverview({ keyword: 'A正常' });
      const ids = result.items.map((i) => i.userId);
      expect(ids).toContain(normalId);
      expect(ids).not.toContain(consultantId);
      expect(ids).not.toContain(terminatedId);

      const allIds = (result.allEmployees || []).map((e) => e.userId);
      // allEmployees 只列正常员工
      expect(allIds).not.toContain(consultantId);
      expect(allIds).not.toContain(terminatedId);
    });

    it('items[*].status 透传员工状态', async () => {
      const result = await svc.getQuotaOverview({ keyword: 'A正常' });
      const item = result.items.find((i) => i.userId === normalId);
      expect(item?.status).toBe('正常');
    });
  });

  describe('[QUOTAOV-002] includeAllStatuses=true', () => {
    it('items 含顾问 / 离职，allEmployees 仍只含正常', async () => {
      const result = await svc.getQuotaOverview({ includeAllStatuses: true });
      const ids = result.items.map((i) => i.userId);
      expect(ids).toContain(normalId);
      expect(ids).toContain(consultantId);
      expect(ids).toContain(terminatedId);

      // 状态透传
      expect(result.items.find((i) => i.userId === consultantId)?.status).toBe('顾问');
      expect(result.items.find((i) => i.userId === terminatedId)?.status).toBe('已离职');

      // allEmployees 下拉始终仅含正常
      const allIds = (result.allEmployees || []).map((e) => e.userId);
      expect(allIds).not.toContain(consultantId);
      expect(allIds).not.toContain(terminatedId);
    });

    it('summary.employeeCount 包含全部可见员工（>= 3）', async () => {
      const result = await svc.getQuotaOverview({ includeAllStatuses: true });
      expect(result.summary.employeeCount).toBeGreaterThanOrEqual(3);
    });
  });

  describe('[QUOTAOV-003] 数据漂移 fallback', () => {
    it('快照 userId 不在员工表 → 不出现在 items（被 visibleUserIds 过滤）', async () => {
      const result = await svc.getQuotaOverview({ includeAllStatuses: true });
      const ids = result.items.map((i) => i.userId);
      expect(ids).not.toContain(orphanId);
    });
  });
});
