// Import channel constants from the existing constants file
import { isEqual } from "lodash";
import {
  SMS,
  EMAIL,
  MOBILE_PUSH,
  WHATSAPP,
  PUSH,
  ZALO,
  RCS,
  LINE,
  VIBER,
  WEBPUSH,
  EMF,
  VENENO,
  TEXT,
  IOS,
  ANDROID,
  EXTERNAL_URL,
  BIG_TEXT,
} from "../v2Containers/CreativesContainer/constants";

// Creates a base payload structure common to all channels
const createBasePayload = (channelType, metadata = {}) => {
  const { actionId, ouId, clientName, module } = metadata;

  return {
    centralCommsPayload: {
      ouId: ouId || -1,
      sourceEntityId: actionId,
      channel: channelType,
      module,
      executionParams: {},
      clientName:
        clientName || ([SMS, EMAIL].includes(channelType) ? EMF : VENENO)
    }
  };
};

// Transforms the channel payload based on the channel type
/**
 * General transformer function that handles different channel types
 * @param {Object} data - The input data
 * @param {Object} options - Additional options for transformation
 * @returns {Object} - Transformed payload based on channel type
 */
export const transformChannelPayload = (data, options = {}) => {
  const channel = data.channel?.toUpperCase();

  switch (channel) {
    case SMS:
      return transformSmsPayload(data, options);
    case MOBILE_PUSH:
      return transformMpushPayload(data, options);
    case EMAIL:
      return transformEmailPayload(data, options);
    case WHATSAPP:
      return transformWhatsappPayload(data, options);
    case ZALO:
      return transformZaloPayload(data, options);
    case RCS:
      return transformRcsPayload(data, options);
    case LINE:
      return transformLinePayload(data, options);
    case VIBER:
      return transformViberPayload(data, options);
    case WEBPUSH:
      return transformWebpushPayload(data, options);
    default:
      return data; // Return unchanged for unsupported channels
  }
};
/**
 * Transforms SMS data to the required payload format
 * @param {Object} smsData - Current SMS data
 * @param {Object} options - Additional options (ouId, sourceEntityId, etc.)
 * @returns {Object} - Transformed SMS payload
 */
const transformSmsPayload = (smsData, options = {}) => {
  const { loyaltyMetaData = {} } = options;
  const { transformedMessageDetails = {} } = loyaltyMetaData;
  const { smsDeliverySettings } = transformedMessageDetails;

  // Get base payload structure
  const payload = createBasePayload(SMS, loyaltyMetaData);

  // Add SMS-specific properties
  payload.centralCommsPayload.smsMessageContent = {
    channel: SMS,
    // Override the message property if messageBody exists
    message: smsData?.messageBody || "",
    ...smsData
  };
  payload.centralCommsPayload.smsDeliverySettings = smsDeliverySettings || {};

  return payload;
};
/**
 * Transforms Email data to the required payload format
 * @param {Object} emailData - Current email data
 * @param {Object} options - Additional options (ouId, sourceEntityId, etc.)
 * @returns {Object} - Transformed Email payload
 */
const transformEmailPayload = (emailData, options = {}) => {
  const { loyaltyMetaData = {} } = options;
  const { transformedMessageDetails = {} } = loyaltyMetaData;
  const { emailDeliverySettings = {} } = transformedMessageDetails;

  // Get base payload structure
  const payload = createBasePayload(EMAIL, loyaltyMetaData);

  // Add Email-specific properties
  payload.centralCommsPayload.emailMessageContent = {
    channel: EMAIL,
    messageBody: emailData?.emailBody || "",
    messageSubject: emailData?.emailSubject || "",
    ...emailData
  };
  payload.centralCommsPayload.emailDeliverySettings =
    emailDeliverySettings || {};

  return payload;
};
/**
 * Transforms Mobile Push data to the required payload format
 * @param {Object} mpushData - Current mobile push data
 * @param {Object} options - Additional options (ouId, sourceEntityId, etc.)
 * @returns {Object} - Transformed Mobile Push payload
 */
