/**
 * IAM 后台 - 字段级权限 CRUD
 */
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 } from '../../helpers/test-setup.helper';

describe('IAM Admin - FieldPermissions API', () => {
  let app: INestApplication;
  let prisma: PrismaService;
  let adminToken: string;

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

  beforeEach(async () => {
    const ctx = await setupIntegrationTest(app, prisma);
    adminToken = ctx.adminToken;
  });

  afterEach(async () => {
    await cleanupDatabase(prisma);
  });

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

  async function aTestRole() {
    return prisma.role.create({
      data: {
        code: `ROLE_FP_${Date.now()}`,
        name: 'fp role',
        description: 'fp test',
        isBuiltIn: false,
        enabled: true,
      },
    });
  }

  it('[IAM-ADMIN-FP-001] POST 创建字段权限成功，落审计', async () => {
    const role = await aTestRole();
    const res = await request(app.getHttpServer())
      .post('/api/v1/iam/field-permissions')
      .set('Authorization', `Bearer ${adminToken}`)
      .send({
        roleId: role.id,
        resource: 'purchase_order',
        field: 'amount',
        access: 'DESENSITIZE',
      })
      .expect(201);

    expect(res.body.data.access).toBe('DESENSITIZE');
    const audits = await prisma.iamAuditLog.findMany({
      where: { resource: 'FieldPermission', action: 'CREATE', targetId: res.body.data.id },
    });
    expect(audits.length).toBe(1);
  });

  it('[IAM-ADMIN-FP-002] 重复 (roleId, resource, field) 被拒', async () => {
    const role = await aTestRole();
    await request(app.getHttpServer())
      .post('/api/v1/iam/field-permissions')
      .set('Authorization', `Bearer ${adminToken}`)
      .send({ roleId: role.id, resource: 'po', field: 'amount', access: 'HIDDEN' })
      .expect(201);

    await request(app.getHttpServer())
      .post('/api/v1/iam/field-permissions')
      .set('Authorization', `Bearer ${adminToken}`)
      .send({ roleId: role.id, resource: 'po', field: 'amount', access: 'VISIBLE' })
      .expect(409);
  });

  it('[IAM-ADMIN-FP-003] PATCH 改 access 成功', async () => {
    const role = await aTestRole();
    const created = await request(app.getHttpServer())
      .post('/api/v1/iam/field-permissions')
      .set('Authorization', `Bearer ${adminToken}`)
      .send({ roleId: role.id, resource: 'po', field: 'price', access: 'HIDDEN' })
      .expect(201);

    await request(app.getHttpServer())
      .patch(`/api/v1/iam/field-permissions/${created.body.data.id}`)
      .set('Authorization', `Bearer ${adminToken}`)
      .send({ access: 'READONLY' })
      .expect(200);

    const after = await prisma.fieldPermission.findUnique({
      where: { id: created.body.data.id },
    });
    expect(after?.access).toBe('READONLY');
  });

  it('[IAM-ADMIN-FP-004] DELETE 删除成功，落 DELETE 审计', async () => {
    const role = await aTestRole();
    const created = await request(app.getHttpServer())
      .post('/api/v1/iam/field-permissions')
      .set('Authorization', `Bearer ${adminToken}`)
      .send({ roleId: role.id, resource: 'po', field: 'cost', access: 'HIDDEN' })
      .expect(201);

    await request(app.getHttpServer())
      .delete(`/api/v1/iam/field-permissions/${created.body.data.id}`)
      .set('Authorization', `Bearer ${adminToken}`)
      .expect(200);

    const audits = await prisma.iamAuditLog.findMany({
      where: { resource: 'FieldPermission', action: 'DELETE', targetId: created.body.data.id },
    });
    expect(audits.length).toBe(1);
  });

  it('[IAM-ADMIN-FP-005] GET ?resource= 过滤生效', async () => {
    const role = await aTestRole();
    await request(app.getHttpServer())
      .post('/api/v1/iam/field-permissions')
      .set('Authorization', `Bearer ${adminToken}`)
      .send({ roleId: role.id, resource: 'r1', field: 'f1', access: 'HIDDEN' })
      .expect(201);
    await request(app.getHttpServer())
      .post('/api/v1/iam/field-permissions')
      .set('Authorization', `Bearer ${adminToken}`)
      .send({ roleId: role.id, resource: 'r2', field: 'f2', access: 'HIDDEN' })
      .expect(201);

    const res = await request(app.getHttpServer())
      .get('/api/v1/iam/field-permissions?resource=r1')
      .set('Authorization', `Bearer ${adminToken}`)
      .expect(200);
    expect(res.body.data.every((x: { resource: string }) => x.resource === 'r1')).toBe(true);
  });
});
