import { describe, it, expect } from 'vitest';
import {
  GupshupSmsProviderAdapter,
  KaleyraSmsProviderAdapter,
  ExotelSmsProviderAdapter,
  GupshupWhatsAppProviderAdapter,
  Dialog360WhatsAppProviderAdapter,
  TwentyFourSevenSmsProviderAdapter,
} from '@zyphon/provider-generic';
import { ZohoEmailProviderAdapter } from '@zyphon/provider-email-zoho';
import { SesProviderAdapter } from '@zyphon/provider-email-ses';

describe('Indian SMS, WhatsApp & Email Provider Contracts', () => {
  it('Gupshup Enterprise SMS sends DLT payload and parses success reference', async () => {
    let capturedBody = '';
    const fetchFn = async (_url: string, init?: RequestInit) => {
      capturedBody = String(init?.body || '');
      return new Response('success | 919876543210 | 32948239482394823-1234', { status: 200 });
    };

    const adapter = new GupshupSmsProviderAdapter({ id: 'gupshup-sms-in', fetchFn });
    const result = await adapter.send(
      {
        message_id: 'msg_gs_1',
        request_id: 'req_gs_1',
        application_id: 'app',
        channel: 'sms',
        recipient: '+919876543210',
        content: { type: 'text', body: 'Your OTP is 4821', template: '1107161234567890123' },
        metadata: {},
        created_at: Date.now(),
      },
      {
        userid: '2000192831',
        password: 'secret-gs-password',
        sender_id: 'ACMEIN',
        pe_id: '1100123456789012345',
      },
      AbortSignal.timeout(5000),
    );

    expect(result.success).toBe(true);
    expect(result.provider_reference).toBe('32948239482394823-1234');
    expect(capturedBody).toContain('principalEntityId=1100123456789012345');
    expect(capturedBody).toContain('dltTemplateId=1107161234567890123');
    expect(JSON.stringify(result)).not.toContain('secret-gs-password');
  });

  it('Kaleyra SMS sends India DLT payload with api-key header', async () => {
    let capturedHeaders: Record<string, string> = {};
    const fetchFn = async (_url: string, init: RequestInit) => {
      capturedHeaders = init.headers as Record<string, string>;
      return new Response(
        JSON.stringify({ id: 'kal_msg_991', data: [{ message_id: 'kal_msg_991' }] }),
        { status: 202 },
      );
    };

    const adapter = new KaleyraSmsProviderAdapter({ id: 'kaleyra-in', fetchFn });
    const result = await adapter.send(
      {
        message_id: 'msg_kal_1',
        request_id: 'req_kal_1',
        application_id: 'app',
        channel: 'sms',
        recipient: '+919876543210',
        content: { type: 'text', body: 'Your OTP is 4821' },
        metadata: {},
        created_at: Date.now(),
      },
      {
        sid: 'HXIN1234567890',
        api_key: 'A9f8d7s6f8d7s6f',
        sender_id: 'ACMEIN',
        pe_id: '1100123456789012345',
        template_id: '1107161234567890123',
      },
      AbortSignal.timeout(5000),
    );

    expect(result.success).toBe(true);
    expect(result.provider_reference).toBe('kal_msg_991');
    expect(capturedHeaders['api-key']).toBe('A9f8d7s6f8d7s6f');
    expect(JSON.stringify(result)).not.toContain('A9f8d7s6f8d7s6f');
  });

  it('Exotel India SMS sends DltEntityId and DltTemplateId over Basic Auth', async () => {
    let capturedBody = '';
    const fetchFn = async (_url: string, init: RequestInit) => {
      capturedBody = String(init.body || '');
      return new Response(
        JSON.stringify({ SMSMessage: { Sid: 'exo_sms_8821', Status: 'queued' } }),
        { status: 200 },
      );
    };

    const adapter = new ExotelSmsProviderAdapter({ id: 'exotel-in', fetchFn });
    const result = await adapter.send(
      {
        message_id: 'msg_exo_1',
        request_id: 'req_exo_1',
        application_id: 'app',
        channel: 'sms',
        recipient: '+919876543210',
        content: { type: 'text', body: 'Your OTP is 4821' },
        metadata: {},
        created_at: Date.now(),
      },
      {
        sid: 'acmeindia1',
        api_key: 'exo_key',
        api_token: 'exo_secret_token',
        sender_id: 'ACMEIN',
        pe_id: '1100123456789012345',
        template_id: '1107161234567890123',
      },
      AbortSignal.timeout(5000),
    );

    expect(result.success).toBe(true);
    expect(result.provider_reference).toBe('exo_sms_8821');
    expect(capturedBody).toContain('DltEntityId=1100123456789012345');
    expect(capturedBody).toContain('DltTemplateId=1107161234567890123');
    expect(JSON.stringify(result)).not.toContain('exo_secret_token');
  });

  it('Gupshup WhatsApp sends message and returns messageId', async () => {
    const fetchFn = async () =>
      new Response(
        JSON.stringify({ status: 'submitted', messageId: 'gswa_77123' }),
        { status: 202 },
      );

    const adapter = new GupshupWhatsAppProviderAdapter({ id: 'gupshup-wa', fetchFn });
    const result = await adapter.send(
      {
        message_id: 'msg_gswa_1',
        request_id: 'req_gswa_1',
        application_id: 'app',
        channel: 'whatsapp',
        recipient: '+919876543210',
        content: { type: 'text', body: 'Namaste from Zyphon' },
        metadata: {},
        created_at: Date.now(),
      },
      {
        app: 'AcmeProd',
        api_key: 'gs_wa_secret_key',
        source: '919876500000',
      },
      AbortSignal.timeout(5000),
    );

    expect(result.success).toBe(true);
    expect(result.provider_reference).toBe('gswa_77123');
    expect(JSON.stringify(result)).not.toContain('gs_wa_secret_key');
  });

  it('360dialog WhatsApp sends template or text payload with D360-API-KEY', async () => {
    let capturedPayload: Record<string, unknown> = {};
    const fetchFn = async (_url: string, init: RequestInit) => {
      capturedPayload = JSON.parse(String(init.body || '{}'));
      return new Response(
        JSON.stringify({ messages: [{ id: 'wamid.HBgMOTE5ODc2NTQzMjEwFQIAERgS' }] }),
        { status: 200 },
      );
    };

    const adapter = new Dialog360WhatsAppProviderAdapter({ id: 'd360-wa', fetchFn });
    const result = await adapter.send(
      {
        message_id: 'msg_d360_1',
        request_id: 'req_d360_1',
        application_id: 'app',
        channel: 'whatsapp',
        recipient: '+919876543210',
        content: { type: 'text', body: '4821', template: 'otp_login_hi' },
        metadata: {},
        created_at: Date.now(),
      },
      {
        api_key: 'd360_secret_api_key',
      },
      AbortSignal.timeout(5000),
    );

    expect(result.success).toBe(true);
    expect(result.provider_reference).toBe('wamid.HBgMOTE5ODc2NTQzMjEwFQIAERgS');
    expect(capturedPayload.type).toBe('template');
    expect(JSON.stringify(result)).not.toContain('d360_secret_api_key');
  });

  it('Zoho ZeptoMail (.in) sends email via api.zeptomail.zoho.in with Zoho-enczapikey', async () => {
    let capturedUrl = '';
    let capturedAuth = '';
    const fetchFn = async (url: string, init: RequestInit) => {
      capturedUrl = url;
      capturedAuth = (init.headers as Record<string, string>)['Authorization'] || '';
      return new Response(
        JSON.stringify({ request_id: 'zepto_in_req_9981', message: 'OK' }),
        { status: 201 },
      );
    };

    const adapter = new ZohoEmailProviderAdapter({ id: 'zoho-in', fetchFn });
    const result = await adapter.send(
      {
        message_id: 'msg_zoho_1',
        request_id: 'req_zoho_1',
        application_id: 'app',
        channel: 'email',
        recipient: 'customer@example.in',
        content: { type: 'html', subject: 'Invoice #104', body: '<p>Paid</p>' },
        metadata: {},
        created_at: Date.now(),
      },
      {
        token: 'wSsVR610/R7zC6p9z2asL+w7zF1UUlqgFxx0',
        from: 'no-reply@acme.in',
        region: 'zeptomail.zoho.in',
      },
      AbortSignal.timeout(5000),
    );

    expect(result.success).toBe(true);
    expect(result.provider_reference).toBe('zepto_in_req_9981');
    expect(capturedUrl).toBe('https://api.zeptomail.zoho.in/v1.1/email');
    expect(capturedAuth).toContain('Zoho-enczapikey ');
    expect(JSON.stringify(result)).not.toContain('wSsVR610');
  });

  it('Amazon SES accepts catalog keys access_key and secret with ap-south-1 default', async () => {
    let capturedUrl = '';
    const fetchFn = async (url: string) => {
      capturedUrl = url;
      return new Response(JSON.stringify({ MessageId: 'ses_mumbai_001' }), { status: 200 });
    };

    const adapter = new SesProviderAdapter({ id: 'ses-mumbai', fetchFn });
    const result = await adapter.send(
      {
        message_id: 'msg_ses_1',
        request_id: 'req_ses_1',
        application_id: 'app',
        channel: 'email',
        recipient: 'ops@acme.in',
        content: { type: 'text', subject: 'Alert', body: 'All healthy' },
        metadata: {},
        created_at: Date.now(),
      },
      {
        access_key: 'AKIAIOSFODNN7EXAMPLE',
        secret: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
        from: 'alerts@acme.in',
        region: 'ap-south-1',
      },
      AbortSignal.timeout(5000),
    );

    expect(result.success).toBe(true);
    expect(result.provider_reference).toBe('ses_mumbai_001');
    expect(capturedUrl).toContain('email.ap-south-1.amazonaws.com');
  });

  it('24x7SMS sends India DLT payload and parses message reference', async () => {
    let capturedUrl = '';
    const fetchFn = async (url: string) => {
      capturedUrl = url;
      return new Response(JSON.stringify({ status: 'success', messageId: '247_msg_883192' }), { status: 200 });
    };

    const adapter = new TwentyFourSevenSmsProviderAdapter({ id: '247sms-in', fetchFn });
    const result = await adapter.send(
      {
        message_id: 'msg_247_1',
        request_id: 'req_247_1',
        application_id: 'app',
        channel: 'sms',
        recipient: '+919876543210',
        content: { type: 'text', body: 'Your OTP is 9214', template: '1107161234567890123' },
        metadata: {},
        created_at: Date.now(),
      },
      {
        api_key: 'secret-247-api-key',
        sender_id: 'ACMEIN',
        pe_id: '1100123456789012345',
      },
      AbortSignal.timeout(5000),
    );

    expect(result.success).toBe(true);
    expect(result.provider_reference).toBe('247_msg_883192');
    expect(capturedUrl).toContain('websms.24x7sms.com');
    expect(capturedUrl).toContain('APIKEY=secret-247-api-key');
    expect(capturedUrl).toContain('SenderID=ACMEIN');
    expect(capturedUrl).toContain('PE_ID=1100123456789012345');
    expect(capturedUrl).toContain('DLTTemplateID=1107161234567890123');
    expect(capturedUrl).toContain('MobileNo=919876543210');
  });

  it('24x7SMS returns validation error when API key is missing', async () => {
    const adapter = new TwentyFourSevenSmsProviderAdapter();
    const result = await adapter.send(
      {
        message_id: 'msg_247_2',
        request_id: 'req_247_2',
        application_id: 'app',
        channel: 'sms',
        recipient: '+919876543210',
        content: { type: 'text', body: 'Hello' },
        metadata: {},
        created_at: Date.now(),
      },
      { sender_id: 'ACMEIN' },
      AbortSignal.timeout(5000),
    );

    expect(result.success).toBe(false);
    expect(result.error?.code).toBe('CREDENTIAL_ERROR');
  });
});