const transformMpushPayload = (mpushData, options = {}) => {
  const { loyaltyMetaData = {} } = options;
  const { transformedMessageDetails = {} } = loyaltyMetaData;
  const { mobilePushDeliverySettings = {} } = transformedMessageDetails;

  // Get default values for Android and iOS content
  const androidContent = mpushData?.androidContent || {};
  const iosContent = mpushData?.iosContent || {
    type: androidContent?.type || TEXT,
    deviceType: IOS,
    title: mpushData?.messageSubject || "",
    message: "",
  };

  // Get base payload structure
  const payload = createBasePayload(PUSH, loyaltyMetaData);

  // Add Mobile Push-specific properties with spread operator
  payload.centralCommsPayload.mpushMessageContent = {
    channel: PUSH,
    messageSubject: mpushData?.messageSubject || "",
    androidContent: {
      type: androidContent?.type || TEXT, // Use the type from content if available, fallback to TEXT
      deviceType: ANDROID,
      ...androidContent,
      cta: {
        type: EXTERNAL_URL,
        actionText: null,
        templateCtaId: null,
        ...(androidContent?.cta || {}),
      },
      expandableDetails: {
        style: BIG_TEXT,
        ...androidContent?.expandableDetails,
      },
      customProperties: androidContent?.custom || {},
    },
    iosContent: {
      type: iosContent?.type || TEXT, // Use the type from content if available, fallback to TEXT
      deviceType: IOS,
      ...iosContent,
      cta: {
        type: EXTERNAL_URL,
        actionText: null,
        templateCtaId: null,
        ...(iosContent?.cta || {}),
      },
      expandableDetails: {
        style: BIG_TEXT,
        ...iosContent?.expandableDetails,
      },
      customProperties: iosContent?.custom || {},
    },
    accountId: mpushData?.accountId || 0,
  };
  payload.centralCommsPayload.mpushDeliverySettings = mobilePushDeliverySettings || {};

  return payload;
};
/**
 * Transforms WhatsApp data to the required payload format
 * @param {Object} whatsappData - Current WhatsApp data
 * @param {Object} options - Additional options (ouId, sourceEntityId, etc.)
 * @returns {Object} - Transformed WhatsApp payload
 */
const transformWhatsappPayload = (whatsappData, options = {}) => {
  const { loyaltyMetaData = {} } = options;
  const { transformedMessageDetails = {} } = loyaltyMetaData;
  const { whatsappDeliverySettings = {} } = transformedMessageDetails;

  // Get base payload structure
  const payload = createBasePayload(WHATSAPP, loyaltyMetaData);

  // Add WhatsApp-specific properties
  payload.centralCommsPayload.whatsappMessageContent = {
    channel: WHATSAPP,
    messageBody: "",
    ...whatsappData,
    // Ensure templateConfigs is preserved (it might contain complex nested objects)
    templateConfigs: whatsappData?.templateConfigs || {}
  };
  payload.centralCommsPayload.whatsappDeliverySettings =
    whatsappDeliverySettings || {};

  return payload;
};
/**
 * Transforms Zalo data to the required payload format
 * @param {Object} zaloData - Current Zalo data
 * @param {Object} options - Additional options (ouId, sourceEntityId, etc.)
 * @returns {Object} - Transformed Zalo payload
 */
const transformZaloPayload = (zaloData, options = {}) => {
  const { loyaltyMetaData = {} } = options;
  const { transformedMessageDetails = {} } = loyaltyMetaData;
  const { zaloDeliverySettings = {} } = transformedMessageDetails;

  // Get base payload structure
  const payload = createBasePayload(ZALO, loyaltyMetaData);

  // Add Zalo-specific properties
  payload.centralCommsPayload.zaloMessageContent = {
    channel: ZALO,
    messageBody: "",
    accountId: "",
    accountName: "",
    token: "",
    ...zaloData,
    // Ensure templateConfigs is preserved (it might contain complex nested objects)
    templateConfigs: zaloData?.templateConfigs || {}
  };
  payload.centralCommsPayload.zaloDeliverySettings = zaloDeliverySettings || {};

  return payload;
};

/**
 * Transforms RCS data to the required payload format
 * @param {Object} rcsData - Current RCS data
 * @param {Object} options - Additional options (ouId, sourceEntityId, etc.)
 * @returns {Object} - Transformed RCS payload
 */
// TODO: RCS is currently not supported by the CCS - BE. We need to make changes in future as per the BE changes.
const transformRcsPayload = (rcsData, options = {}) => {
  const { loyaltyMetaData = {} } = options;
  const { transformedMessageDetails = {} } = loyaltyMetaData;
  const { rcsDeliverySettings = {} } = transformedMessageDetails || {};

  // Get base payload structure
  const payload = createBasePayload(RCS, loyaltyMetaData);

  // Add RCS-specific properties
  payload.centralCommsPayload.rcsMessageContent = {
    channel: RCS,
    messageBody: "",
    accountId: rcsData?.accountId || "",
    accountName: rcsData?.accountName || "",
    ...rcsData,
    // Ensure templateConfigs is preserved (it might contain complex nested objects)
    templateConfigs: rcsData?.templateConfigs || {},
  };
  payload.centralCommsPayload.rcsDeliverySettings = rcsDeliverySettings;

  return payload;
};

