import React from 'react';
import { FormattedMessage } from 'react-intl';
import get from 'lodash/get';
import { convert } from "html-to-text";
import { EMBEDDED } from "../v2Containers/Whatsapp/constants";
import {
  EDIT,
  EMAIL,
  INAPP,
  PREVIEW,
} from "../v2Containers/App/constants";
import {
  MOBILE_PUSH,
  SMS,
  ANDROID,
  IOS,
} from "../v2Containers/CreativesContainer/constants";
import { GLOBAL_CONVERT_OPTIONS } from "../v2Components/FormBuilder/constants";
import { SMS_TRAI_VAR } from '../v2Containers/SmsTrai/Edit/constants';
import { EMAIL_REGEX, PHONE_REGEX } from '../v2Components/CommonTestAndPreview/constants';

export const apiMessageFormatHandler = (id, fallback) => (
  <FormattedMessage id={id} defaultMessage={fallback} />
);

export const addBaseToTemplate = (template) => {
  const {
    versions: {
      history = [],
    } = {},
  } = template || {};
  if (history?.length) {
    return ({
      ...template,
      versions: {
        ...template.versions,
        base: {
          ...history[0],
          ...( get(template, 'versions.base.subject') ? {subject: get(template, 'versions.base.subject')} : { subject: history?.[0]?.subject }),
        },
      },
    });
  }
  return template;
};

export const isEmbeddedEditOrPreview = (queryType, creativesMode) => queryType === EMBEDDED && [EDIT, PREVIEW].includes(creativesMode);

export const transformCustomFieldsData = (customFields) => {
  // Define mapping of scopes to their display names
  const scopeMapping = {
    loyalty_registration: 'Registration custom fields',
    loyalty_transaction: 'Registration custom fields',
    store_custom_fields: 'Organization custom fields',
    org_custom_field: 'Organization custom fields',
  };

  // Initialize result structure with all possible sections
  const result = Object.values(scopeMapping).reduce((acc, sectionName) => {
    acc[sectionName] = {
      name: sectionName,
      subtags: {},
    };
    return acc;
  }, {});

  // Process each custom field
  Object.values(customFields).forEach((field) => {
    const {scope = ''} = field;
    const sectionName = scopeMapping[scope];

    if (sectionName) {
      // Determine the prefix based on scope
      let prefix = 'custom_field';
      if (scope === 'org_custom_field') {
        prefix = 'org_custom_field';
      } else if (scope === 'store_custom_fields') {
        prefix = 'store_custom_field';
      }

      const fieldKey = `${prefix}.${field?.name}`;
      // Add field to appropriate section
      result[sectionName].subtags[fieldKey] = {
        name: field?.name,
        desc: field?.name || field?.label,
      };
    }
  });

  // Remove empty sections (those with no subtags)
  Object.keys(result).forEach((sectionName) => {
    if (Object.keys(result[sectionName]?.subtags)?.length === 0) {
      delete result[sectionName];
    }
  });

  return result;
};

export const isTagIncluded = (value) => value && value.includes('{{') && value.includes('}}');


/**
 *
 * @param {*} channel
 * @param {*} formData
 * @returns
 */
export const getChannelData = (channel, formData, baseLanguage) => {
  switch (channel?.toUpperCase()) {
    case EMAIL.toUpperCase():
      return convert(
        formData?.base?.[baseLanguage]?.["template-content"] || "",
        GLOBAL_CONVERT_OPTIONS
      );

    case SMS:
      return (
        `${formData?.base?.["sms-editor"]} ${formData?.["template-name"]}` || ""
      );
    case SMS_TRAI_VAR?.toUpperCase():
      return formData?.versions?.base?.["updated-sms-editor"].join(" ") || "";
    default:
      return JSON.stringify(formData);
  }
};

/**
 * Validates liquid template content for a given channel and options.
 * @param {string} content - The content to validate.
 * @param {string} channel - Channel type (e.g., EMAIL, SMS, MOBILE_PUSH).
 * @param {object} options - Validation options and callbacks.
 * @returns {Promise} Resolves to the validation result.
 */
