/**
 * L1 集成测试 — site-attendance v1.5 shared-checkin 剩余 6 endpoint
 *
 * 覆盖 shared-checkin.controller 中以下 endpoint：
 *   GET  /checkpoints/code/:code/qr-token               @Public
 *   GET  /checkpoints/code/:code/dispatch-options        @Public
 *   POST /internal/shared-checkin/cleanup-ticket-usage   @Public（内部 cron）
 *   GET  /checkpoints/:id/partners                       @RequirePermissions
 *   PATCH /partners/:partnerId                           @RequirePermissions
 *   DELETE /partners/:partnerId                          @RequirePermissions
 *
 * 不重复测 shared-checkin.api.test.ts 已覆盖的：
 *   POST /:id/partners (创建) / POST /dispatch / POST /validate-ticket
 *
 * 关联工单 #341 · Batch partners endpoints
 */

import { INestApplication } from '@nestjs/common';
import request from 'supertest';
import { randomBytes } from 'crypto';
import { PrismaService } from '@/core/database/prisma/prisma.service';
import { createTestApp } from '../../helpers/app.helper';
import { cleanupByPrefix } from '../../helpers/cleanup.helper';
import { createAdminUser, createTestUser } from '../../helpers/factories';
import {
  issueQrToken,
} from '@/modules/site-attendance/utils/shared-checkin.util';

const TEST_SECRET = randomBytes(32).toString('hex');
const TEST_ALLOWED_HOST = 'ff.test.example.com';