/**
 * Transforms LINE data to the required payload format
 * @param {Object} lineData - Current LINE data
 * @param {Object} options - Additional options (ouId, sourceEntityId, etc.)
 * @returns {Object} - Transformed LINE payload
 */
const transformLinePayload = (lineData, options = {}) => {
  const { loyaltyMetaData = {} } = options;
  const { transformedMessageDetails = {} } = loyaltyMetaData;
  const { lineDeliverySettings = {} } = transformedMessageDetails || {};

  // Get base payload structure
  const payload = createBasePayload(LINE, loyaltyMetaData);
  payload.centralCommsPayload.lineMessageContent = {
    channel: LINE,
    accountId: lineData?.accountId || 0,
    accountDetails: lineData?.accountDetails || "",
    messageBody: lineData?.messageBody || "",
    ...lineData,
  };
  payload.centralCommsPayload.lineDeliverySettings = lineDeliverySettings;
  return payload;
};

/**
 * Transforms VIBER data to the required payload format
 * @param {Object} viberData - Current VIBER data
 * @param {Object} options - Additional options (ouId, sourceEntityId, etc.)
 * @returns {Object} - Transformed VIBER payload
 */
const transformViberPayload = (viberData, options = {}) => {
  const { loyaltyMetaData = {} } = options;
  const { transformedMessageDetails = {} } = loyaltyMetaData;
  const { viberDeliverySettings = {} } = transformedMessageDetails || {};
  // Get base payload structure
  const payload = createBasePayload(VIBER, loyaltyMetaData);
  payload.centralCommsPayload.viberMessageContent = {
    channel: VIBER,
    accountId: viberData?.accountId || 0,
    accountDetails: viberData?.accountDetails || "",
    messageBody: viberData?.messageBody || "",
    ...viberData,
  };
  payload.centralCommsPayload.viberDeliverySettings = viberDeliverySettings;
  return payload;
};

/**
 * Transforms WebPush data to the required payload format
 * @param {Object} webpushData - Current WebPush data
 * @param {Object} options - Additional options (ouId, sourceEntityId, etc.)
 * @returns {Object} - Transformed WebPush payload
 */
const transformWebpushPayload = (webpushData, options = {}) => {
  const { loyaltyMetaData = {} } = options;
  const { transformedMessageDetails = {} } = loyaltyMetaData;
  const { webpushDeliverySettings = {} } = transformedMessageDetails || {};
  
  // Get base payload structure
  const payload = createBasePayload(WEBPUSH, loyaltyMetaData);
  
  // Extract webpush content from messageContent.content.content structure
  const webpushContent = webpushData?.messageContent?.content?.content || {};
  const accountId = webpushData?.messageContent?.content?.accountId || 0;
  
  // Add WebPush-specific properties
  payload.centralCommsPayload.webpushMessageContent = {
    channel: WEBPUSH,
    accountId,
    content: {
      title: webpushContent?.title || '',
      message: webpushContent?.message || '',
      ...(webpushContent?.iconImageUrl && { iconImageUrl: webpushContent.iconImageUrl }),
      ...(webpushContent?.cta && { cta: webpushContent.cta }),
      ...(webpushContent?.expandableDetails && { expandableDetails: webpushContent.expandableDetails }),
    },
    messageSubject: webpushData?.messageSubject || "",
    offers: webpushData?.messageContent?.content?.offers || [],
  };
  payload.centralCommsPayload.webpushDeliverySettings = webpushDeliverySettings;
  
  return payload;
};

// Checks if the template has changed
export const getTemplateDiffState = (channel, oldData, newData) => {
  switch (channel.toUpperCase()) {
    case SMS:
      return checkSmsDiff(oldData, newData);
    case EMAIL:
      return checkEmailDiff(oldData, newData);
    case MOBILE_PUSH:
    case PUSH:
      return checkPushDiff(oldData, newData);
    case WHATSAPP:
      return checkWhatsappDiff(oldData, newData);
    case ZALO:
      return checkZaloDiff(oldData, newData);
    case LINE:
      return checkLineDiff(oldData, newData);
    case VIBER:
      return checkViberDiff(oldData, newData);
    // TODO: RCS is currently not supported by the CCS - BE. We need to make changes in future as per the BE changes.
    case RCS:
      return checkRcsDiff(oldData, newData);
    default:
      return false;
  }
};
/**
 * Checks differences between old and new SMS data
 * @param {Object} oldData - Previous SMS template data
 * @param {Object} newData - Updated SMS template data
 * @returns {Boolean} - Whether the template has changed
 */
