import { ConfigService } from '@nestjs/config';
import { AtlasRuntimeClient } from '../atlas-runtime.client';
import { MessageProviderRegistry } from './message-providers';

describe('MessageProviderRegistry', () => {
  const atlasRuntime = {
    sendMessage: jest.fn(),
  };

  function registry(config: Record<string, unknown>) {
    return new MessageProviderRegistry(
      {
        get: jest.fn((key: string) => config[key]),
      } as unknown as ConfigService,
      atlasRuntime as unknown as AtlasRuntimeClient,
    );
  }

  beforeEach(() => {
    jest.clearAllMocks();
  });

  it('WhatsApp com dryRun:true não faz envio real mesmo com flags reais', async () => {
    const providers = registry({
      AUTOMATION_SEND_ENABLED: true,
      AUTOMATION_DRY_RUN: false,
    });

    const result = await providers
      .getProvider('WHATSAPP')
      .send({ to: '+5511999999999', body: 'Oi', dryRun: true });

    expect(result.status).toBe('dry_run');
    expect(result.rawResponse).toMatchObject({
      channel: 'WHATSAPP',
      dryRun: true,
    });
  });

  it('Email/WhatsApp/Push ficam em dry-run por padrão', async () => {
    const providers = registry({
      AUTOMATION_SEND_ENABLED: false,
      AUTOMATION_DRY_RUN: true,
    });

    await expect(
      providers
        .getProvider('EMAIL')
        .send({ to: 'ana@planfi.com.br', body: 'Oi' }),
    ).resolves.toMatchObject({ success: true, status: 'dry_run' });
    await expect(
      providers
        .getProvider('WHATSAPP')
        .send({ to: '+5511999999999', body: 'Oi' }),
    ).resolves.toMatchObject({ success: true, status: 'dry_run' });
    await expect(
      providers.getProvider('PUSH').send({ to: 'user_1', body: 'Oi' }),
    ).resolves.toMatchObject({ success: true, status: 'dry_run' });
  });

  it('sem dry-run e com envio habilitado delega e-mail para o Atlas', async () => {
    const providers = registry({
      AUTOMATION_SEND_ENABLED: 'true',
      AUTOMATION_DRY_RUN: 'false',
    });
    atlasRuntime.sendMessage.mockResolvedValue({
      success: true,
      providerMessageId: 'mail_1',
      status: 'sent',
      retryable: false,
    });

    await expect(
      providers.getProvider('EMAIL').send({
        to: 'ana@planfi.com.br',
        subject: 'Teste',
        body: 'Oi',
        dryRun: false,
      }),
    ).resolves.toMatchObject({
      success: true,
      providerMessageId: 'mail_1',
      status: 'sent',
      retryable: false,
    });
    expect(atlasRuntime.sendMessage).toHaveBeenCalledWith({
      channel: 'EMAIL',
      to: 'ana@planfi.com.br',
      subject: 'Teste',
      body: 'Oi',
      meta: undefined,
      dryRun: false,
    });
  });

  it('delega WhatsApp e Push para o Atlas quando envio real está habilitado', async () => {
    const providers = registry({
      AUTOMATION_SEND_ENABLED: true,
      AUTOMATION_DRY_RUN: false,
    });
    atlasRuntime.sendMessage.mockResolvedValue({
      success: true,
      status: 'sent',
      retryable: false,
    });

    await providers.getProvider('WHATSAPP').send({
      to: '+5511999999999',
      body: 'Oi',
      meta: { provider: 'atlas' },
      dryRun: false,
    });
    await providers.getProvider('PUSH').send({
      to: 'user_1',
      subject: 'Teste',
      body: 'Oi',
      dryRun: false,
    });

    expect(atlasRuntime.sendMessage).toHaveBeenNthCalledWith(1, {
      channel: 'WHATSAPP',
      to: '+5511999999999',
      subject: undefined,
      body: 'Oi',
      meta: { provider: 'atlas' },
      dryRun: false,
    });
    expect(atlasRuntime.sendMessage).toHaveBeenNthCalledWith(2, {
      channel: 'PUSH',
      to: 'user_1',
      subject: 'Teste',
      body: 'Oi',
      meta: undefined,
      dryRun: false,
    });
  });

  it('não chama o Atlas quando as flags globais mantêm dry-run', async () => {
    const providers = registry({
      AUTOMATION_SEND_ENABLED: true,
      AUTOMATION_DRY_RUN: true,
    });

    await expect(
      providers.getProvider('EMAIL').send({
        to: 'ana@planfi.com.br',
        subject: 'Teste',
        body: 'Oi',
        dryRun: false,
      }),
    ).resolves.toMatchObject({ success: true, status: 'dry_run' });
    expect(atlasRuntime.sendMessage).not.toHaveBeenCalled();
  });
});