export const validateLiquidTemplateContent = async (
  content,
  options
) => {
  const {
    getLiquidTags,
    formatMessage,
    messages,
    onError = () => {},
    onSuccess = () => {},
    tabType,
  } = options;
  const emptyBodyError = formatMessage(messages?.emailBodyEmptyError);
  const somethingWrongMsg = formatMessage(messages?.somethingWentWrong);
  // Empty content check

  if (!content || content.trim() === "") {
    onError({
      standardErrors: [emptyBodyError],
      liquidErrors: [],
      tabType,
    });
    return false;
  }

  // Await getLiquidTags as a promise if it doesn't already return one
  const getLiquidTagsAsync = (inputContent) => new Promise((resolve) => {
    getLiquidTags(inputContent, (result) => {
      resolve(result);
    });
  });

  const {askAiraResponse: result, isError} = await getLiquidTagsAsync(content);
  const validString = /\S/.test(content);
  // Handle API errors or empty content
  if (result?.errors?.length > 0 || !validString || isError) {
    let standardErrors = [];
    let liquidErrors = [];
    
    // Empty content errors are NOT from liquid endpoints, so they go to standardErrors
    if (!validString) {
      standardErrors = [emptyBodyError];
    }
    
    // IMPORTANT: Errors from extractTags and liquidValidation endpoints should ALWAYS be categorized as liquidErrors
    // These endpoints are: /extractTags and /ask-aira-service/creatives_ai/liquidValidation
    // Only errors from these endpoints should appear in Liquid Issues tab
    if (result && Array.isArray(result?.errors) && result.errors.length > 0) {
      // Errors from extractTags or liquidValidation endpoints
      liquidErrors = result.errors.map((error) => {
        const message = typeof error?.message === "string"
          ? error.message
          : somethingWrongMsg;
        return message;
      });
    } else if (isError) {
      // If isError is true, it means the API call to extractTags/liquidValidation failed
      // This is also a liquid endpoint error, so categorize as liquidErrors
      liquidErrors = [somethingWrongMsg];
    }
    
    onError({
      standardErrors,
      liquidErrors,
      tabType,
    });
    return false;
  }
  onSuccess(content, tabType);
  return true;
};

// Internal helper function to validate platform-specific content
export const _validatePlatformSpecificContent = async (
  androidContent,
  iosContent,
  channel,
  options // Contains parent's onError and other options for validateLiquidTemplateContent
) => {
  const {
    singleTab,
    onError: parentOnError, // The onError callback from the calling function (e.g., validateMobilePushContent)
    ...commonVltcOptions // Other options like getLiquidTags, formatMessage, messages, currentTab, etc.
  } = options;

  let isAndroidValid = true;
  let isIosValid = true;

  // This aggregator is passed to validateLiquidTemplateContent.
  // It accumulates errors in the new structure and calls the parentOnError
  const internalOnErrorAggregator = ({
    standardErrors = [],
    liquidErrors = [],
    tabType: tabTypeFromVLTC,
  }) => {

    aggregatedErrors.standardErrors[tabTypeFromVLTC?.toUpperCase() ?? ''].push(
      ...standardErrors
    );
    aggregatedErrors.liquidErrors[tabTypeFromVLTC?.toUpperCase() ?? ''].push(
      ...liquidErrors
    );
    parentOnError(aggregatedErrors);
  };

  // Base options for calling validateLiquidTemplateContent
  const vltcCallOptions = {
    ...commonVltcOptions,
    onError: internalOnErrorAggregator,
    onSuccess: () => {},
  };
  // Initialize error structure with platform-specific categories
  const aggregatedErrors = {
    standardErrors: {
      [ANDROID]: [],
      [IOS]: [],
      generic: [],
    },
    liquidErrors: {
      [ANDROID]: [],
      [IOS]: [],
      generic: [],
    },
  };

  if (androidContent && (singleTab === ANDROID || !singleTab)) {

    isAndroidValid = await validateLiquidTemplateContent(
      androidContent,
      { ...vltcCallOptions, tabType: ANDROID }
    );
  }

  if (iosContent && (singleTab === IOS || !singleTab)) {

    isIosValid = await validateLiquidTemplateContent(
      iosContent,
      { ...vltcCallOptions, tabType: IOS }
    );
  }
  //if singleTab is android, then validate only android content and make ios valid by default
  if (singleTab === ANDROID) {
    isIosValid = true;
  }
  //if singleTab is ios, then validate only ios content and make android valid by default
  if (singleTab === IOS) {
    isAndroidValid = true;
  }
  return isAndroidValid && isIosValid; // Overall success
};

/**
 * Validate Mobile Push content for both Android and iOS tabs
 * @param {object} formData - Form data containing Android and iOS content
 * @param {object} options - Options for validation (currentTab, onError, onSuccess, getLiquidTags, formatMessage, messages, singleTab).
 * @returns {Promise<boolean>} - Promise that resolves to true when validation succeeds, false otherwise
 */