const checkSmsDiff = (oldData, newData) => {
  // Extract old message content
  const oldMessage =
    oldData?.transformedMessageDetails?.smsMessageContent?.message || "";

  // Extract new message content
  const newMessage = newData?.messageBody || "";

  // Compare message content
  return oldMessage !== newMessage;
};
/**
 * Checks differences between old and new Email data
 * @param {Object} oldData - Previous Email template data
 * @param {Object} newData - Updated Email template data
 * @returns {Boolean} - Whether the template has changed
 */
const checkEmailDiff = (oldData, newData) => {
  // Extract old email content
  const oldEmailBody =
    oldData?.transformedMessageDetails?.emailMessageContent?.messageBody || "";
  const oldEmailSubject =
    oldData?.transformedMessageDetails?.emailMessageContent?.messageSubject ||
    "";

  // Extract new email content
  const newEmailBody = newData?.emailBody || "";
  const newEmailSubject = newData?.emailSubject || "";

  // Check if subject has changed
  if (oldEmailSubject !== newEmailSubject) {
    return true;
  }

  // Use lodash's isEqual for deep comparison of email body content --> more efficient for complex HTML content
  return !isEqual(oldEmailBody, newEmailBody);
};
/**
 * Checks differences between old and new Push data
 * @param {Object} oldData - Previous Push template data
 * @param {Object} newData - Updated Push template data
 * @returns {Boolean} - Whether the template has changed
 */
const checkPushDiff = (oldData, newData) => {
  // Extract old push content
  const oldAndroidContent =
    oldData?.transformedMessageDetails?.mpushMessageContent?.androidContent ||
    {};
  const oldIosContent =
    oldData?.transformedMessageDetails?.mpushMessageContent?.iosContent || {};
  const oldSubject =
    oldData?.transformedMessageDetails?.mpushMessageContent?.messageSubject ||
    "";

  // Extract new push content
  const newAndroidContent = newData?.androidContent || {};
  const newIosContent = newData?.iosContent || {};
  const newSubject = newData?.messageSubject || "";

  // Compare subject
  if (oldSubject !== newSubject) return true;

  // Compare Android content
  if (oldAndroidContent.title !== newAndroidContent.title) return true;
  if (oldAndroidContent.message !== newAndroidContent.message) return true;
  if (oldAndroidContent.cta?.actionLink !== newAndroidContent.cta?.actionLink) {
    return true;
  }

  // Compare iOS content
  if (oldIosContent.title !== newIosContent.title) return true;
  if (oldIosContent.message !== newIosContent.message) return true;
  if (oldIosContent.cta?.actionLink !== newIosContent.cta?.actionLink) {
    return true;
  }

  return false;
};
/**
 * Checks differences between old and new WhatsApp data
 * @param {Object} oldData - Previous WhatsApp template data
 * @param {Object} newData - Updated WhatsApp template data
 * @returns {Boolean} - Whether the template has changed
 */
const checkWhatsappDiff = (oldData, newData) => {
  // Extract old WhatsApp content
  const oldMessage =
    oldData?.transformedMessageDetails?.whatsappMessageContent?.messageBody ||
    "";
  const oldTemplateConfigs =
    oldData?.transformedMessageDetails?.whatsappMessageContent
      ?.templateConfigs || {};

  // Extract new WhatsApp content
  const newMessage = newData?.messageBody || "";
  const newTemplateConfigs = newData?.templateConfigs || {};

  // Compare message content
  if (oldMessage !== newMessage) return true;

  // Compare account IDs for quick rejection
  if (
    oldData?.transformedMessageDetails?.whatsappMessageContent?.accountId !==
    newData?.accountId
  ) {
    return true;
  }

  // Compare source account identifiers for quick rejection
  if (
    oldData?.transformedMessageDetails?.whatsappMessageContent
      ?.sourceAccountIdentifier !== newData?.sourceAccountIdentifier
  ) {
    return true;
  }

  // If template configs have different structures, they've changed
  if (
    Object.keys(newTemplateConfigs).length !==
    Object.keys(oldTemplateConfigs).length
  ) {
    return true;
  }

  // Use deep comparison for template configs
  return !isEqual(oldTemplateConfigs, newTemplateConfigs);
};
/**
 * Checks differences between old and new Zalo data
 * @param {Object} oldData - Previous Zalo template data
 * @param {Object} newData - Updated Zalo template data
 * @returns {Boolean} - Whether the template has changed
 */
