import cloneDeep from 'lodash/cloneDeep';
import { getMediaDetails } from '../services/api';
import { WHATSAPP } from '../v2Containers/Whatsapp/constants';

// Enum-like constants to avoid magic strings
export const MEDIA_CONTENT_TYPE = {
  MIXED: 'mixed',
  TAGS: 'tags',
  URLS: 'urls',
  NONE: 'none',
};

export const TRANSFORM_DIRECTION = {
  FORWARD: 'forward',
  REVERSE: 'reverse',
  SMART: 'smart',
};

/**
 * Helper function to extract media ID from URL patterns
 * @param {string} url - The media URL to extract ID from
 * @returns {string|null} - Extracted media ID or null if not found
 */
function extractMediaIdFromUrl(url) {
  if (!url || typeof url !== 'string') {
    return null;
  }


  // Already contains media_content pattern - extract the ID
  const mediaContentMatch = url.match(/\{\{media_content\(([^)]+)\)\}\}/);
  if (mediaContentMatch) {
    return mediaContentMatch[1];
  }

  return null;
}

/**
 * Helper function to detect if template config contains media_content tags or URLs
 * @param {object} templateConfig The template configuration to analyze
 * @returns {string} MEDIA_CONTENT_TYPE.TAGS if contains media_content tags, MEDIA_CONTENT_TYPE.URLS if contains URLs, MEDIA_CONTENT_TYPE.MIXED if both, MEDIA_CONTENT_TYPE.NONE if neither
 */
function detectMediaContentType(templateConfig) {
  if (!templateConfig?.cards?.length) {
    return MEDIA_CONTENT_TYPE.NONE;
  }

  let hasUrls = false;
  let hasTags = false;

  templateConfig.cards.forEach(card => {
    if (card?.media?.url) {
      const url = card.media.url;
      if (extractMediaIdFromTag(url)) {
        hasTags = true;
      } else if (extractMediaIdFromUrl(url)) {
        hasUrls = true;
      } else {
        // Regular URL that doesn't contain extractable media ID
        hasUrls = true;
      }
    }
  });

  if (hasUrls && hasTags) return MEDIA_CONTENT_TYPE.MIXED;
  if (hasTags) return MEDIA_CONTENT_TYPE.TAGS;
  if (hasUrls) return MEDIA_CONTENT_TYPE.URLS;
  return MEDIA_CONTENT_TYPE.NONE;
}

/**
 * Smart bidirectional transformation function that automatically detects and applies the correct transformation.
 * This is the recommended function to use when you have a media details ID.
 *
 * AUTOMATIC DETECTION:
 * - If template contains URLs → converts to {{media_content(id)}} tags
 * - If template contains {{media_content(id)}} tags → converts to URLs
 * - If template contains mixed content → applies appropriate transformation per card
 *
 * @param {object} templateConfig The template configuration to transform.
 * @param {string} channel The channel for which to transform the config.
 * @param {string} mediaDetailsId The ID to use when calling getMediaDetails API.
 * @param {object} options Additional options for the transformation.
 * @param {string} options.forceDirection Force transformation direction: 'forward' (URLs→tags) or 'reverse' (tags→URLs).
 * @returns {Promise<object>} Promise that resolves to the transformed template configuration.
 */