export const validateMobilePushContent = async (formData, options) => {
  const {
    currentTab,
    onError, // This is the onError callback passed by the caller of validateMobilePushContent
    onSuccess, // This is the FINAL success callback for MobilePush
    ...restOptions // Options for validateLiquidTemplateContent (getLiquidTags, formatMessage, etc.)
  } = options;
  // Clear previous errors by calling the passed onError
  onError({ standardErrors: [], liquidErrors: [] });

  // For extractTags API: send plain template text (title + message), not the whole form as JSON.
  // OLD Mobile Push UI: Android = message-title, message-editor; iOS = message-title2, message-editor2.
  // New Mobile Push UI: both tabs use { title, message, buttons/ctas } — use extractContent().
  const rawAndroid = formData?.[0];
  const rawIos = formData?.[1];
  const isObject = (v) => v != null && typeof v === 'object' && !Array.isArray(v);
  const androidTab = isObject(rawAndroid) ? rawAndroid : {};
  const iosTab = isObject(rawIos) ? rawIos : {};
  const isOldUiShape = 'message-title' in androidTab || 'message-editor' in androidTab;
  let androidContentForValidation;
  let iosContentForValidation;
  if (isOldUiShape) {
    androidContentForValidation = [androidTab['message-title'], androidTab['message-editor']]
      .filter(Boolean)
      .join(' ');
    iosContentForValidation = [iosTab['message-title2'], iosTab['message-editor2']]
      .filter(Boolean)
      .join(' ');
  } else {
    androidContentForValidation = extractContent(androidTab);
    iosContentForValidation = extractContent(iosTab);
  }

  // Pass the original 'onError' from this function's arguments,
  // 'currentTab', and other relevant options to the helper.
  const overallSuccess = await _validatePlatformSpecificContent(
    androidContentForValidation,
    iosContentForValidation,
    MOBILE_PUSH,
    { ...restOptions, currentTab, onError }
  );

  // Submit payload remains full form data (JSON string) for save.
  const androidContentToSubmit = JSON.stringify(formData?.[0]);
  const iosContentToSubmit = JSON.stringify(formData?.[1]);
  const getContentToSubmit = () => {
    if (currentTab === 1 && androidContentToSubmit) return [androidContentToSubmit, ANDROID?.toLowerCase()];
    if (currentTab === 2 && iosContentToSubmit) return [iosContentToSubmit, IOS?.toLowerCase()];
    if (androidContentToSubmit) return [androidContentToSubmit, ANDROID?.toLowerCase()];
    if (iosContentToSubmit) return [iosContentToSubmit, IOS?.toLowerCase()];
    return ["", ""];
  };
  if (overallSuccess) {
    const [contentToSubmit, tabTypeToSubmit] = getContentToSubmit();
    // Call the FINAL onSuccess only ONCE here
    onSuccess(contentToSubmit, tabTypeToSubmit);
    return true;
  }
  return false;
};

// Helper function to extract content for a platform
export const extractContent = (platformData) => {
  if (!platformData) return '';
  const { title, message, ctas, isBEEeditor, beeHtml } = platformData;
  
  // For BEE editor, extract content from beeHtml
  if (isBEEeditor && beeHtml) {
    // beeHtml can be an object with value property or a string
    const beeHtmlContent = typeof beeHtml === 'string' ? beeHtml : (beeHtml?.value || '');
    return [
      title,
      beeHtmlContent,
      ...((ctas?.map((cta) => cta?.text || cta?.actionLink)) || []),
    ].filter(Boolean).join(' ');
  }
  
  // For regular content
  return [
    title,
    message,
    ...((ctas?.map((cta) => cta?.text || cta?.actionLink)) || []),
  ].filter(Boolean).join(' ');
};

/**
 * Validate INAPP content for both Android and iOS
 * @param {object} formData - Form data containing Android and iOS content
 * @param {object} options - Options for validation
 * @returns {Promise} - Promise that resolves when validation completes
 */
