import "dotenv/config";
import axios, { type AxiosResponse } from "axios";
import type {
  SendTemplateParams,
  SendDeliveryUpdateParams,
  SendCustomerPaymentReceivedParams,
  TemplateComponent,
  WhatsAppConfig,
  SendSupplierPaymentMessageParams,
  SendSupplierBoxReturnMessageParams,
  SendInvoiceReadyParams,
} from "./whatsapp.types.js";
import {
  WHATSAPP_TEMPLATES,
  buildDeliveryUpdateComponents,
  buildCustomerPaymentReceivedComponents,
  buildCustomerPaymentReceivedTemplateParams,
  buildSupplierPaymentMessageComponents,
  buildSupplierPaymentMessageTemplateParams,
  buildSupplierBoxReturnMessageComponents,
  buildSupplierBoxReturnMessageTemplateParams,
  buildInvoiceReadyComponents,
  buildInvoiceReadyTemplateParams,
} from "./whatsapp.templates.js";

export class WhatsAppService {
  /**
   * Reads and validates the SmartPing WhatsApp API configuration from environment variables.
   */
  private getConfig(): WhatsAppConfig {
    const apiUrl =
      process.env.WHATSAPP_API_URL ||
      "https://backend.api-wa.co/campaign/smartping/api";
    const apiKey =
      process.env.WHATSAPP_API_KEY;

    if (!apiKey) {
      throw new Error(
        "WhatsApp API Error: WHATSAPP_API_KEY is not configured in .env"
      );
    }

    return {
      apiUrl,
      apiKey,
      phoneNumberId: process.env.WHATSAPP_PHONE_NUMBER_ID,
    };
  }

  /**
   * Check if WhatsApp service is configured with valid environment variables.
   */
  public isConfigured(): boolean {
    const apiKey = process.env.WHATSAPP_API_KEY;
    return Boolean(
      apiKey &&
      apiKey !== "your-api-key" &&
      apiKey !== "your_api_key_here" &&
      apiKey !== "your_whatsapp_api_key_here" &&
      apiKey !== "YOUR_WHATSAPP_API_KEY"
    );
  }

  /**
   * Sanitizes phone number to international format with '+' prefix for SmartPing (E.164).
   * E.g. '9876543210' -> '+919876543210'
   * E.g. '+91 98765-43210' -> '+919876543210'
   */
  public sanitizePhoneNumber(phone: string): string {
    if (!phone) {
      throw new Error("Phone number is required to send WhatsApp message");
    }

    let cleaned = phone.replace(/\D/g, "");

    // If 10 digits (Standard Indian Mobile Number), prepend country code 91
    if (cleaned.length === 10) {
      cleaned = `91${cleaned}`;
    }

    return `+${cleaned}`;
  }

  /**
   * Extracts flat string parameters from TemplateComponent array if provided.
   */
  private extractParamsFromComponents(components?: TemplateComponent[]): string[] {
    if (!components || components.length === 0) return [];
    const params: string[] = [];
    for (const comp of components) {
      if (comp.parameters) {
        for (const p of comp.parameters) {
          if ("text" in p && p.text !== undefined) {
            params.push(String(p.text));
          } else if ("currency" in p && p.currency) {
            params.push(String(p.currency.fallback_value));
          } else if ("date_time" in p && p.date_time) {
            params.push(String(p.date_time.fallback_value));
          } else {
            params.push(String(p));
          }
        }
      }
    }
    return params;
  }

  /**
   * Core method to send WhatsApp template message via SmartPing API.
   * Method: POST
   * URL: https://backend.api-wa.co/campaign/smartping/api
   */
  async sendTemplate({
    to,
    userName = "Customer",
    templateName,
    campaignName,
    templateParams,
    components,
  }: SendTemplateParams): Promise<any> {
    const { apiUrl, apiKey } = this.getConfig();
    const destination = this.sanitizePhoneNumber(to);
    const targetCampaign = campaignName || templateName;

    if (!targetCampaign) {
      throw new Error("WhatsApp API Error: campaignName is required for SmartPing");
    }

    const finalParams =
      templateParams && templateParams.length > 0
        ? templateParams
        : this.extractParamsFromComponents(components);

    const payload = {
      apiKey,
      campaignName: targetCampaign,
      destination,
      userName: userName || "Customer",
      templateParams: finalParams,
    };

    try {
      const response: AxiosResponse = await axios.post(apiUrl, payload, {
        headers: {
          "Content-Type": "application/json",
        },
        timeout: 15000,
      });

      return response.data;
    } catch (error: any) {
      const errorDetails = error.response?.data || error.message;
      console.error("SmartPing WhatsApp API Error Response:", JSON.stringify(errorDetails, null, 2));

      const message =
        error.response?.data?.message ||
        error.response?.data?.error?.message ||
        error.message ||
        "Failed to send WhatsApp message via SmartPing";

      throw new Error(`WhatsApp Send Failed: ${message}`);
    }
  }

