/**
 * WhatsApp Business Service
 *
 * Handles WhatsApp Business Cloud API integration:
 * - Send messages via Meta Cloud API
 * - Verify webhook signatures
 * - Process incoming messages
 * - Manage connection state
 *
 * Security: Uses HMAC-SHA256 for webhook verification
 * Encryption: Stores access tokens with AES-256-GCM
 */

import { prisma } from '@/lib/db';
import { encrypt, decrypt } from '@/lib/encryption';
import { logger } from '@/lib/logger';
import { userApiCredentialsAdapter } from '@/lib/adapters/workflows';
import { apiKeyManagementService } from './api-key-management.service';
import { systemSettingsService } from './system-settings.service';
import crypto from 'crypto';

export interface WhatsAppMessage {
  to: string;
  type: 'text' | 'template' | 'interactive';
  text?: {
    body: string;
    preview_url?: boolean;
  };
  template?: {
    name: string;
    language: {
      code: string;
    };
    components?: Array<{
      type: string;
      parameters: Array<{
        type: string;
        text: string;
      }>;
    }>;
  };
}

export interface WhatsAppWebhookPayload {
  object: string;
  entry: Array<{
    id: string;
    changes: Array<{
      value: {
        messaging_product: string;
        metadata: {
          display_phone_number: string;
          phone_number_id: string;
        };
        contacts?: Array<{
          profile: {
            name: string;
          };
          wa_id: string;
        }>;
        messages?: Array<{
          from: string;
          id: string;
          timestamp: string;
          type: string;
          text?: {
            body: string;
          };
          interactive?: {
            type: string;
            button_reply?: {
              id: string;
              title: string;
            };
          };
        }>;
        statuses?: Array<{
          id: string;
          status: string;
          timestamp: string;
          recipient_id: string;
        }>;
      };
      field: string;
    }>;
  }>;
}

export interface SendMessageResponse {
  success: boolean;
  messageId?: string;
  error?: string;
}

export interface WebhookVerificationResult {
  isValid: boolean;
  challenge?: string;
  error?: string;
}

export class WhatsAppService {
  private readonly META_API_VERSION = 'v21.0';
  private readonly META_API_BASE = `https://graph.facebook.com/${this.META_API_VERSION}`;