export const validateInAppContent = async (formData, options) => {
  const {
    onError, // This is the onError callback passed by the caller of validateInAppContent
    onSuccess, // FINAL success callback
    ...restOptions // Options for validateLiquidTemplateContent
  } = options;
  // Clear previous errors with new structure
  onError({
    standardErrors: {
      [ANDROID]: [],
      [IOS]: [],
      generic: [],
    },
    liquidErrors: {
      [ANDROID]: [],
      [IOS]: [],
      generic: [],
    },
  });

  let androidContent = "";
  let iosContent = "";
  let parseError = null;

  // Extract content
  try {

    const baseContent = formData?.versions?.base?.content;
    androidContent = extractContent(baseContent?.ANDROID);
    iosContent = extractContent(baseContent?.IOS);
  } catch (error) {
    parseError = error; // Capture parsing error
  }

  // Check if *any* content exists
  if (parseError) {
    onError((prevErrors) => ({
      ...prevErrors,
      standardErrors: {
        ...prevErrors.standardErrors,
        generic: [
          restOptions.formatMessage(restOptions.messages.somethingWentWrong),
        ],
      },
    }));
    return false;
  }

  // Pass the original 'onError' from this function's arguments
  // and other relevant options to the helper.
  const overallSuccess = await _validatePlatformSpecificContent(
    androidContent,
    iosContent,
    INAPP,
    { ...restOptions, onError }
  );

  if (overallSuccess) {
    // Call FINAL onSuccess ONCE
    onSuccess();
    return true;
  }
  // Errors already reported via the 'onError' callback passed to _validatePlatformSpecificContent
  return false;
};

/**
 * Validate carousel cards for errors
 * Checks each card for body errors, missing text, missing media, and unsaved buttons
 *
 * @param {Array} carouselData - Array of carousel card objects
 * @param {string} mediaType - Media type ('image' or 'video', case-insensitive)
 * @param {Object} options - Optional configuration
 * @param {string} options.imageConstant - Constant for image media type (default: 'IMAGE')
 * @param {string} options.videoConstant - Constant for video media type (default: 'VIDEO')
 * @returns {Object} Object containing validation results: { isValid: boolean, reasons: string[] }
 */
export const validateCarouselCards = (
  carouselData = [],
  mediaType = '',
  options = {}
) => {
  const {
    imageConstant = 'IMAGE',
    videoConstant = 'VIDEO',
  } = options;

  const reasons = [];
  const normalizedMediaType = mediaType?.toLowerCase() || '';
  const normalizedImageType = imageConstant?.toLowerCase() || '';
  const normalizedVideoType = videoConstant?.toLowerCase() || '';

  carouselData?.forEach((card, idx) => {
    // Check for body errors
    if (card?.bodyError) {
      reasons.push(`card ${idx + 1}: bodyError=${card.bodyError}`);
    }

    // Check for empty body text
    if (!card?.bodyText) {
      reasons.push(`card ${idx + 1}: bodyText empty`);
    }

    // Check for missing image source when media type is image
    if (normalizedMediaType === normalizedImageType && !card?.imageSrc) {
      reasons.push(`card ${idx + 1}: imageSrc missing`);
    }

    // Check for missing video source when media type is video
    if (normalizedMediaType === normalizedVideoType && !card?.videoSrc) {
      reasons.push(`card ${idx + 1}: videoSrc missing`);
    }

    // Check if all buttons are saved
    if (card?.buttons && !card.buttons.every((b) => b?.isSaved === true)) {
      reasons.push(`card ${idx + 1}: some buttons not saved`);
    }
  });

  return {
    isValid: reasons.length === 0,
    reasons,
  };
};

export const hasPersonalizationTags = (text = '') =>
  (text && ((text.includes('{{') && text.includes('}}')) || (text.includes('[') && text.includes(']'))));

export const getMessageForDevice = (templateData, device) => templateData?.versions?.[device]?.base?.expandableDetails?.message;

export const getTitleForDevice = (templateData, device) => templateData?.versions?.[device]?.base?.title || '';

export const checkForPersonalizationTokens = (formData) => {
  // Check for {{ }} (liquid tags) and [ ] (event context tags) in mobile push content
  const tokenRegex = /\{\{[\s\S]*?\}\}|\[[\s\S]*?\]/;

  // Check all tabs/versions for personalization tokens
  if (formData && typeof formData === 'object') {
    for (const key in formData) {
      const tabData = formData[key];
      if (tabData && typeof tabData === 'object') {
        for (const fieldKey in tabData) {
          const fieldValue = tabData[fieldKey];
          if (typeof fieldValue === 'string' && tokenRegex.test(fieldValue)) {
            return true;
          }
        }
      }
    }
  }
  return false;
};

export const isValidEmail = (email) => EMAIL_REGEX.test(email);
export const isValidMobile = (mobile) => PHONE_REGEX.test(mobile);

export const formatPhoneNumber = (phone) => {
  if (!phone) return '';
  return String(phone).replace(/[^\d]/g, '');
};