import request from 'supertest';
import { Role } from '../../../src/generated/prisma/enums.js';
import {
  closeE2EContext,
  createE2EContext,
  type E2EContext,
} from '../helpers/e2e-context.helper.js';
import {
  expectSuccessEnvelope,
  uniqueSeedValue,
} from '../helpers/e2e-http.helper.js';
import { assertRoleMatrix } from '../helpers/e2e-matrix.helper.js';

describe('BDictionariesController (e2e)', () => {
  let ctx: E2EContext;

  beforeAll(async () => {
    ctx = await createE2EContext();
  });

  afterAll(async () => {
    await closeE2EContext(ctx);
  });

  describe('GET /b/dictionaries', () => {
    it('成功：DOCTOR 可查询启用中的系统字典', async () => {
      const response = await request(ctx.app.getHttpServer())
        .get('/b/dictionaries')
        .query({ type: 'PRIMARY_DISEASE' })
        .set('Authorization', `Bearer ${ctx.tokens[Role.DOCTOR]}`);

      expectSuccessEnvelope(response, 200);
      expect(
        (response.body.data as Array<{ label: string; enabled: boolean }>).some(
          (item) => item.label === '先天性脑积水' && item.enabled === true,
        ),
      ).toBe(true);
    });
  });

  describe('字典维护流程', () => {
    it('成功：SYSTEM_ADMIN 可新增、更新、删除字典项，非管理员读取不到停用项', async () => {
      const createLabel = uniqueSeedValue('字典项');
      const updateLabel = `${createLabel}-启用`;

      const createResponse = await request(ctx.app.getHttpServer())
        .post('/b/dictionaries')
        .set('Authorization', `Bearer ${ctx.tokens[Role.SYSTEM_ADMIN]}`)
        .send({
          type: 'SHUNT_MODE',
          label: createLabel,
          sortOrder: 999,
          enabled: false,
        });

      expectSuccessEnvelope(createResponse, 201);
      const createdId = createResponse.body.data.id as number;

      const doctorReadResponse = await request(ctx.app.getHttpServer())
        .get('/b/dictionaries')
        .query({ type: 'SHUNT_MODE' })
        .set('Authorization', `Bearer ${ctx.tokens[Role.DOCTOR]}`);

      expectSuccessEnvelope(doctorReadResponse, 200);
      expect(
        (doctorReadResponse.body.data as Array<{ label: string }>).some(
          (item) => item.label === createLabel,
        ),
      ).toBe(false);

      const adminReadResponse = await request(ctx.app.getHttpServer())
        .get('/b/dictionaries')
        .query({ type: 'SHUNT_MODE', includeDisabled: true })
        .set('Authorization', `Bearer ${ctx.tokens[Role.SYSTEM_ADMIN]}`);

      expectSuccessEnvelope(adminReadResponse, 200);
      expect(
        (adminReadResponse.body.data as Array<{ label: string }>).some(
          (item) => item.label === createLabel,
        ),
      ).toBe(true);

      const updateResponse = await request(ctx.app.getHttpServer())
        .patch(`/b/dictionaries/${createdId}`)
        .set('Authorization', `Bearer ${ctx.tokens[Role.SYSTEM_ADMIN]}`)
        .send({
          label: updateLabel,
          enabled: true,
        });

      expectSuccessEnvelope(updateResponse, 200);
      expect(updateResponse.body.data.label).toBe(updateLabel);
      expect(updateResponse.body.data.enabled).toBe(true);

      const deleteResponse = await request(ctx.app.getHttpServer())
        .delete(`/b/dictionaries/${createdId}`)
        .set('Authorization', `Bearer ${ctx.tokens[Role.SYSTEM_ADMIN]}`);

      expectSuccessEnvelope(deleteResponse, 200);
      expect(deleteResponse.body.data.id).toBe(createdId);
    });

    it('角色矩阵：仅 SYSTEM_ADMIN 可维护字典，其他角色 403，未登录 401', async () => {
      await assertRoleMatrix({
        name: 'POST /b/dictionaries role matrix',
        tokens: ctx.tokens,
        expectedStatusByRole: {
          [Role.SYSTEM_ADMIN]: 201,
          [Role.HOSPITAL_ADMIN]: 403,
          [Role.DIRECTOR]: 403,
          [Role.LEADER]: 403,
          [Role.DOCTOR]: 403,
          [Role.ENGINEER]: 403,
        },
        sendAsRole: async (_role, token) =>
          request(ctx.app.getHttpServer())
            .post('/b/dictionaries')
            .set('Authorization', `Bearer ${token}`)
            .send({
              type: 'DISTAL_SHUNT_DIRECTION',
              label: uniqueSeedValue('矩阵字典项'),
            }),
        sendWithoutToken: async () =>
          request(ctx.app.getHttpServer())
            .post('/b/dictionaries')
            .send({
              type: 'DISTAL_SHUNT_DIRECTION',
              label: uniqueSeedValue('匿名字典项'),
            }),
      });
    });
  });
});