  /**
   * Send a text message via WhatsApp Business API
   */
  async sendMessage(
    userId: string,
    to: string,
    message: string
  ): Promise<SendMessageResponse> {
    try {
      // Get WhatsApp credentials
      const credentials = await this.getWhatsAppCredentials(userId);
      if (!credentials) {
        logger.warn('WhatsApp credentials not found', { userId });
        return {
          success: false,
          error: 'WhatsApp not connected. Please connect your WhatsApp Business account.',
        };
      }

      const { phoneNumberId, accessToken } = credentials;

      // Prepare message payload
      const payload: WhatsAppMessage = {
        to: to.replace(/[^0-9]/g, ''), // Remove non-numeric characters
        type: 'text',
        text: {
          body: message,
          preview_url: true,
        },
      };

      // Send via Meta API
      const response = await fetch(
        `${this.META_API_BASE}/${phoneNumberId}/messages`,
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${accessToken}`,
          },
          body: JSON.stringify(payload),
        }
      );

      const data = await response.json();

      if (!response.ok) {
        logger.error('WhatsApp send message failed', {
          userId,
          status: response.status,
          error: data,
        });
        return {
          success: false,
          error: data.error?.message || 'Failed to send message',
        };
      }

      logger.info('WhatsApp message sent successfully', {
        userId,
        messageId: data.messages?.[0]?.id,
      });

      return {
        success: true,
        messageId: data.messages?.[0]?.id,
      };
    } catch (error) {
      logger.error('WhatsApp send message error', error);
      return {
        success: false,
        error: 'Internal error sending message',
      };
    }
  }

  /**
   * Verify webhook request from Meta
   * Used for initial webhook setup
   */
  verifyWebhook(
    mode: string,
    token: string,
    challenge: string
  ): WebhookVerificationResult {
    const verifyToken = process.env.WHATSAPP_VERIFY_TOKEN;

    if (!verifyToken) {
      logger.error('WHATSAPP_VERIFY_TOKEN not configured');
      return {
        isValid: false,
        error: 'Webhook verification not configured',
      };
    }

    if (mode === 'subscribe' && token === verifyToken) {
      logger.info('WhatsApp webhook verified successfully');
      return {
        isValid: true,
        challenge,
      };
    }

    logger.warn('WhatsApp webhook verification failed', {
      mode,
      tokenMatch: token === verifyToken,
    });

    return {
      isValid: false,
      error: 'Invalid verification token',
    };
  }

  /**
   * Verify webhook signature using HMAC-SHA256
   * Ensures payload authenticity from Meta
   */
  verifyWebhookSignature(
    payload: string,
    signature: string | null
  ): boolean {
    if (!signature) {
      logger.warn('WhatsApp webhook signature missing');
      return false;
    }

    const appSecret = process.env.WHATSAPP_APP_SECRET;
    if (!appSecret) {
      logger.error('WHATSAPP_APP_SECRET not configured');
      return false;
    }

    try {
      // Meta sends signature as sha256=<hash>
      const signatureHash = signature.split('sha256=')[1];
      if (!signatureHash) {
        logger.warn('Invalid signature format');
        return false;
      }

      // Calculate expected signature
      const expectedHash = crypto
        .createHmac('sha256', appSecret)
        .update(payload)
        .digest('hex');

      // Constant-time comparison to prevent timing attacks
      const isValid = crypto.timingSafeEqual(
        Buffer.from(signatureHash),
        Buffer.from(expectedHash)
      );

      if (!isValid) {
        logger.warn('WhatsApp webhook signature verification failed');
      }

      return isValid;
    } catch (error) {
      logger.error('Error verifying webhook signature', error);
      return false;
    }
  }

  /**
   * Process incoming WhatsApp message
   * Extracts message data and forwards to N8N
   */
  async processIncomingMessage(
    payload: WhatsAppWebhookPayload
  ): Promise<{ success: boolean; error?: string }> {
    try {
      // Validate payload structure
      if (!payload.entry || payload.entry.length === 0) {
        return { success: false, error: 'Invalid payload structure' };
      }

      for (const entry of payload.entry) {
        for (const change of entry.changes) {
          // Only process messages (not status updates)
          if (change.field !== 'messages') {
            continue;
          }

          const { value } = change;

          // Process incoming messages
          if (value.messages && value.messages.length > 0) {
            for (const message of value.messages) {
              await this.forwardMessageToN8N(message, value);
            }
          }

          // Log status updates but don't process
          if (value.statuses && value.statuses.length > 0) {
            logger.debug('WhatsApp message status update received', {
              statuses: value.statuses,
            });
          }
        }
      }

      return { success: true };
    } catch (error) {
      logger.error('Error processing WhatsApp message', error);
      return { success: false, error: 'Failed to process message' };
    }
  }

  /**
   * Forward incoming message to N8N webhook
   */
  private async forwardMessageToN8N(
    message: WhatsAppWebhookPayload['entry'][0]['changes'][0]['value']['messages'][0],
    metadata: WhatsAppWebhookPayload['entry'][0]['changes'][0]['value']
  ): Promise<void> {
    try {
      const n8nWebhookUrl = process.env.N8N_WEBHOOK_URL;

      if (!n8nWebhookUrl) {
        logger.warn('N8N_WEBHOOK_URL not configured - skipping message forward');
        return;
      }

      // Get auth token from database or env fallback
      const n8nAuthToken = await systemSettingsService.getN8NWebhookToken();

      // Extract message content
      let messageText = '';
      if (message.type === 'text' && message.text) {
        messageText = message.text.body;
      } else if (message.type === 'interactive' && message.interactive) {
        messageText =
          message.interactive.button_reply?.title ||
          `Interactive: ${message.interactive.type}`;
      } else {
        messageText = `Unsupported message type: ${message.type}`;
      }

      // Find user by WhatsApp phone number
      const user = await prisma.users.findFirst({
        where: {
          whatsappNumber: metadata.metadata.phone_number_id,
          whatsappConnected: true,
          isActive: true,
        },
        select: {
          id: true,
          name: true,
          email: true,
        },
      });

      if (!user) {
        logger.warn('User not found for WhatsApp number', {
          phoneNumberId: metadata.metadata.phone_number_id,
        });
        return;
      }

      // Forward to N8N
      const n8nPayload = {
        platform: 'whatsapp',
        user_id: user.id,
        customer_phone: message.from,
        customer_name: metadata.contacts?.[0]?.profile?.name || 'Unknown',
        message: {
          id: message.id,
          timestamp: message.timestamp,
          type: message.type,
          text: messageText,
        },
        metadata: {
          phone_number_id: metadata.metadata.phone_number_id,
          display_phone_number: metadata.metadata.display_phone_number,
        },
      };

      const response = await fetch(n8nWebhookUrl, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          ...(n8nAuthToken && { Authorization: `Bearer ${n8nAuthToken}` }),
        },
        body: JSON.stringify(n8nPayload),
      });

      if (!response.ok) {
        logger.error('Failed to forward message to N8N', {
          status: response.status,
          userId: user.id,
        });
      } else {
        logger.info('WhatsApp message forwarded to N8N', {
          userId: user.id,
          messageId: message.id,
        });
      }
    } catch (error) {
      logger.error('Error forwarding message to N8N', error);
    }
  }

  /**
   * Get WhatsApp credentials for a user
   * Returns decrypted access token and phone number ID
   */
  private async getWhatsAppCredentials(
    userId: string
  ): Promise<{ phoneNumberId: string; accessToken: string } | null> {
    try {
      // Get WhatsApp API key from encrypted storage
      const accessToken = await apiKeyManagementService.getDecryptedAPIKey(
        userId,
        'whatsapp'
      );

      if (!accessToken) {
        return null;
      }

      // Get phone number ID from user record
      const user = await prisma.users.findUnique({
        where: { id: userId },
        select: { whatsappNumber: true, whatsappConnected: true },
      });

      if (!user || !user.whatsappConnected || !user.whatsappNumber) {
        return null;
      }

      return {
        phoneNumberId: user.whatsappNumber, // We store phone_number_id here
        accessToken,
      };
    } catch (error) {
      logger.error('Error retrieving WhatsApp credentials', {
        error,
        userId,
      });
      return null;
    }
  }

  /**
   * Connect WhatsApp Business account
   */
  async connectWhatsApp(
    userId: string,
    phoneNumberId: string,
    accessToken: string
  ): Promise<{ success: boolean; error?: string }> {
    try {
      // Verify credentials by making test API call
      const testResponse = await fetch(
        `${this.META_API_BASE}/${phoneNumberId}?fields=display_phone_number,verified_name`,
        {
          headers: {
            Authorization: `Bearer ${accessToken}`,
          },
        }
      );

      if (!testResponse.ok) {
        const error = await testResponse.json();
        logger.warn('WhatsApp credentials verification failed', {
          userId,
          error,
        });
        return {
          success: false,
          error: 'Invalid WhatsApp credentials. Please check and try again.',
        };
      }

      const phoneData = await testResponse.json();

      // Store encrypted access token
      await apiKeyManagementService.createAPIKey(userId, {
        service: 'whatsapp',
        keyName: 'WhatsApp Business Access Token',
        apiKey: accessToken,
      });

      // Update user record
      await prisma.users.update({
        where: { id: userId },
        data: {
          whatsappConnected: true,
          whatsappNumber: phoneNumberId,
          whatsappConnectedAt: new Date(),
        },
      });

      logger.info('WhatsApp connected successfully', {
        userId,
        phoneNumber: phoneData.display_phone_number,
      });

      return { success: true };
    } catch (error) {
      logger.error('Error connecting WhatsApp', error);
      return {
        success: false,
        error: 'Failed to connect WhatsApp. Please try again.',
      };
    }
  }

  /**
   * Disconnect WhatsApp Business account
   */
  async disconnectWhatsApp(
    userId: string
  ): Promise<{ success: boolean; error?: string }> {
    try {
      // Find and deactivate API key
      const apiKeys = await userApiCredentialsAdapter.findMany({
        where: {
          userId,
          service: 'whatsapp',
          isActive: true,
        },
      }) as Array<{ id: string }>;

      for (const key of apiKeys) {
        await apiKeyManagementService.deactivateAPIKey(key.id, userId);
      }

      // Update user record
      await prisma.users.update({
        where: { id: userId },
        data: {
          whatsappConnected: false,
          whatsappNumber: null,
          whatsappConnectedAt: null,
        },
      });

      logger.info('WhatsApp disconnected successfully', { userId });

      return { success: true };
    } catch (error) {
      logger.error('Error disconnecting WhatsApp', error);
      return {
        success: false,
        error: 'Failed to disconnect WhatsApp. Please try again.',
      };
    }
  }

  /**
   * Get WhatsApp connection status for a user
   */
  async getConnectionStatus(userId: string): Promise<{
    connected: boolean;
    phoneNumber?: string;
    displayPhoneNumber?: string;
    verifiedName?: string;
    connectedAt?: Date;
  }> {
    try {
      const user = await prisma.users.findUnique({
        where: { id: userId },
        select: {
          whatsappConnected: true,
          whatsappNumber: true,
          whatsappConnectedAt: true,
        },
      });

      if (
        !user ||
        !user.whatsappConnected ||
        !user.whatsappNumber
      ) {
        return { connected: false };
      }

      // Get phone details from Meta API
      const credentials = await this.getWhatsAppCredentials(userId);
      if (!credentials) {
        return {
          connected: true,
          phoneNumber: user.whatsappNumber,
          connectedAt: user.whatsappConnectedAt || undefined,
        };
      }

      try {
        const response = await fetch(
          `${this.META_API_BASE}/${credentials.phoneNumberId}?fields=display_phone_number,verified_name`,
          {
            headers: {
              Authorization: `Bearer ${credentials.accessToken}`,
            },
          }
        );

        if (response.ok) {
          const data = await response.json();
          return {
            connected: true,
            phoneNumber: user.whatsappNumber,
            displayPhoneNumber: data.display_phone_number,
            verifiedName: data.verified_name,
            connectedAt: user.whatsappConnectedAt || undefined,
          };
        }
      } catch (error) {
        // API call failed, but still show as connected
        logger.debug('Failed to fetch WhatsApp phone details', error);
      }

      return {
        connected: true,
        phoneNumber: user.whatsappNumber,
        connectedAt: user.whatsappConnectedAt || undefined,
      };
    } catch (error) {
      logger.error('Error getting WhatsApp connection status', error);
      return { connected: false };
    }
  }
}

// Export singleton instance
export const whatsappService = new WhatsAppService();