describe('Site Attendance — Partners & QR endpoints (L1)', () => {
  let app: INestApplication;
  let prisma: PrismaService;

  beforeAll(async () => {
    process.env.NODE_ENV = 'test';
    process.env.SHARED_CHECKIN_SECRET = TEST_SECRET;
    process.env.SHARED_CHECKIN_ALLOWED_HOSTS = `${TEST_ALLOWED_HOST},partner.test.example.com`;
    app = await createTestApp();
    prisma = app.get<PrismaService>(PrismaService);
    // orphan 清理
    await cleanupByPrefix(prisma, { schemas: ['platform_site_attendance', 'platform_iam'] });
  });

  afterEach(async () => {
    jest.restoreAllMocks();
    await cleanupByPrefix(prisma, { schemas: ['platform_site_attendance', 'platform_iam'] });
  });

  afterAll(async () => {
    await app.close();
  });

  // ============================================================
  // helpers
  // ============================================================

  function suffix() {
    return `t_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
  }

  async function login(username: string, password: string): Promise<string> {
    const resp = await request(app.getHttpServer())
      .post('/api/v1/auth/login')
      .send({ username, password })
      .expect(200);
    return resp.body.data.accessToken as string;
  }

  async function setupAdmin() {
    const s = suffix();
    const adminUser = await createAdminUser({
      username: s,
      email: `${s}@example.com`,
      password: 'Admin@123',
      displayName: `t_Partners Admin ${s}`,
    });
    const adminToken = await login(adminUser.username, 'Admin@123');
    return { adminUser, adminToken };
  }

  async function setupEmployee() {
    const s = suffix();
    const employee = await createTestUser({
      username: s,
      email: `${s}@example.com`,
      password: 'Emp@123',
      displayName: `t_Partners Emp ${s}`,
    });
    const empToken = await login(employee.username, 'Emp@123');
    return { employee, empToken };
  }

  /** 创建 SIGNED + sharedCheckinEnabled=true 的 checkpoint */
  async function createSharedCheckpoint(adminToken: string) {
    const name = `t_CP-${Math.random().toString(36).slice(2, 8)}`;
    const res = await request(app.getHttpServer())
      .post('/api/v1/site-attendance/checkpoints')
      .set('Authorization', `Bearer ${adminToken}`)
      .send({
        name,
        timezone: 'America/Los_Angeles',
        latitude: 34.05,
        longitude: -118.24,
        accessMode: 'SIGNED',
        qrRotationSeconds: 3600,
        qrGraceSeconds: 120,
        sharedCheckinEnabled: true,
        sharedCompanyId: 'ff',
        sharedCompanyLabel: 'Faraday Future',
      })
      .expect(201);
    return res.body.data;
  }

  /** 创建不带 sharedCheckinEnabled 的 SIGNED checkpoint（用于测边界） */
  async function createSignedOnlyCheckpoint(adminToken: string) {
    const name = `t_CP-SIGNED-${Math.random().toString(36).slice(2, 8)}`;
    const res = await request(app.getHttpServer())
      .post('/api/v1/site-attendance/checkpoints')
      .set('Authorization', `Bearer ${adminToken}`)
      .send({
        name,
        timezone: 'America/Los_Angeles',
        latitude: 34.05,
        longitude: -118.24,
        accessMode: 'SIGNED',
        qrRotationSeconds: 3600,
        qrGraceSeconds: 120,
      })
      .expect(201);
    return res.body.data;
  }

  /** 创建 PUBLIC checkpoint */
  async function createPublicCheckpoint(adminToken: string) {
    const name = `t_CP-PUB-${Math.random().toString(36).slice(2, 8)}`;
    const res = await request(app.getHttpServer())
      .post('/api/v1/site-attendance/checkpoints')
      .set('Authorization', `Bearer ${adminToken}`)
      .send({
        name,
        timezone: 'America/Los_Angeles',
        latitude: 34.05,
        longitude: -118.24,
        accessMode: 'PUBLIC',
      })
      .expect(201);
    return res.body.data;
  }

  /** 创建 partner（通过 API，复用已有 createPartner endpoint） */
  async function createPartner(
    adminToken: string,
    checkpointId: string,
    overrides: Partial<{
      companyId: string;
      companyLabel: string;
      targetUrl: string;
      isActive: boolean;
    }> = {},
  ) {
    const res = await request(app.getHttpServer())
      .post(`/api/v1/site-attendance/checkpoints/${checkpointId}/partners`)
      .set('Authorization', `Bearer ${adminToken}`)
      .send({
        companyId: `t_partner_${Math.random().toString(36).slice(2, 6)}`.replace(/[^a-z0-9_-]/g, '_'),
        companyLabel: `t_Partner Label ${Date.now()}`,
        targetUrl: `https://${TEST_ALLOWED_HOST}/siteattendance/c/PARTNER-CODE`,
        ...overrides,
      })
      .expect(201);
    return res.body.data;
  }

  // ============================================================
  // GET /checkpoints/code/:code/qr-token  (@Public)
  // ============================================================

  describe('GET /checkpoints/code/:code/qr-token', () => {
    it('[QR-1] SIGNED checkpoint → 返回 token + expiresAt + scope=checkpoint', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSignedOnlyCheckpoint(adminToken);

      const res = await request(app.getHttpServer())
        .get(`/api/v1/site-attendance/checkpoints/code/${cp.code}/qr-token`)
        .expect(200);

      expect(res.body.data.token).toBeTruthy();
      expect(res.body.data.scope).toBe('checkpoint');
      expect(res.body.data.rotationSeconds).toBe(3600);
    });

    it('[QR-2] sharedCheckinEnabled=true → scope=shared', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);

      const res = await request(app.getHttpServer())
        .get(`/api/v1/site-attendance/checkpoints/code/${cp.code}/qr-token`)
        .expect(200);

      expect(res.body.data.scope).toBe('shared');
      expect(res.body.data.token).toBeTruthy();
    });

    it('[QR-3] PUBLIC checkpoint（非 shared）→ 返回 token 为空字符串', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createPublicCheckpoint(adminToken);

      const res = await request(app.getHttpServer())
        .get(`/api/v1/site-attendance/checkpoints/code/${cp.code}/qr-token`)
        .expect(200);

      // PUBLIC 非 shared 无需 token，service 返回 token=''
      expect(res.body.data.token).toBe('');
      expect(res.body.data.expiresAt).toBeNull();
    });

    it('[QR-4] @Public — 无 Authorization 头也能访问', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSignedOnlyCheckpoint(adminToken);

      const res = await request(app.getHttpServer())
        .get(`/api/v1/site-attendance/checkpoints/code/${cp.code}/qr-token`);
        // 故意不带 Authorization

      expect(res.status).not.toBe(401);
      expect(res.status).toBe(200);
    });

    it('[QR-5] 不存在的 code → 404 CHECKPOINT_NOT_FOUND', async () => {
      const res = await request(app.getHttpServer())
        .get('/api/v1/site-attendance/checkpoints/code/non-existent-code-xyz/qr-token')
        .expect(404);

      expect(res.body.error?.code ?? res.body.code).toBe('CHECKPOINT_NOT_FOUND');
    });
  });

  // ============================================================
  // GET /checkpoints/code/:code/dispatch-options  (@Public)
  // ============================================================

  describe('GET /checkpoints/code/:code/dispatch-options', () => {
    it('[DO-1] shared checkpoint + 有效 QR token → 返回 self + partners 列表', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);
      await createPartner(adminToken, cp.id);

      const { token } = issueQrToken({
        scope: 'shared',
        checkpointCode: cp.code,
        rotationSeconds: 3600,
      });

      const res = await request(app.getHttpServer())
        .get(`/api/v1/site-attendance/checkpoints/code/${cp.code}/dispatch-options`)
        .query({ t: token })
        .expect(200);

      expect(res.body.data.self.companyId).toBe('ff');
      expect(Array.isArray(res.body.data.partners)).toBe(true);
      expect(res.body.data.partners.length).toBeGreaterThanOrEqual(1);
    });

    it('[DO-2] @Public — 无 Authorization 头也能访问', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);
      const { token } = issueQrToken({
        scope: 'shared',
        checkpointCode: cp.code,
        rotationSeconds: 3600,
      });

      const res = await request(app.getHttpServer())
        .get(`/api/v1/site-attendance/checkpoints/code/${cp.code}/dispatch-options`)
        .query({ t: token });
        // 故意不带 Authorization

      expect(res.status).not.toBe(401);
      expect(res.status).toBe(200);
    });

    it('[DO-3] sharedCheckinEnabled=false 的 checkpoint → 404 DISPATCH_NOT_ENABLED', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSignedOnlyCheckpoint(adminToken);
      const { token } = issueQrToken({
        scope: 'checkpoint',
        checkpointCode: cp.code,
        rotationSeconds: 3600,
      });

      const res = await request(app.getHttpServer())
        .get(`/api/v1/site-attendance/checkpoints/code/${cp.code}/dispatch-options`)
        .query({ t: token })
        .expect(404);

      expect(res.body.error?.code ?? res.body.code).toBe('DISPATCH_NOT_ENABLED');
    });

    it('[DO-4] QR token 签名伪造 → 401 QR_TOKEN_INVALID', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);

      // Token 格式 = `${bucket}.${HMAC_HEX}`（见 shared-checkin.util#issueQrToken）。
      // 构造"格式合法但 HMAC 不匹配"的 token —— 保留真 bucket 让 DTO/格式校验通过，
      // 把 MAC 部分换成同长度全 0 hex，service 验签必失败 → 401。
      const { token: realToken } = issueQrToken({
        scope: 'shared',
        checkpointCode: cp.code,
        rotationSeconds: 3600,
      });
      const [bucket, realMac] = realToken.split('.');
      const fakeMac = '0'.repeat(realMac.length);
      const fakeToken = `${bucket}.${fakeMac}`;

      const res = await request(app.getHttpServer())
        .get(`/api/v1/site-attendance/checkpoints/code/${cp.code}/dispatch-options`)
        .query({ t: fakeToken })
        .expect(401);

      expect(res.body.error?.code ?? res.body.code).toMatch(/QR_TOKEN_INVALID|QR_TOKEN_MALFORMED/);
    });

    it('[DO-5] 不存在的 code → 404 DISPATCH_CHECKPOINT_NOT_FOUND', async () => {
      const { token } = issueQrToken({
        scope: 'shared',
        checkpointCode: 'GHOST-CODE',
        rotationSeconds: 3600,
      });

      const res = await request(app.getHttpServer())
        .get('/api/v1/site-attendance/checkpoints/code/GHOST-CODE/dispatch-options')
        .query({ t: token })
        .expect(404);

      expect(res.body.error?.code ?? res.body.code).toBe('DISPATCH_CHECKPOINT_NOT_FOUND');
    });

    it('[DO-6] 没有 t 参数时 → 4xx（token missing 或 malformed）', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);

      const res = await request(app.getHttpServer())
        .get(`/api/v1/site-attendance/checkpoints/code/${cp.code}/dispatch-options`);
        // 故意不带 t

      expect(res.status).toBeGreaterThanOrEqual(400);
      expect(res.status).toBeLessThan(500);
    });
  });

  // ============================================================
  // POST /internal/shared-checkin/cleanup-ticket-usage  (@Public)
  // ============================================================

  describe('POST /internal/shared-checkin/cleanup-ticket-usage', () => {
    it('[CU-1] @Public — 无 Authorization 头也可调用', async () => {
      const res = await request(app.getHttpServer())
        .post('/api/v1/site-attendance/internal/shared-checkin/cleanup-ticket-usage');
        // 不带 Authorization

      expect(res.status).not.toBe(401);
      expect(res.status).toBe(201);
    });

    it('[CU-2] 真清过期 ticket：fixture 1 条已过期 → deletedCount === 1 + DB 行已删', async () => {
      // 先清干净 (防跨 suite 残留过期 ticket 影响 deletedCount 断准)
      await prisma.sharedCheckinTicketUsage.deleteMany({});

      // fixture 一条已过期 ticket（expiresAt < now）
      const expiredNonce = `t_expired_${suffix()}`;
      await prisma.sharedCheckinTicketUsage.create({
        data: {
          nonce: expiredNonce,
          expiresAt: new Date(Date.now() - 60 * 1000), // 1 分钟前过期
        },
      });

      // 再 fixture 一条未过期（确保不会被误清）
      const validNonce = `t_valid_${suffix()}`;
      await prisma.sharedCheckinTicketUsage.create({
        data: {
          nonce: validNonce,
          expiresAt: new Date(Date.now() + 60 * 60 * 1000), // 1 小时后过期
        },
      });

      const res = await request(app.getHttpServer())
        .post('/api/v1/site-attendance/internal/shared-checkin/cleanup-ticket-usage')
        .expect(201);

      const deletedCount = res.body.data?.deletedCount ?? res.body.deletedCount;
      expect(deletedCount).toBe(1);

      // DB 验证：过期那条已删，未过期那条还在
      const expired = await prisma.sharedCheckinTicketUsage.findUnique({
        where: { nonce: expiredNonce },
      });
      const valid = await prisma.sharedCheckinTicketUsage.findUnique({
        where: { nonce: validNonce },
      });
      expect(expired).toBeNull();
      expect(valid).toBeTruthy();
    });

    it('[CU-3] 连续调用两次均成功（幂等，无副作用）', async () => {
      await request(app.getHttpServer())
        .post('/api/v1/site-attendance/internal/shared-checkin/cleanup-ticket-usage')
        .expect(201);
      const res2 = await request(app.getHttpServer())
        .post('/api/v1/site-attendance/internal/shared-checkin/cleanup-ticket-usage')
        .expect(201);

      expect(res2.status).toBe(201);
    });
  });

  // ============================================================
  // GET /checkpoints/:id/partners  (@RequirePermissions)
  // ============================================================

  describe('GET /checkpoints/:id/partners', () => {
    it('[LP-1] admin 可获取 partners 列表（happy path）', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);
      await createPartner(adminToken, cp.id);
      await createPartner(adminToken, cp.id);

      const res = await request(app.getHttpServer())
        .get(`/api/v1/site-attendance/checkpoints/${cp.id}/partners`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(200);

      expect(Array.isArray(res.body.data?.partners ?? res.body.partners)).toBe(true);
      const partners = res.body.data?.partners ?? res.body.partners;
      expect(partners.length).toBeGreaterThanOrEqual(2);
    });

    it('[LP-2] 空 partner 列表时返回 [] 而非报错', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);

      const res = await request(app.getHttpServer())
        .get(`/api/v1/site-attendance/checkpoints/${cp.id}/partners`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(200);

      const partners = res.body.data?.partners ?? res.body.partners;
      expect(Array.isArray(partners)).toBe(true);
      expect(partners.length).toBe(0);
    });

    it('[LP-3] 无 Authorization 头 → 401', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);

      await request(app.getHttpServer())
        .get(`/api/v1/site-attendance/checkpoints/${cp.id}/partners`)
        // 故意不带 token
        .expect(401);
    });

    it('[LP-4] 普通员工 token（无权限）→ 403', async () => {
      const { adminToken } = await setupAdmin();
      const { empToken } = await setupEmployee();
      const cp = await createSharedCheckpoint(adminToken);

      await request(app.getHttpServer())
        .get(`/api/v1/site-attendance/checkpoints/${cp.id}/partners`)
        .set('Authorization', `Bearer ${empToken}`)
        .expect(403);
    });

    it('[LP-5] checkpoint 不存在 → 404 CHECKPOINT_NOT_FOUND', async () => {
      const { adminToken } = await setupAdmin();

      const res = await request(app.getHttpServer())
        .get('/api/v1/site-attendance/checkpoints/non-existent-cp-id-xyz/partners')
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(404);

      expect(res.body.error?.code ?? res.body.code).toBe('CHECKPOINT_NOT_FOUND');
    });
  });

  // ============================================================
  // PATCH /partners/:partnerId  (@RequirePermissions)
  // ============================================================

  describe('PATCH /partners/:partnerId', () => {
    it('[UP-1] admin 更新 companyLabel → 200 + 数据持久化', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);
      const partner = await createPartner(adminToken, cp.id);

      const newLabel = `t_Updated Label ${Date.now()}`;
      const res = await request(app.getHttpServer())
        .patch(`/api/v1/site-attendance/partners/${partner.id}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send({ companyLabel: newLabel })
        .expect(200);

      const updated = res.body.data ?? res.body;
      expect(updated.companyLabel).toBe(newLabel);
    });

    it('[UP-2] 更新 isActive=false → 停用 partner', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);
      const partner = await createPartner(adminToken, cp.id);

      const res = await request(app.getHttpServer())
        .patch(`/api/v1/site-attendance/partners/${partner.id}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send({ isActive: false })
        .expect(200);

      const updated = res.body.data ?? res.body;
      expect(updated.isActive).toBe(false);
    });

    it('[UP-3] 更新 sortOrder → 200', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);
      const partner = await createPartner(adminToken, cp.id);

      const res = await request(app.getHttpServer())
        .patch(`/api/v1/site-attendance/partners/${partner.id}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send({ sortOrder: 99 })
        .expect(200);

      const updated = res.body.data ?? res.body;
      expect(updated.sortOrder).toBe(99);
    });

    it('[UP-4] targetUrl 改为不在白名单的 hostname → 400 PARTNER_TARGETURL_HOST_NOT_ALLOWED', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);
      const partner = await createPartner(adminToken, cp.id);

      const res = await request(app.getHttpServer())
        .patch(`/api/v1/site-attendance/partners/${partner.id}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send({ targetUrl: 'https://evil.attacker.example/siteattendance' })
        .expect(400);

      expect(res.body.error?.code ?? res.body.code).toBe('PARTNER_TARGETURL_HOST_NOT_ALLOWED');
    });

    it('[UP-5] companyId 包含非法字符（大写）→ 400（NestJS ValidationPipe 拦截）', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);
      const partner = await createPartner(adminToken, cp.id);

      const res = await request(app.getHttpServer())
        .patch(`/api/v1/site-attendance/partners/${partner.id}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .send({ companyId: 'INVALID_UPPER' })
        .expect(400);

      // NestJS 全局 ValidationPipe 在 DTO 层拦截非法格式 → VALIDATION_ERROR
      // （service-level PARTNER_COMPANYID_INVALID 在 DTO 后才会触发，本 case 走不到）
      expect(res.body.error?.code ?? res.body.code).toBe('VALIDATION_ERROR');
    });

    it('[UP-6] 不存在的 partnerId → 404 PARTNER_NOT_FOUND', async () => {
      const { adminToken } = await setupAdmin();

      const res = await request(app.getHttpServer())
        .patch('/api/v1/site-attendance/partners/non-existent-partner-xyz')
        .set('Authorization', `Bearer ${adminToken}`)
        .send({ companyLabel: 't_New Label' })
        .expect(404);

      expect(res.body.error?.code ?? res.body.code).toBe('PARTNER_NOT_FOUND');
    });

    it('[UP-7] 无 Authorization 头 → 401', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);
      const partner = await createPartner(adminToken, cp.id);

      await request(app.getHttpServer())
        .patch(`/api/v1/site-attendance/partners/${partner.id}`)
        .send({ companyLabel: 't_New Label' })
        .expect(401);
    });

    it('[UP-8] 普通员工 token → 403', async () => {
      const { adminToken } = await setupAdmin();
      const { empToken } = await setupEmployee();
      const cp = await createSharedCheckpoint(adminToken);
      const partner = await createPartner(adminToken, cp.id);

      await request(app.getHttpServer())
        .patch(`/api/v1/site-attendance/partners/${partner.id}`)
        .set('Authorization', `Bearer ${empToken}`)
        .send({ companyLabel: 't_New Label' })
        .expect(403);
    });
  });

  // ============================================================
  // DELETE /partners/:partnerId  (@RequirePermissions)
  // ============================================================

  describe('DELETE /partners/:partnerId', () => {
    it('[DP-1] admin 删除 partner → 200 + 后续 GET 列表中消失', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);
      const partner = await createPartner(adminToken, cp.id);

      // NestJS DELETE 默认返 200（controller 无 @HttpCode(204)，
      // `return;` 只表示无 body，状态码取默认值）。
      await request(app.getHttpServer())
        .delete(`/api/v1/site-attendance/partners/${partner.id}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(200);

      // 确认列表里不再有该 partner
      const listRes = await request(app.getHttpServer())
        .get(`/api/v1/site-attendance/checkpoints/${cp.id}/partners`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(200);

      const partners = listRes.body.data?.partners ?? listRes.body.partners;
      const found = partners.find((p: any) => p.id === partner.id);
      expect(found).toBeUndefined();
    });

    it('[DP-2] 不存在的 partnerId → 404 PARTNER_NOT_FOUND', async () => {
      const { adminToken } = await setupAdmin();

      const res = await request(app.getHttpServer())
        .delete('/api/v1/site-attendance/partners/non-existent-partner-xyz')
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(404);

      expect(res.body.error?.code ?? res.body.code).toBe('PARTNER_NOT_FOUND');
    });

    it('[DP-3] 无 Authorization 头 → 401', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);
      const partner = await createPartner(adminToken, cp.id);

      await request(app.getHttpServer())
        .delete(`/api/v1/site-attendance/partners/${partner.id}`)
        .expect(401);
    });

    it('[DP-4] 普通员工 token → 403', async () => {
      const { adminToken } = await setupAdmin();
      const { empToken } = await setupEmployee();
      const cp = await createSharedCheckpoint(adminToken);
      const partner = await createPartner(adminToken, cp.id);

      await request(app.getHttpServer())
        .delete(`/api/v1/site-attendance/partners/${partner.id}`)
        .set('Authorization', `Bearer ${empToken}`)
        .expect(403);
    });

    it('[DP-5] 同一 partner 连续删除两次 → 第二次 404', async () => {
      const { adminToken } = await setupAdmin();
      const cp = await createSharedCheckpoint(adminToken);
      const partner = await createPartner(adminToken, cp.id);

      // 第一次删除
      await request(app.getHttpServer())
        .delete(`/api/v1/site-attendance/partners/${partner.id}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect([200, 204]);

      // 第二次应该 404
      const res2 = await request(app.getHttpServer())
        .delete(`/api/v1/site-attendance/partners/${partner.id}`)
        .set('Authorization', `Bearer ${adminToken}`)
        .expect(404);

      expect(res2.body.error?.code ?? res2.body.code).toBe('PARTNER_NOT_FOUND');
    });
  });
});