const checkZaloDiff = (oldData, newData) => {
  // Extract old Zalo content
  const oldTemplateConfigs =
    oldData?.transformedMessageDetails?.zaloMessageContent?.templateConfigs ||
    {};
  const oldAccountId =
    oldData?.transformedMessageDetails?.zaloMessageContent?.accountId || "";
  const oldToken =
    oldData?.transformedMessageDetails?.zaloMessageContent?.token || "";

  // Extract new Zalo content
  const newTemplateConfigs = newData?.templateConfigs || {};
  const newAccountId = newData?.accountId || "";
  const newToken = newData?.token || "";

  // Compare simple properties for quick rejection
  if (oldAccountId !== newAccountId) return true;
  if (oldToken !== newToken) return true;

  // If template configs have different structures, they've changed
  if (
    Object.keys(newTemplateConfigs).length !==
    Object.keys(oldTemplateConfigs).length
  ) {
    return true;
  }

  // Use deep comparison for template configs
  return !isEqual(oldTemplateConfigs, newTemplateConfigs);
};

/**
 * Checks differences between old and new RCS data
 * @param {Object} oldData - Previous RCS template data
 * @param {Object} newData - Updated RCS template data
 * @returns {Boolean} - Whether the template has changed
 */
// TODO: RCS is currently not supported by the CCS - BE. We need to make changes in future as per the BE changes.
const checkRcsDiff = (oldData, newData) => {
  // Extract old RCS content
  const { templateConfigs: oldTemplateConfigs = {}, accountId: oldAccountId = "", accountName: oldAccountName = "" } = 
    oldData?.transformedMessageDetails?.rcsMessageContent || {};

  // Extract new RCS content
  const { templateConfigs: newTemplateConfigs = {}, accountId: newAccountId = "", accountName: newAccountName = "" } = newData || {};

  // Compare simple properties for quick rejection
  if (oldAccountId !== newAccountId) return true;
  if (oldAccountName !== newAccountName) return true;

  // If template configs have different structures, they've changed
  if (
    Object.keys(newTemplateConfigs)?.length
    !== Object.keys(oldTemplateConfigs)?.length
  ) {
    return true;
  }

  // Use deep comparison for template configs
  return !isEqual(oldTemplateConfigs, newTemplateConfigs);
};

/**
 * Checks differences between old and new LINE data
 * @param {Object} oldData - Previous LINE template data
 * @param {Object} newData - Updated LINE template data
 * @returns {Boolean} - Whether the template has changed
 */
const checkLineDiff = (oldData, newData) => {
  // Extract old LINE content
  const { messageBody: oldMessageBody = "", accountId: oldAccountId = "", accountDetails: oldAccountDetails = "" } = 
    oldData?.transformedMessageDetails?.lineMessageContent || {};

  // Extract new LINE content
  const { messageBody: newMessageBody = "", accountId: newAccountId = "", accountDetails: newAccountDetails = "" } = newData || {};

  // Compare simple properties for quick rejection
  if (oldMessageBody !== newMessageBody) return true;
  if (oldAccountId !== newAccountId) return true;
  if (oldAccountDetails !== newAccountDetails) return true;

  return false;
};

/**
 * Checks differences between old and new VIBER data
 * @param {Object} oldData - Previous VIBER template data
 * @param {Object} newData - Updated VIBER template data
 * @returns {Boolean} - Whether the template has changed
 */
const checkViberDiff = (oldData, newData) => {
  // Extract old VIBER content
  const { messageBody: oldMessageBody = "", accountId: oldAccountId = "", accountDetails: oldAccountDetails = "" } = 
    oldData?.transformedMessageDetails?.viberMessageContent || {};

  // Extract new VIBER content
  const { messageBody: newMessageBody = "", accountId: newAccountId = "", accountDetails: newAccountDetails = "" } = newData || {};

  // Compare simple properties for quick rejection
  if (oldMessageBody !== newMessageBody) return true;
  if (oldAccountId !== newAccountId) return true;
  if (oldAccountDetails !== newAccountDetails) return true;

  return false;
};