export async function transformTemplateConfigWithMediaDetails(templateConfig, channel, mediaDetailsId, options = {}) {
  if (channel !== WHATSAPP || !templateConfig?.cards?.length) {
    return templateConfig;
  }

  if (!mediaDetailsId) {
    console.warn('mediaDetailsId is required for transformTemplateConfigWithMediaDetails');
    return templateConfig;
  }

  const { forceDirection = null } = options;

  // Detect what type of content we have
  const contentType = detectMediaContentType(templateConfig);

  if (contentType === MEDIA_CONTENT_TYPE.NONE) {
    return templateConfig;
  }

  // Determine transformation direction
  let transformDirection;
  if (forceDirection) {
    transformDirection = forceDirection;
  } else {
    // Auto-detect based on content
    if (contentType === MEDIA_CONTENT_TYPE.URLS) {
      transformDirection = TRANSFORM_DIRECTION.FORWARD; // URLs → tags
    } else if (contentType === MEDIA_CONTENT_TYPE.TAGS) {
      transformDirection = TRANSFORM_DIRECTION.REVERSE; // tags → URLs
    } else if (contentType === MEDIA_CONTENT_TYPE.MIXED) {
      transformDirection = TRANSFORM_DIRECTION.SMART; // Handle mixed content intelligently
    }
  }

  const newConfig = cloneDeep(templateConfig);
  try {

    // Fetch media details mapping from API
    const response = await getMediaDetails({ id: mediaDetailsId })

    // Extract the URL-to-ID mapping from the API response
    const urlToIdMapping = response?.response || {};

    if (Object.keys(urlToIdMapping).length === 0) {
      console.warn('No media details mapping found in API response');
      return newConfig;
    }

    // Create reverse mapping: ID -> URL (for reverse transformations)
    const idToUrlMapping = {};
    Object.entries(urlToIdMapping).forEach(([url, mediaId]) => {
      idToUrlMapping[mediaId] = url;
    });


    // Apply transformations based on direction
    newConfig?.cards?.forEach(card => {
      if (card?.media && card?.media?.url) {
        const currentUrl = card.media.url;

        if (transformDirection === TRANSFORM_DIRECTION.FORWARD ||
           (transformDirection === TRANSFORM_DIRECTION.SMART && !extractMediaIdFromTag(currentUrl))) {
          // Forward transformation: URL → tag
          const mediaDetailId = urlToIdMapping[currentUrl];
          if (mediaDetailId) {
            card.media.url = `{{media_content(${mediaDetailId})}}`;
          } else {
            console.warn(`No media detail ID found for URL: ${currentUrl}`);
          }
        } else if (transformDirection === TRANSFORM_DIRECTION.REVERSE ||
                  (transformDirection === TRANSFORM_DIRECTION.SMART && extractMediaIdFromTag(currentUrl))) {
          // Reverse transformation: tag → URL
          const mediaId = extractMediaIdFromTag(currentUrl);
          if (mediaId) {
            const actualUrl = idToUrlMapping[mediaId];
            if (actualUrl) {
              card.media.url = actualUrl;
            } else {
              console.warn(`No URL found for media ID: ${mediaId}`);
            }
          }
        }
      }
    });

    return newConfig;

  } catch (error) {
    console.error('Failed to fetch media details for transformation:', error);

    // Fallback: try to extract/convert what we can without API
    newConfig.cards.forEach(card => {
      if (card.media && card.media.url) {
        if (transformDirection === TRANSFORM_DIRECTION.FORWARD) {
          const extractedId = extractMediaIdFromUrl(card.media.url);
          if (extractedId) {
            card.media.url = `{{media_content(${extractedId})}}`;
          }
        }
        // For reverse transformation, we can't do much without the API mapping
      }
    });

    // cleanup the newConfig
    delete newConfig.accessToken;

    return newConfig;
  }
}

/**
 * Helper function to extract media ID from media_content tags
 * @param {string} url - The URL containing media_content tag
 * @returns {string|null} - Extracted media ID or null if not found
 */
function extractMediaIdFromTag(url) {
  if (!url || typeof url !== 'string') {
    return null;
  }

  // Extract media ID from {{media_content(id)}} pattern
  const tagMatch = url.match(/\{\{media_content\(([^)]+)\)\}\}/);
  return tagMatch ? tagMatch[1] : null;
}

/**
 * Convenience function for reverse transformation: fetches media details and converts tags to URLs in one call.
 * This function forces reverse transformation direction. For automatic detection, use transformTemplateConfigWithMediaDetails.
 * @param {object} templateConfig The template configuration containing media_content tags.
 * @param {string} channel The channel for which to transform the config.
 * @param {string} mediaDetailsId The ID to use when calling getMediaDetails API.
 * @param {object} options Additional options for the transformation.
 * @returns {Promise<object>} Promise that resolves to the template config with actual URLs.
 */
export async function convertMediaTagsToUrls(templateConfig, channel, mediaDetailsId, options = {}) {
  return transformTemplateConfigWithMediaDetails(templateConfig, channel, mediaDetailsId, {
    ...options,
    forceDirection: TRANSFORM_DIRECTION.REVERSE
  });
}

/**
 * Convenience function for forward transformation: fetches media details and converts URLs to tags in one call.
 * This function forces forward transformation direction. For automatic detection, use transformTemplateConfigWithMediaDetails.
 * @param {object} templateConfig The template configuration containing URLs.
 * @param {string} channel The channel for which to transform the config.
 * @param {string} mediaDetailsId The ID to use when calling getMediaDetails API.
 * @param {object} options Additional options for the transformation.
 * @returns {Promise<object>} Promise that resolves to the template config with media_content tags.
 */
export async function convertUrlsToMediaTags(templateConfig, channel, mediaDetailsId, options = {}) {
  return transformTemplateConfigWithMediaDetails(templateConfig, channel, mediaDetailsId, {
    ...options,
    forceDirection: TRANSFORM_DIRECTION.FORWARD
  });
}
