/**
 * Platform Master L1b — 字典 / 参考数据 API 集成测试 (PR1)
 *
 * 验证：
 * - currencies / countries / geo-regions / units-of-measure / dictionaries 5 个字典 seed 数据正确
 * - GET API 返回符合预期（响应被 TransformInterceptor 包成 { code, data, message }，读 res.body.data）
 * - dictionary 按 category 过滤工作
 *
 * 参考 docs/modules/robot-manager/business-analysis/重构方案.md §3.7
 */
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 } from '../../helpers/test-setup.helper';

describe('Platform Master L1b API (PR1)', () => {
  let app: INestApplication;
  let prisma: PrismaService;
  let adminToken: string;

  const authGet = (path: string) =>
    request(app.getHttpServer()).get(path).set('Authorization', `Bearer ${adminToken}`);

  beforeAll(async () => {
    app = await createTestApp();
    prisma = app.get<PrismaService>(PrismaService);
    const ctx = await setupIntegrationTest(app, prisma);
    adminToken = ctx.adminToken;
  });

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

  describe('GET /api/v1/platform-master/currencies', () => {
    it('返回 4 种已 seed 的货币', async () => {
      const res = await authGet('/api/v1/platform-master/currencies').expect(200);
      expect(res.body.data).toBeInstanceOf(Array);
      const codes = res.body.data.map((c: { code: string }) => c.code);
      expect(codes).toEqual(expect.arrayContaining(['USD', 'CNY', 'EUR', 'AED']));
    });

    it('每个货币含 decimals/symbol', async () => {
      const res = await authGet('/api/v1/platform-master/currencies/USD').expect(200);
      expect(res.body.data).toMatchObject({
        code: 'USD',
        name: expect.any(String),
        decimals: 2,
        symbol: '$',
        enabled: true,
      });
    });
  });

  describe('GET /api/v1/platform-master/countries', () => {
    it('返回 5 个 seed 国家', async () => {
      const res = await authGet('/api/v1/platform-master/countries').expect(200);
      const codes = res.body.data.map((c: { code: string }) => c.code);
      expect(codes).toEqual(expect.arrayContaining(['CN', 'US', 'AE', 'DE', 'GB']));
    });

    it('region=APAC 只返回 CN', async () => {
      const res = await authGet('/api/v1/platform-master/countries?region=APAC').expect(200);
      const codes = res.body.data.map((c: { code: string }) => c.code);
      expect(codes).toEqual(['CN']);
    });
  });

  describe('GET /api/v1/platform-master/geo-regions', () => {
    it('返回 4 个 region', async () => {
      const res = await authGet('/api/v1/platform-master/geo-regions').expect(200);
      const codes = res.body.data.map((r: { code: string }) => r.code);
      expect(codes).toEqual(expect.arrayContaining(['APAC', 'NA', 'MEA', 'EU']));
    });
  });

  describe('GET /api/v1/platform-master/units-of-measure', () => {
    it('返回 4 个 UoM', async () => {
      const res = await authGet('/api/v1/platform-master/units-of-measure').expect(200);
      const codes = res.body.data.map((u: { code: string }) => u.code);
      expect(codes).toEqual(expect.arrayContaining(['PCS', 'KG', 'L', 'M']));
    });

    it('按 category 过滤', async () => {
      const res = await authGet('/api/v1/platform-master/units-of-measure?category=weight').expect(200);
      const codes = res.body.data.map((u: { code: string }) => u.code);
      expect(codes).toEqual(['KG']);
    });
  });

  describe('GET /api/v1/platform-master/dictionaries', () => {
    it('category=label_type 返回 7 个质量标签类型', async () => {
      const res = await authGet('/api/v1/platform-master/dictionaries?category=label_type').expect(200);
      expect(res.body.data).toHaveLength(7);
      const codes = res.body.data.map((d: { code: string }) => d.code);
      expect(codes).toEqual(
        expect.arrayContaining([
          'BODY_FCC',
          'BODY_MADE_IN_CN',
          'BODY_SN',
          'REMOTE_SN',
          'BATTERY_SN',
          'INSPECTION_SHEET',
          'SHIPPING_BOX',
        ]),
      );
    });

    it('category=tariff_type 返回 3 个关税类型', async () => {
      const res = await authGet('/api/v1/platform-master/dictionaries?category=tariff_type').expect(200);
      expect(res.body.data).toHaveLength(3);
    });

    it('category=service_issue_type 返回 5 个（含 v5 实际 issue tag）', async () => {
      const res = await authGet('/api/v1/platform-master/dictionaries?category=service_issue_type').expect(200);
      expect(res.body.data).toHaveLength(5);
      const codes = res.body.data.map((d: { code: string }) => d.code);
      expect(codes).toEqual(
        expect.arrayContaining(['WATER_DAMAGE', 'FRONT_DAMAGE', 'DISSEMBLED', 'BATTERY_ISSUE', 'OTHER']),
      );
    });

    it('没传 category 抛 400 BadRequest', async () => {
      await authGet('/api/v1/platform-master/dictionaries').expect(400);
    });

    it('label_zh 中文字段存在', async () => {
      const res = await authGet('/api/v1/platform-master/dictionaries/label_type/BODY_FCC').expect(200);
      expect(res.body.data).toMatchObject({
        category: 'label_type',
        code: 'BODY_FCC',
        labelEn: 'Body FCC Label',
        labelZh: '机身 FCC 标',
        enabled: true,
      });
    });
  });

  describe('GET /api/v1/platform-master/dictionaries/categories', () => {
    it('返回所有 category 列表', async () => {
      const res = await authGet('/api/v1/platform-master/dictionaries/categories').expect(200);
      expect(res.body.data).toEqual(
        expect.arrayContaining([
          'label_type',
          'tariff_type',
          'declaration_type',
          'service_issue_type',
          'industry',
        ]),
      );
    });
  });

  describe('L1c 数据质量校验', () => {
    it('所有 dictionary 行 labelEn 非空', async () => {
      const all = await prisma.dictionary.findMany({ where: { enabled: true } });
      const missing = all.filter((d) => !d.labelEn || !d.labelEn.trim());
      expect(missing).toEqual([]);
    });

    it('所有 dictionary 行 category 合法（白名单内）', async () => {
      const validCategories = new Set([
        'label_type',
        'tariff_type',
        'declaration_type',
        'service_issue_type',
        'industry',
      ]);
      const all = await prisma.dictionary.findMany({ where: { enabled: true } });
      const invalid = all.filter((d) => !validCategories.has(d.category));
      expect(invalid).toEqual([]);
    });

    it('所有 currency 行 decimals ≥ 0 且 code 3 位', async () => {
      const all = await prisma.currency.findMany();
      const invalid = all.filter((c) => c.decimals < 0 || c.code.length !== 3);
      expect(invalid).toEqual([]);
    });

    it('所有 country 行 iso3 正好 3 位', async () => {
      const all = await prisma.country.findMany();
      const invalid = all.filter((c) => c.iso3.length !== 3);
      expect(invalid).toEqual([]);
    });
  });

  describe('v3 — RobotLifecycleStage enum 28 个值', () => {
    it('v2 旧值（ORDERED/IN_STOCK 等）已彻底移除', async () => {
      const enumValues: { enumlabel: string }[] = await prisma.$queryRawUnsafe(
        `SELECT enumlabel FROM pg_enum WHERE enumtypid = (SELECT oid FROM pg_type WHERE typname = 'RobotLifecycleStage')`,
      );
      const labels = enumValues.map((r) => r.enumlabel);
      expect(labels).not.toEqual(
        expect.arrayContaining(['ORDERED', 'IN_TRANSIT', 'BONDED', 'IN_STOCK', 'SOLD']),
      );
      expect(labels).toEqual(
        expect.arrayContaining([
          'SUPPLY_PO_CREATED',
          'WAREHOUSE_BRANDED_READY',
          'SALES_RESERVED',
          'DELIVERY_DELIVERED',
          'AFTERSALES_UNDER_REPAIR',
          'CLOSED',
        ]),
      );
    });
  });
});
