import {
  applicationDefault,
  cert,
  getApps,
  initializeApp,
} from 'firebase-admin/app';
import { getMessaging } from 'firebase-admin/messaging';
import { FirebasePushGateway } from './firebase-push.gateway';

jest.mock('firebase-admin/app', () => ({
  applicationDefault: jest.fn(() => 'default-credential'),
  cert: jest.fn(() => 'inline-credential'),
  getApps: jest.fn(() => []),
  initializeApp: jest.fn(() => ({ name: 'mis-mobile' })),
}));
jest.mock('firebase-admin/messaging', () => ({
  getMessaging: jest.fn(() => ({ send: jest.fn().mockResolvedValue('sent') })),
}));

describe('Firebase credentials configuration', () => {
  const original = process.env.FIREBASE_SERVICE_ACCOUNT_JSON;
  beforeEach(() => {
    jest.clearAllMocks();
    delete process.env.FIREBASE_SERVICE_ACCOUNT_JSON;
  });
  afterAll(() => {
    if (original === undefined)
      delete process.env.FIREBASE_SERVICE_ACCOUNT_JSON;
    else process.env.FIREBASE_SERVICE_ACCOUNT_JSON = original;
  });

  it('uses inline JSON and preserves escaped private-key newlines', async () => {
    const account = {
      project_id: 'test',
      client_email: 'test@example.com',
      private_key: 'line1\nline2\n',
    };
    process.env.FIREBASE_SERVICE_ACCOUNT_JSON = JSON.stringify(account);
    await new FirebasePushGateway().send('test-token', 1, 7);
    expect(cert).toHaveBeenCalledWith(account);
    expect(applicationDefault).not.toHaveBeenCalled();
    expect(initializeApp).toHaveBeenCalledWith(
      expect.objectContaining({ credential: 'inline-credential' }),
      'mis-mobile',
    );
  });

  it('keeps application-default credentials available when inline JSON is absent', async () => {
    await new FirebasePushGateway().send('test-token', 1, 7);
    expect(applicationDefault).toHaveBeenCalled();
    expect(cert).not.toHaveBeenCalled();
  });

  it('rejects malformed JSON without exposing its contents', async () => {
    process.env.FIREBASE_SERVICE_ACCOUNT_JSON = 'private-secret-malformed-json';
    await expect(
      new FirebasePushGateway().send('test-token', 1, 7),
    ).rejects.toThrow('Invalid FIREBASE_SERVICE_ACCOUNT_JSON configuration.');
    expect(getMessaging).not.toHaveBeenCalled();
    expect(getApps).toHaveBeenCalled();
  });
});
