import { resolveRpc, PLANFI_RPC_CATALOG } from './planfi-rpc-catalog';

describe('planfi RPC catalog', () => {
  it('resolve customer.list para GET /api/clients com unwrap data', () => {
    const r = resolveRpc('customer.list', {});
    expect(r.method).toBe('GET');
    expect(r.path).toBe('/api/clients');
    expect(r.unwrap).toBe('data');
    expect(r.query).toEqual({});
  });

  it('mapeia params restantes para query string (GET)', () => {
    const r = resolveRpc('customer.list', { email: 'a@b.com', page: 2 });
    expect(r.query).toEqual({ email: 'a@b.com', page: '2' });
  });

  it('resolve segments.materialize para POST /api/atlas/jobs/materialize-segments', () => {
    const r = resolveRpc('segments.materialize', {});
    expect(r.method).toBe('POST');
    expect(r.path).toBe('/api/atlas/jobs/materialize-segments');
    expect(r.body).toEqual({});
  });

  it('resolve customers.syncUsage para POST /api/atlas/jobs/sync-usage com lote no corpo', () => {
    const r = resolveRpc('customers.syncUsage', { lote: 200 });
    expect(r.method).toBe('POST');
    expect(r.path).toBe('/api/atlas/jobs/sync-usage');
    expect(r.body).toEqual({ lote: 200 });
  });

  it('resolve customers.reconcileBilling para POST /api/atlas/jobs/reconcile-billing com lote/cursor no corpo', () => {
    const r = resolveRpc('customers.reconcileBilling', { lote: 200, cursor: 'abc' });
    expect(r.method).toBe('POST');
    expect(r.path).toBe('/api/atlas/jobs/reconcile-billing');
    expect(r.body).toEqual({ lote: 200, cursor: 'abc' });
  });

  it('resolve customers.syncPlanLimits para POST /api/atlas/jobs/sync-plan-limits', () => {
    const r = resolveRpc('customers.syncPlanLimits', {});
    expect(r.method).toBe('POST');
    expect(r.path).toBe('/api/atlas/jobs/sync-plan-limits');
    expect(r.body).toEqual({});
  });

  it('ignora params nulos/undefined na query', () => {
    const r = resolveRpc('customer.list', { email: undefined, name: null, page: 1 });
    expect(r.query).toEqual({ page: '1' });
  });

  it('lança erro claro para método desconhecido', () => {
    expect(() => resolveRpc('customer.delete', {})).toThrow(
      /método desconhecido "customer\.delete"/,
    );
  });

  it('aceita params ausentes (undefined)', () => {
    const r = resolveRpc('customer.list');
    expect(r.path).toBe('/api/clients');
    expect(r.query).toEqual({});
  });

  // Garante que o resolvedor de :param funciona, mesmo que o catálogo v1 não use.
  it('substitui :param no path e o consome dos params', () => {
    const spy = { method: 'GET' as const, path: '/api/clients/:id', unwrap: undefined };
    (PLANFI_RPC_CATALOG as Record<string, typeof spy>)['_test.byId'] = spy;
    try {
      const r = resolveRpc('_test.byId', { id: 'abc 123', extra: 'x' });
      expect(r.path).toBe('/api/clients/abc%20123');
      expect(r.query).toEqual({ extra: 'x' });
    } finally {
      delete (PLANFI_RPC_CATALOG as Record<string, unknown>)['_test.byId'];
    }
  });

  it('lança erro quando :param obrigatório está ausente', () => {
    const spy = { method: 'GET' as const, path: '/api/clients/:id' };
    (PLANFI_RPC_CATALOG as Record<string, typeof spy>)['_test.byId'] = spy;
    try {
      expect(() => resolveRpc('_test.byId', {})).toThrow(
        /parâmetro obrigatório "id" ausente/,
      );
    } finally {
      delete (PLANFI_RPC_CATALOG as Record<string, unknown>)['_test.byId'];
    }
  });
});