  /**
   * Helper: Send Delivery Update (Template: delivery_update_2)
   */
  async sendDeliveryUpdate(params: SendDeliveryUpdateParams): Promise<any> {
    const components = buildDeliveryUpdateComponents(params);
    return this.sendTemplate({
      to: params.phone,
      userName: params.customerName,
      templateName: WHATSAPP_TEMPLATES.DELIVERY_UPDATE,
      languageCode: params.languageCode || "en_US",
      components,
    });
  }

  /**
   * Helper: Send Customer Payment Received (SmartPing Campaign: CUSTOMER_PAY_RECEIVE)
   * Variables:
   * {{1}} = Customer Name
   * {{2}} = Payment Amount
   * {{3}} = Payment Date
   * {{4}} = Remaining Balance
   */
  async sendCustomerPaymentReceived(
    params: SendCustomerPaymentReceivedParams
  ): Promise<any> {
    const templateParams = buildCustomerPaymentReceivedTemplateParams(params);
    return this.sendTemplate({
      to: params.phone,
      userName: params.customerName || "Customer",
      campaignName: WHATSAPP_TEMPLATES.CUSTOMER_PAYMENT_RECEIVED,
      templateParams,
    });
  }

  /** 
   * Helper: Send Supplier Payment Message (SmartPing Campaign: BILLING)
   * Variables:
   * {{1}} = Supplier Name
   * {{2}} = Payment Amount
   * {{3}} = Payment Date
   * {{4}} = Payment Mode
   * {{5}} = Reference Number
   * {{6}} = Remaining Balance
   */
  async sendSupplierPaymentMessage(
    params: SendSupplierPaymentMessageParams
  ): Promise<any> {
    const templateParams = buildSupplierPaymentMessageTemplateParams(params);
    return this.sendTemplate({
      to: params.phone,
      userName: params.supplierName || "Supplier",
      campaignName: WHATSAPP_TEMPLATES.SUPPLIER_PAYMENT_MESSAGE,
      templateParams,
    });
  }

  /**
   * Helper: Send Supplier Box Return Message (SmartPing Campaign: BOX_RETURN)
   * Variables:
   * {{1}} = Supplier Name
   * {{2}} = Total boxes purchased
   * {{3}} = Vegetable Name
   * {{4}} = Returned boxes
   * {{5}} = Retained boxes
   */
  async sendSupplierBoxReturnMessage(
    params: SendSupplierBoxReturnMessageParams
  ): Promise<any> {
    const templateParams = buildSupplierBoxReturnMessageTemplateParams(params);
    return this.sendTemplate({
      to: params.phone,
      userName: params.supplierName || "Supplier",
      campaignName: WHATSAPP_TEMPLATES.BOX_RETURN_SUPPLIER,
      templateParams,
    });
  }

  /**
   * Helper: Send Invoice Ready notification to customer (SmartPing Campaign: CUSTOMER_PAY)
   * Variables:
   * {{1}} = Customer Name
   * {{2}} = Invoice Number
   * {{3}} = Invoice Amount
   * {{4}} = Invoice UUID
   */
  async sendInvoiceReady(
    params: SendInvoiceReadyParams
  ): Promise<any> {
    const templateParams = buildInvoiceReadyTemplateParams(params);
    return this.sendTemplate({
      to: params.phone,
      userName: params.customerName || "Customer",
      campaignName: WHATSAPP_TEMPLATES.INVOICE_READY,
      templateParams,
    });
  }
}

const whatsappService = new WhatsAppService();
export default whatsappService;

