/**
 * Webhook Trigger Bridge
 *
 * Bridges email provider webhook events to the automation TriggerService.
 * When Brevo, Mailchimp, or Zoho sends a webhook event (email opened, link clicked,
 * contact subscribed, etc.), this service translates the event and fires the
 * corresponding trigger in the automation engine.
 *
 * This preserves the existing webhook handlers that update campaign stats and
 * contact status — the bridge is called AFTER those handlers complete.
 */

import { triggerService } from './TriggerService';
import { emailIntegrationService } from '../email/EmailIntegrationService';

// ============================================
// TYPE DEFINITIONS
// ============================================

interface BrevoWebhookPayload {
  event?: string;
  email?: string;
  id?: number;
  campaign_id?: number;
  message_id?: string;
  ts?: number;
  date?: string;
  subject?: string;
  tags?: string[];
  link?: string;
  sending_ip?: string;
  ts_event?: number;
  // Brevo's list id has been seen under several shapes across webhook versions.
  listId?: number;
  list_id?: number | number[];
  list_ids?: number | number[];
}

/**
 * Collect all list ids from a Brevo webhook payload regardless of the exact
 * field name/shape Brevo used (listId, list_id, or list_ids; scalar or array).
 * Returns a de-duplicated array of string ids (empty if none present).
 */
function normalizeBrevoListIds(payload: BrevoWebhookPayload): string[] {
  const collected: any[] = [];
  const add = (v: any) => {
    if (v == null) return;
    if (Array.isArray(v)) collected.push(...v);
    else collected.push(v);
  };
  add(payload.listId);
  add(payload.list_id);
  add(payload.list_ids);
  return Array.from(
    new Set(
      collected
        .map((v) => String(v))
        .filter((v) => v !== '' && v !== 'undefined' && v !== 'null')
    )
  );
}

interface MailchimpWebhookPayload {
  type?: string;
  fired_at?: string;
  data?: {
    id?: string;
    list_id?: string;
    email?: string;
    email_type?: string;
    ip_signup?: string;
    ip_opt?: string;
    reason?: string;
    campaign_id?: string;
    merge_fields?: Record<string, string>;
    old_email?: string;
    new_email?: string;
    action?: string;
    url?: string;
  };
}

interface ZohoWebhookPayload {
  event?: string;
  email?: string;
  campaign_key?: string;
  campaign_name?: string;
  list_key?: string;
  contact_key?: string;
  timestamp?: string;
  bounce_type?: 'hard' | 'soft';
  link_url?: string;
  ip_address?: string;
  user_agent?: string;
}

// ============================================
// WEBHOOK TRIGGER BRIDGE CLASS
// ============================================

export class WebhookTriggerBridge {

  /**
   * Handle Brevo webhook events and bridge to automation triggers
   */
  async handleBrevoEvent(companyId: string, payload: BrevoWebhookPayload): Promise<void> {
    if (!companyId || !payload.event || !payload.email) {
      console.log(`[WebhookTriggerBridge] handleBrevoEvent skipped: missing companyId=${companyId}, event=${payload.event}, email=${payload.email}`);
      return;
    }

    const contactData = {
      id: payload.email,
      email: payload.email,
    };

    console.log(`[WebhookTriggerBridge] Brevo event: ${payload.event}, email: ${payload.email}, listId: ${payload.listId}, companyId: ${companyId}`);

    try {
      switch (payload.event) {
        case 'listAddition':
        case 'contactAdded':
        case 'contactCreated': {
          // Contact subscribed/added to a list. Normalize the list id(s) so a
          // camelCase/snake_case or array payload isn't silently dropped.
          const listIds = normalizeBrevoListIds(payload);
          console.log(`[WebhookTriggerBridge] Calling onContactAddedToList with listIds=${JSON.stringify(listIds)}`);
          await triggerService.onContactAddedToList(companyId, contactData, listIds);
          break;
        }

        case 'uniqueOpened':
        case 'opened':
          await triggerService.onEmailOpened(companyId, contactData, {
            emailId: payload.message_id,
            campaignId: payload.campaign_id?.toString(),
          });
          break;

        case 'clicked':
          await triggerService.onEmailClicked(companyId, contactData, {
            url: payload.link,
            emailId: payload.message_id,
          });
          break;

        // Bounce, unsubscribe, spam events update contact status
        // but don't fire automation triggers — handled by existing webhook handler
        default:
          // Other Brevo events (delivered, hardBounce, softBounce, etc.)
          // are handled by the existing emailWebhooks route for stats tracking
          break;
      }
    } catch (error) {
      console.error('[WebhookTriggerBridge] Error handling Brevo event:', error);
    }
  }

  /**
   * Handle Mailchimp webhook events and bridge to automation triggers
   */
  async handleMailchimpEvent(companyId: string, payload: MailchimpWebhookPayload): Promise<void> {
    if (!companyId || !payload.type) return;

    const contactData = {
      id: payload.data?.email || '',
      email: payload.data?.email || '',
    };

    try {
      switch (payload.type) {
        case 'subscribe':
          await triggerService.onContactAddedToList(
            companyId,
            contactData,
            payload.data?.list_id || ''
          );
          break;

        case 'campaign':
          // Mailchimp campaign status events — check the action
          if (payload.data?.action === 'sent') {
            // Campaign sent notification — no trigger needed
          }
          break;

        default:
          // Other Mailchimp events (unsubscribe, profile, cleaned, upemail)
          // are handled by existing webhook handler
          break;
      }
    } catch (error) {
      console.error('[WebhookTriggerBridge] Error handling Mailchimp event:', error);
    }
  }

  /**
   * Handle Zoho Campaigns webhook events and bridge to automation triggers
   */
  async handleZohoEvent(companyId: string, payload: ZohoWebhookPayload): Promise<void> {
    if (!companyId || !payload.event || !payload.email) return;

    const contactData = {
      id: payload.email,
      email: payload.email,
    };

    try {
      switch (payload.event) {
        case 'email_open':
          await triggerService.onEmailOpened(companyId, contactData, {
            campaignId: payload.campaign_key,
          });
          break;

        case 'email_click':
          await triggerService.onEmailClicked(companyId, contactData, {
            url: payload.link_url,
          });
          break;

        default:
          // Other Zoho events (email_delivered, bounce, unsubscribed, spam)
          // are handled by existing webhook handler
          break;
      }
    } catch (error) {
      console.error('[WebhookTriggerBridge] Error handling Zoho event:', error);
    }
  }

  /**
   * Resolve companyId from provider and identifier
   * Used when companyId is not available in the webhook URL
   */
  async resolveCompanyId(provider: string, identifier: string): Promise<string | null> {
    try {
      // Look up the EmailIntegration document for this provider
      const { EmailIntegration } = await import('../../models/EmailIntegration');
      const integration = await EmailIntegration.findOne({
        provider,
        status: 'connected',
      }).lean();

      return integration?.companyId?.toString() || null;
    } catch (error) {
      console.error('[WebhookTriggerBridge] Error resolving companyId:', error);
      return null;
    }
  }
}

// Singleton export
export const webhookTriggerBridge = new WebhookTriggerBridge();