/**
 * Clean WordPress/Elementor content and convert to styled React components
 */

import Image from 'next/image';
import React, { ReactNode } from 'react';
import { cleanHtmlEntities, getImagePath, getImageAlt, ImageMapping } from '@/lib/wordpress-content';
import { getAllLocations } from './location-data';
import { Card, CardContent } from '@/components/ui/card';
import { VendingMachineCard } from '@/components/vending-machine-card';
import { ImageCarousel } from '@/components/image-carousel';

interface CleanContentOptions {
  imageMapping?: ImageMapping;
  pageTitle?: string; // Page title to check for duplicates
  prioritizeFirstImage?: boolean;
}

/**
 * Clean and convert WordPress Elementor HTML to styled React components
 */
export function cleanWordPressContent(
  html: string,
  options: CleanContentOptions = {}
): ReactNode[] {
  if (!html || typeof html !== 'string') {
    return [];
  }

  const { imageMapping = {}, pageTitle, prioritizeFirstImage = false } = options;
  const components: ReactNode[] = [];
  let hasPrioritizedImage = false;

  try {
    // Update location links to new format (currently just returns HTML unchanged)
    // TODO: If location links need updating in the future, implement URL pattern matching here
    // For example, convert old WordPress URLs to new Next.js route format
    // Example: /vending-machines/salt-lake-city/ -> /vending-machines-salt-lake-city-utah
    const htmlWithUpdatedLinks = html;
    
    // Remove Elementor wrapper and data attributes
    let cleaned = htmlWithUpdatedLinks
      // Remove Elementor wrapper div
      .replace(/<div[^>]*data-elementor-type[^>]*>/gi, '')
      .replace(/<\/div>\s*$/, '')
      // Remove all Elementor data attributes
      .replace(/\s+data-[^=]*="[^"]*"/gi, '')
      // Remove Elementor-specific classes but keep useful ones
      .replace(/\s+class="elementor[^"]*"/gi, '')
      .replace(/\s+class="ekit[^"]*"/gi, '')
      // Remove SVG decorative shapes
      .replace(/<svg[^>]*>[\s\S]*?<\/svg>/gi, '')
      // Remove empty divs
      .replace(/<div[^>]*>\s*<\/div>/gi, '');

    // Extract sections (Elementor sections become our sections)
    const sectionRegex = /<section[^>]*>([\s\S]*?)<\/section>/gi;
    let sectionMatch;
    const sections: string[] = [];

    while ((sectionMatch = sectionRegex.exec(cleaned)) !== null) {
      sections.push(sectionMatch[1]);
    }

    // If no sections found, treat entire content as one section
    if (sections.length === 0) {
      sections.push(cleaned);
    }

    sections.forEach((sectionHtml, sectionIndex) => {
      const sectionComponents: ReactNode[] = [];

      // Extract funfact widgets BEFORE cleaning (they contain SVG icons and special structure)
      const funfactRegex = /<div[^>]*elementor-widget-elementskit-funfact[^>]*>([\s\S]*?)<\/div>\s*<\/div>\s*<\/div>/gi;
      const funfacts: Array<{ number: string; title: string; index: number }> = [];
      let funfactMatch;
      
      funfactRegex.lastIndex = 0;
      while ((funfactMatch = funfactRegex.exec(sectionHtml)) !== null) {
        const funfactHtml = funfactMatch[0];
        // Extract text content (remove HTML tags and SVG)
        let text = funfactHtml.replace(/<svg[^>]*>[\s\S]*?<\/svg>/gi, '');
        text = text.replace(/<[^>]+>/g, ' ');
        text = text.replace(/\s+/g, ' ').trim();
        
        // Try to find number and title patterns
        // Funfacts typically have format: "NUMBER TITLE" or just text
        const parts = text.split(/\s+/);
        let number = '';
        let title = '';
        
        // Check if first part is a number
        if (parts.length > 0 && /^\d+[+\-]?$/.test(parts[0])) {
          number = parts[0];
          title = parts.slice(1).join(' ');
        } else {
          // Try to extract from HTML structure
          const numberMatch = funfactHtml.match(/funfact-number[^>]*>([^<]+)</i);
          const titleMatch = funfactHtml.match(/funfact-title[^>]*>([^<]+)</i);
          number = numberMatch ? numberMatch[1].trim() : '';
          title = titleMatch ? titleMatch[1].trim() : text;
        }
        
        if (text) {
          funfacts.push({
            number: number || text.split(' ')[0] || '',
            title: title || text.substring(number.length).trim() || text,
            index: funfactMatch.index
          });
        }
      }

      // Extract and process headings
      const headingRegex = /<h([1-6])[^>]*>(.*?)<\/h[1-6]>/gi;
      let headingMatch;
      const headings: Array<{ level: number; content: string; index: number }> = [];
      let isFirstHeading = true;
      
      // Helper function to check if headings are similar (for duplicate detection)
      const areHeadingsSimilar = (heading1: string, heading2: string): boolean => {
        const h1 = heading1.trim().toLowerCase();
        const h2 = heading2.trim().toLowerCase();
        
        // Exact match
        if (h1 === h2) return true;
        
        // Check if one contains the other
        if (h1.includes(h2) || h2.includes(h1)) {
          const shorter = h1.length < h2.length ? h1 : h2;
          const longer = h1.length >= h2.length ? h1 : h2;
          
          // If shorter is at least 60% of longer, consider similar
          if (shorter.length / longer.length >= 0.6) {
            return true;
          }
          
          // If shorter is a single word and appears as a word (not substring) in longer, consider similar
          // This catches cases like "Reviews" in "Rocky Mountain Vending: Reviews & Testimonials"
          if (shorter.split(/\s+/).length === 1) {
            // Check if it appears as a whole word (with word boundaries)
            const wordRegex = new RegExp(`\\b${shorter.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`, 'i');
            if (wordRegex.test(longer)) {
              return true;
            }
          }
          
          // If shorter is multiple words and all words appear in longer, consider similar
          const shorterWords = shorter.split(/\s+/).filter(w => w.length > 2); // Filter out short words like "a", "an", "the"
          if (shorterWords.length >= 2) {
            const allWordsMatch = shorterWords.every(word => {
              const wordRegex = new RegExp(`\\b${word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`, 'i');
              return wordRegex.test(longer);
            });
            if (allWordsMatch) {
              return true;
            }
          }
        }
        
        // Check if they start with the same words (for cases where one is a longer version)
        const h1Words = h1.split(/\s+/).slice(0, 3); // First 3 words
        const h2Words = h2.split(/\s+/).slice(0, 3);
        if (h1Words.length >= 2 && h2Words.length >= 2) {
          // Check if first 2 words match
          if (h1Words[0] === h2Words[0] && h1Words[1] === h2Words[1]) {
            return true;
          }
        }
        
        return false;
      };
      
      headingRegex.lastIndex = 0;
      while ((headingMatch = headingRegex.exec(sectionHtml)) !== null) {
        const headingContent = cleanHtmlEntities(headingMatch[2]);
        const headingLevel = parseInt(headingMatch[1]);
        
        // Skip heading if:
        // 1. It's the first heading and matches the page title, OR
        // 2. It's an h1 that matches the page title (h1 should only be used for page title)
        if (pageTitle) {
          if (areHeadingsSimilar(headingContent, pageTitle)) {
            // Skip if it's the first heading, or if it's an h1 (h1 should only be page title)
            if (isFirstHeading || headingLevel === 1) {
              isFirstHeading = false;
              continue;
            }
          }
        }
        
        headings.push({
          level: headingLevel,
          content: headingContent,
          index: headingMatch.index
        });
        isFirstHeading = false;
      }

      // Check for slider/carousel widgets first (like elementskit-client-logo)
      // Look for the widget container that has elementskit-client-logo - match the entire widget including nested divs
      const sliderWidgetRegex = /<div[^>]*elementor-widget-elementskit-client-logo[^>]*>([\s\S]*?)(?:<\/div>\s*){3,}/gi;
      let sliderMatch = sliderWidgetRegex.exec(sectionHtml);
      
      // Also try to find the slider div directly with the comment
      if (!sliderMatch) {
        const sliderDivRegex = /<div[^>]*elementskit-clients-slider[^>]*>([\s\S]*?)<!--\s*\.elementskit-clients-slider\s+END\s*-->/gi;
        sliderMatch = sliderDivRegex.exec(sectionHtml);
      }
      
      // Try a simpler approach - find any div with swiper-wrapper
      if (!sliderMatch) {
        const swiperWrapperRegex = /<div[^>]*swiper-wrapper[^>]*>([\s\S]*?)<\/div>\s*<\/div>/gi;
        sliderMatch = swiperWrapperRegex.exec(sectionHtml);
      }
      
      let sliderImages: Array<{ src: string; alt: string; width?: number; height?: number; title?: string }> = [];
      let sliderIndex: number | null = null;
      
      if (sliderMatch) {
        sliderIndex = sliderMatch.index;
        const sliderContent = sliderMatch[1];
        // Extract all images from the slider - look in swiper-slide divs
        const slideRegex = /<div[^>]*swiper-slide[^>]*>([\s\S]*?)<\/div>\s*<\/div>/gi;
        let slideMatch;
        
        slideRegex.lastIndex = 0;
        while ((slideMatch = slideRegex.exec(sliderContent)) !== null) {
          const slideContent = slideMatch[1];
          const imgMatch = slideContent.match(/<img([^>]*)>/i);
          
          if (imgMatch) {
            const imgTag = imgMatch[0];
            const srcMatch = imgTag.match(/src=["']([^"']+)["']/i);
            const altMatch = imgTag.match(/alt=["']([^"']*)["']/i);
            const titleMatch = slideContent.match(/title=["']([^"']*)["']/i) || imgTag.match(/title=["']([^"']*)["']/i);
            const widthMatch = imgTag.match(/width=["']?(\d+)["']?/i);
            const heightMatch = imgTag.match(/height=["']?(\d+)["']?/i);

            if (srcMatch) {
              // Fix malformed URLs (e.g., https:///wp-content -> https://rockymountainvending.com/wp-content)
              let imageSrc = srcMatch[1];
              if (imageSrc.startsWith('https:///') || imageSrc.startsWith('http:///')) {
                imageSrc = imageSrc.replace(/^https?:\/\//, 'https://rockymountainvending.com/');
              } else if (imageSrc.startsWith('https://wp-content') || imageSrc.startsWith('http://wp-content')) {
                imageSrc = imageSrc.replace(/^https?:\/\/wp-content/, 'https://rockymountainvending.com/wp-content');
              }
              
              sliderImages.push({
                src: imageSrc,
                alt: altMatch ? cleanHtmlEntities(altMatch[1]) : (titleMatch ? cleanHtmlEntities(titleMatch[1]) : ''),
                width: widthMatch ? parseInt(widthMatch[1]) : undefined,
                height: heightMatch ? parseInt(heightMatch[1]) : undefined,
                title: titleMatch ? cleanHtmlEntities(titleMatch[1]) : undefined
              });
            }
          }
        }
        
        // If no slides found, try direct image extraction from slider content
        if (sliderImages.length === 0) {
          const sliderImageRegex = /<img([^>]*)>/gi;
          let sliderImgMatch;
          
          sliderImageRegex.lastIndex = 0;
          while ((sliderImgMatch = sliderImageRegex.exec(sliderContent)) !== null) {
            const imgTag = sliderImgMatch[0];
            const srcMatch = imgTag.match(/src=["']([^"']+)["']/i);
            const altMatch = imgTag.match(/alt=["']([^"']*)["']/i);
            const titleMatch = imgTag.match(/title=["']([^"']*)["']/i);
            const widthMatch = imgTag.match(/width=["']?(\d+)["']?/i);
            const heightMatch = imgTag.match(/height=["']?(\d+)["']?/i);
            
            if (srcMatch) {
              // Fix malformed URLs (e.g., https:///wp-content -> https://rockymountainvending.com/wp-content)
              let imageSrc = srcMatch[1];
              if (imageSrc.startsWith('https:///') || imageSrc.startsWith('http:///')) {
                imageSrc = imageSrc.replace(/^https?:\/\//, 'https://rockymountainvending.com/');
              } else if (imageSrc.startsWith('https://wp-content') || imageSrc.startsWith('http://wp-content')) {
                imageSrc = imageSrc.replace(/^https?:\/\/wp-content/, 'https://rockymountainvending.com/wp-content');
              }
              
              sliderImages.push({
                src: imageSrc,
                alt: altMatch ? cleanHtmlEntities(altMatch[1]) : (titleMatch ? cleanHtmlEntities(titleMatch[1]) : ''),
                width: widthMatch ? parseInt(widthMatch[1]) : undefined,
                height: heightMatch ? parseInt(heightMatch[1]) : undefined,
                title: titleMatch ? cleanHtmlEntities(titleMatch[1]) : undefined
              });
            }
          }
        }
      }

      // Extract Elementor gallery widget items (e.g., repairs page image grid)
      const galleryImages: Array<{ src: string; alt: string; width?: number; height?: number; index: number }> = [];
      const galleryImageRegex = /<div[^>]*class="[^"]*e-gallery-image[^"]*"[^>]*data-thumbnail="([^"]+)"[^>]*data-width="(\d+)"[^>]*data-height="(\d+)"[^>]*aria-label="([^"]*)"[^>]*>/gi;
      let galleryMatch;

      galleryImageRegex.lastIndex = 0;
      while ((galleryMatch = galleryImageRegex.exec(sectionHtml)) !== null) {
        let imageSrc = galleryMatch[1];

        // Fix malformed URLs (e.g., https:///wp-content -> https://rockymountainvending.com/wp-content)
        if (imageSrc.startsWith('https:///') || imageSrc.startsWith('http:///')) {
          imageSrc = imageSrc.replace(/^https?:\/\//, 'https://rockymountainvending.com/');
        } else if (imageSrc.startsWith('https://wp-content') || imageSrc.startsWith('http://wp-content')) {
          imageSrc = imageSrc.replace(
            /^https?:\/\/wp-content/,
            'https://rockymountainvending.com/wp-content'
          );
        }

        const width = parseInt(galleryMatch[2], 10);
        const height = parseInt(galleryMatch[3], 10);
        const alt = cleanHtmlEntities(galleryMatch[4] || '');

        galleryImages.push({
          src: imageSrc,
          alt,
          width: Number.isNaN(width) ? undefined : width,
          height: Number.isNaN(height) ? undefined : height,
          index: galleryMatch.index
        });
      }

      // Extract and process regular images (excluding slider images)
      const imageRegex = /<img([^>]*)>/gi;
      const images: Array<{ src: string; alt: string; width?: number; height?: number; index: number }> = [];
      let imageMatch;

      imageRegex.lastIndex = 0;
      while ((imageMatch = imageRegex.exec(sectionHtml)) !== null) {
        // Skip if this image is part of the slider
        if (sliderIndex !== null && imageMatch.index >= sliderIndex && imageMatch.index < sliderIndex + sliderMatch![0].length) {
          continue;
        }
        
        const imgTag = imageMatch[0];
        const srcMatch = imgTag.match(/src=["']([^"']+)["']/i);
        const altMatch = imgTag.match(/alt=["']([^"']*)["']/i);
        const widthMatch = imgTag.match(/width=["']?(\d+)["']?/i);
        const heightMatch = imgTag.match(/height=["']?(\d+)["']?/i);
      
        if (srcMatch) {
          // Fix malformed URLs (e.g., https:///wp-content -> https://rockymountainvending.com/wp-content)
          let imageSrc = srcMatch[1];
          if (imageSrc.startsWith('https:///') || imageSrc.startsWith('http:///')) {
            imageSrc = imageSrc.replace(/^https?:\/\//, 'https://rockymountainvending.com/');
          } else if (imageSrc.startsWith('https://wp-content') || imageSrc.startsWith('http://wp-content')) {
            imageSrc = imageSrc.replace(/^https?:\/\/wp-content/, 'https://rockymountainvending.com/wp-content');
          }
          // Fix specific auto-repair image URL
          if (imageSrc.includes('Vending-Machine-at-an-Auto-Repair-Facility') && !imageSrc.includes('rockymountainvending.com')) {
            imageSrc = 'https://rockymountainvending.com/wp-content/uploads/2024/01/Vending-Machine-at-an-Auto-Repair-Facility-768x1024.webp';
          }
          
          images.push({
            src: imageSrc,
            alt: altMatch ? cleanHtmlEntities(altMatch[1]) : '',
            width: widthMatch ? parseInt(widthMatch[1]) : undefined,
            height: heightMatch ? parseInt(heightMatch[1]) : undefined,
            index: imageMatch.index
          });
        }
      }

      // Extract paragraphs
      const paragraphRegex = /<p[^>]*>(.*?)<\/p>/gi;
      const paragraphs: Array<{ content: string; index: number; hasList: boolean }> = [];
      let paraMatch;

      paragraphRegex.lastIndex = 0;
      while ((paraMatch = paragraphRegex.exec(sectionHtml)) !== null) {
        const content = paraMatch[1];
        const hasList = /<(ul|ol)[^>]*>/i.test(content);
        const cleanContent = cleanHtmlEntities(content).trim();
        
        if (cleanContent.length > 0) {
          paragraphs.push({
            content: cleanContent,
            index: paraMatch.index,
            hasList
          });
        }
      }

      // Extract lists - handle nested structures better
      // First try to find lists at the top level
      const listRegex = /<(ul|ol)[^>]*>([\s\S]*?)<\/\1>/gi;
      const lists: Array<{ listType: 'ul' | 'ol'; items: Array<{ text: string; html: string }>; index: number }> = [];
      let listMatch;

      // Reset regex lastIndex
      listRegex.lastIndex = 0;
      while ((listMatch = listRegex.exec(sectionHtml)) !== null) {
        const listType = listMatch[1] as 'ul' | 'ol';
        const listContent = listMatch[2];
        const itemRegex = /<li[^>]*>(.*?)<\/li>/gi;
        const items: Array<{ text: string; html: string }> = [];
        let itemMatch;

        // Reset item regex
        itemRegex.lastIndex = 0;
        while ((itemMatch = itemRegex.exec(listContent)) !== null) {
          const itemHtml = itemMatch[1];
          // Clean HTML entities but preserve basic formatting
          const cleanText = cleanHtmlEntities(itemHtml);
          items.push({
            text: cleanText,
            html: itemHtml // Keep original HTML for processing
          });
        }

        if (items.length > 0) {
          lists.push({
            listType: listType,
            items,
            index: listMatch.index
          });
        }
      }
      
      // If no lists found at top level, try to find them in paragraphs (they might be nested)
      if (lists.length === 0) {
        // Look for lists inside paragraph content - need to use original HTML, not cleaned
        const paragraphRegexOriginal = /<p[^>]*>(.*?)<\/p>/gi;
        let paraMatchOriginal;
        
        paragraphRegexOriginal.lastIndex = 0;
        while ((paraMatchOriginal = paragraphRegexOriginal.exec(sectionHtml)) !== null) {
          const paraContent = paraMatchOriginal[1];
          const paraListRegex = /<(ul|ol)[^>]*>([\s\S]*?)<\/\1>/gi;
          let paraListMatch;
          
          paraListRegex.lastIndex = 0;
          while ((paraListMatch = paraListRegex.exec(paraContent)) !== null) {
            const listType = paraListMatch[1] as 'ul' | 'ol';
            const listContent = paraListMatch[2];
            const itemRegex = /<li[^>]*>(.*?)<\/li>/gi;
            const items: Array<{ text: string; html: string }> = [];
            let itemMatch;

            itemRegex.lastIndex = 0;
            while ((itemMatch = itemRegex.exec(listContent)) !== null) {
              const itemHtml = itemMatch[1];
              items.push({
                text: cleanHtmlEntities(itemHtml),
                html: itemHtml
              });
            }

            if (items.length > 0) {
              lists.push({
                listType: listType,
                items,
                index: paraMatchOriginal.index + (paraListMatch.index || 0)
              });
            }
          }
        }
      }

      // Group images that should be side-by-side (images close together in same section)
      const imageGroups: Array<Array<typeof images[0] & { type: 'image' }>> = [];
      const processedImageIndices = new Set<number>();
      
      images.forEach((img, idx) => {
        if (processedImageIndices.has(idx)) return;
        
        // Check if this image is in a column layout
        const imgContext = sectionHtml.substring(
          Math.max(0, img.index - 2000),
          Math.min(sectionHtml.length, img.index + 2000)
        );
        const isInColumn = /elementor-col-(33|50|66|25|75)/i.test(imgContext);
        
        const group = [img];
        processedImageIndices.add(idx);
        
        // Find other images close to this one (within 2000 chars)
        images.forEach((otherImg, otherIdx) => {
          if (otherIdx !== idx && !processedImageIndices.has(otherIdx)) {
            const distance = Math.abs(otherImg.index - img.index);
            
            // Check if they're in the same section (no section break between them)
            const betweenContent = sectionHtml.substring(
              Math.min(img.index, otherImg.index),
              Math.max(img.index, otherImg.index)
            );
            const hasSectionBreak = /<\/section>/i.test(betweenContent);
            
            if (distance < 2000 && !hasSectionBreak) {
              // If first image is in a column, check if second is too
              if (isInColumn) {
                const otherContext = sectionHtml.substring(
                  Math.max(0, otherImg.index - 2000),
                  Math.min(sectionHtml.length, otherImg.index + 2000)
                );
                const otherIsInColumn = /elementor-col-(33|50|66|25|75)/i.test(otherContext);
                
                if (otherIsInColumn) {
                  group.push(otherImg);
                  processedImageIndices.add(otherIdx);
                }
              } else {
                // If first image is not in column, group any nearby images (for general side-by-side)
                group.push(otherImg);
                processedImageIndices.add(otherIdx);
              }
            }
          }
        });
        
        // Only create group if there are 2+ images
        if (group.length > 1) {
          imageGroups.push(group.map(img => ({ ...img, type: 'image' as const })));
        } else {
          // Single image, don't group
          processedImageIndices.delete(idx);
        }
      });
      
      // Check if this section should have machine cards (detect "Vending Machines for Gyms" pattern)
      let shouldShowMachineCards = false;
      let machineCardsHeadingIndex: number | null = null;
      let machineCardsParagraphIndex: number | null = null;
      
      // Look for heading "Vending Machines for Gyms" or similar patterns
      // Also match "Vending Machines We Use for..." variations
      const gymMachinesHeading = headings.find(h => {
        const cleanHeading = cleanHtmlEntities(h.content.replace(/<[^>]+>/g, '')).toLowerCase();
        return (cleanHeading.includes('vending machines for') || 
                cleanHeading.includes('vending machines we use')) && 
               (cleanHeading.includes('gym') || cleanHeading.includes('studio') || 
                cleanHeading.includes('community') || cleanHeading.includes('dance') || 
                cleanHeading.includes('car wash'));
      });
      
      if (gymMachinesHeading) {
        machineCardsHeadingIndex = gymMachinesHeading.index;
        // Look for paragraph about machines - more flexible pattern matching
        const gymMachinesParagraph = paragraphs.find(p => {
          const cleanPara = cleanHtmlEntities(p.content.replace(/<[^>]+>/g, '')).toLowerCase();
          // Match various patterns:
          // - "Many of our [gyms/studios/community centers/dance studios/car washes]"
          // - "Primarily we will install"
          // - "Many of our dance studios have just one"
          // - "Many of our community centers have many machines"
          // - "We offer vending machines that are perfectly suited"
          // - Any paragraph that mentions QFV, AMS, Crane, USI, or Seaga machines
          return (cleanPara.includes('many of our') && 
                  (cleanPara.includes('gym') || cleanPara.includes('studio') || 
                   cleanPara.includes('community') || cleanPara.includes('dance') ||
                   cleanPara.includes('car wash'))) ||
                 cleanPara.includes('primarily we will install') ||
                 (cleanPara.includes('many of our') && cleanPara.includes('vending machine')) ||
                 (cleanPara.includes('we offer vending machines') && 
                  (cleanPara.includes('car wash') || cleanPara.includes('location'))) ||
                 (cleanPara.includes('qfv') || cleanPara.includes('ams') || 
                  cleanPara.includes('crane') || cleanPara.includes('usi') || 
                  cleanPara.includes('seaga'));
        });
        
        if (gymMachinesParagraph) {
          machineCardsParagraphIndex = gymMachinesParagraph.index;
          shouldShowMachineCards = true;
        }
      }
      
      // Machine data from machines-we-use page - QFV 50 should always be first
      const gymMachines = [
        {
          name: "QFV 50 Combo",
          description: "The Ultimate Combo Machine: The QFV 50 stands out as our top combo machine, offering a remarkable blend of style and functionality. With 30 customizable drink selections, it caters to a variety of tastes and preferences.",
          image: "/images/wordpress/EH0A1551-HDR.webp",
          alt: "Quick Fresh Vending QFV 50 combo vending machine showcasing dual compartments for snacks and drinks, with dimensions and payment system details.",
          selections: 50,
          items: 300,
        },
        {
          name: "Crane Bev Max 4",
          description: "A Beverage Powerhouse: Bev Max 4 is a testament to efficiency in the vending world, boasting an impressive 48 drink selections. Its standout feature is the incredibly low fault rate of just 0.003%.",
          image: "/images/wordpress/Crane-Bev-Max-4-Drink.webp",
          alt: "Crane Bev Max 4 Classic",
          selections: 48,
          items: 400,
        },
        {
          name: "USI 3130",
          description: "Compact Snack Solution: The USI 3130 is designed for locations where space is at a premium. Despite its compact size, it doesn't compromise on functionality.",
          image: "/images/wordpress/USI-3130-pps9s29iuucicxizctvma2nj0qezz66y25gy5nrsf4.webp",
          alt: "Rocky Mountain Vending USI 3130",
          selections: 24,
          items: 420,
        },
        {
          name: "AMS 39 VCB",
          description: "Reliability Redefined: The AMS 39 VCB is a dependable combo machine that consistently meets our high standards. Its robust design ensures long-term reliability.",
          image: "/images/wordpress/AMS-39-VCB-Combo.webp",
          alt: "AMS 39 VCB",
          selections: 36,
          items: 375,
        },
        {
          name: "Crane Merchant Media Snack",
          description: "The Snack Giant: When it comes to snack machines, the Crane Merchant Media Snack is unparalleled in capacity. It's the largest snack machine available, capable of holding a diverse range of snack options.",
          image: "/images/wordpress/Crane-Merchant-6-Media-Snack-pps9rxkbwo62qvpt49uhflu81t25wooadi7ir9yra8.webp",
          alt: "Crane Merchant Media 6",
          selections: 44,
          items: 375,
        },
      ];
      
      // Filter out images that are part of the machine cards section (they'll be replaced)
      const imagesToExclude = new Set<number>();
      const imageGroupsToExclude = new Set<number>();
      if (shouldShowMachineCards && machineCardsParagraphIndex !== null) {
        // Find all images after the paragraph that should be replaced
        // Look for images in the next section after the paragraph (within 10000 chars to catch all)
        const sectionEndIndex = machineCardsParagraphIndex + 10000;
        images.forEach((img, idx) => {
          if (img.index > machineCardsParagraphIndex! && img.index < sectionEndIndex) {
            // Check if it's one of the machine images (by checking alt text or src)
            const imgAlt = img.alt.toLowerCase();
            const imgSrc = img.src.toLowerCase();
            // Exclude ANY image in elementor/thumbs folder (these are the old machine images)
            // Also exclude any image that matches machine patterns
            if (imgSrc.includes('elementor/thumbs') ||
                imgAlt.includes('crane bev max') || imgAlt.includes('bev max') ||
                imgAlt.includes('usi 3130') || imgAlt.includes('usi') ||
                imgAlt.includes('ams 39') || imgAlt.includes('ams') ||
                imgAlt.includes('crane merchant') || imgAlt.includes('merchant media') ||
                imgAlt.includes('qfv') || imgAlt.includes('quick fresh') ||
                imgAlt.includes('seaga') || imgAlt.includes('seage') ||
                imgSrc.includes('bev-max') || imgSrc.includes('usi-3130') ||
                imgSrc.includes('ams-39') || imgSrc.includes('merchant') ||
                imgSrc.includes('qfv') || imgSrc.includes('qfv-50') ||
                imgSrc.includes('seaga') || imgSrc.includes('seage')) {
              imagesToExclude.add(idx);
            }
          }
        });
        
        // Also exclude image groups if they're in the machine cards section
        imageGroups.forEach((group, groupIdx) => {
          if (group[0].index > machineCardsParagraphIndex! && group[0].index < sectionEndIndex) {
            // Check if any image in the group matches machine patterns
            // Prioritize checking for elementor/thumbs first (most reliable indicator)
            const hasMachineImage = group.some((img) => {
              const imgAlt = img.alt.toLowerCase();
              const imgSrc = img.src.toLowerCase();
              return imgSrc.includes('elementor/thumbs') ||
                     imgAlt.includes('crane bev max') || imgAlt.includes('bev max') ||
                     imgAlt.includes('usi 3130') || imgAlt.includes('usi') ||
                     imgAlt.includes('ams 39') || imgAlt.includes('ams') ||
                     imgAlt.includes('crane merchant') || imgAlt.includes('merchant media') ||
                     imgAlt.includes('qfv') || imgAlt.includes('quick fresh') ||
                     imgAlt.includes('seaga') || imgAlt.includes('seage') ||
                     imgSrc.includes('bev-max') || imgSrc.includes('usi-3130') ||
                     imgSrc.includes('ams-39') || imgSrc.includes('merchant') ||
                     imgSrc.includes('qfv') || imgSrc.includes('qfv-50') ||
                     imgSrc.includes('seaga') || imgSrc.includes('seage');
            });
            if (hasMachineImage) {
              imageGroupsToExclude.add(groupIdx);
              // Mark all images in this group as processed so they're excluded
              group.forEach((img) => {
                const imgIndex = images.findIndex(i => i.index === img.index);
                if (imgIndex !== -1) {
                  processedImageIndices.add(imgIndex);
                }
              });
            }
          }
        });
      }
      
      // Process content in order
      const allElements = [
        ...headings.map(h => ({ type: 'heading' as const, ...h })),
        ...funfacts.map(f => ({ type: 'funfact' as const, ...f })),
        ...(sliderImages.length > 0 ? [{ type: 'slider' as const, images: sliderImages, index: sliderIndex! }] : []),
        ...(galleryImages.length > 0
          ? galleryImages.map(img => ({
              type: 'gallery' as const,
              ...img
            }))
          : []),
        ...imageGroups.filter((group, groupIdx) => !imageGroupsToExclude.has(groupIdx)).map((group, groupIdx) => ({ 
          type: 'image-group' as const, 
          images: group, 
          index: group[0].index 
        })),
        ...images.filter((img, idx) => !processedImageIndices.has(idx) && !imagesToExclude.has(idx)).map(img => ({ type: 'image' as const, ...img })),
        ...paragraphs.map(p => ({ type: 'paragraph' as const, ...p })),
        ...lists.map(l => ({ type: 'list' as const, listType: l.listType, items: l.items, index: l.index })),
        // Add machine cards after the paragraph if detected
        ...(shouldShowMachineCards && machineCardsParagraphIndex !== null 
          ? [{ type: 'machine-cards' as const, index: machineCardsParagraphIndex + 1000 }] 
          : [])
      ].sort((a, b) => a.index - b.index);

      // Render elements
      allElements.forEach((element) => {
        if (element.type === 'heading') {
          const headingElement = element as { type: 'heading'; level: number; content: string; index: number };
          const HeadingTag = `h${headingElement.level}` as keyof React.JSX.IntrinsicElements;
          // Clean HTML tags from heading content
          let cleanHeadingContent = headingElement.content;
          // Remove HTML tags but preserve text content
          cleanHeadingContent = cleanHeadingContent.replace(/<[^>]+>/g, '');
          // Clean HTML entities
          cleanHeadingContent = cleanHtmlEntities(cleanHeadingContent);
          
          sectionComponents.push(
            <HeadingTag
              key={`heading-${sectionIndex}-${headingElement.index}`}
              className={`font-bold mb-4 ${
                headingElement.level === 1
                  ? 'text-4xl md:text-5xl'
                  : headingElement.level === 2
                  ? 'text-3xl md:text-4xl'
                  : headingElement.level === 3
                  ? 'text-2xl md:text-3xl'
                  : 'text-xl md:text-2xl'
              }`}
            >
              {cleanHeadingContent}
            </HeadingTag>
          );
        } else if (element.type === 'slider') {
          // Render slider images as a horizontal scrolling carousel with auto-rotation
          const carouselImages = element.images.map((img) => {
            const imagePath = getImagePath(img.src, imageMapping);
            const alt = getImageAlt(img.src, imageMapping, img.alt || img.title || '');
            
            // Use the mapped local path if available, otherwise fix malformed URLs
            let finalSrc = imagePath;
            
            // If imagePath is a local path (starts with /), use it directly
            if (imagePath.startsWith('/') && !imagePath.startsWith('//')) {
              finalSrc = imagePath;
            } else {
              // Fix malformed URLs in imagePath first
              if (imagePath.startsWith('https:///') || imagePath.startsWith('http:///')) {
                finalSrc = imagePath.replace(/^https?:\/\//, 'https://rockymountainvending.com/');
              } else if (imagePath.startsWith('https://wp-content') || imagePath.startsWith('http://wp-content')) {
                finalSrc = imagePath.replace(/^https?:\/\/wp-content/, 'https://rockymountainvending.com/wp-content');
              } else if (imagePath.startsWith('http')) {
                finalSrc = imagePath; // Keep as-is if valid URL
              } else {
                // Fallback to original src and fix it
                finalSrc = img.src;
                if (finalSrc.startsWith('https:///') || finalSrc.startsWith('http:///')) {
                  finalSrc = finalSrc.replace(/^https?:\/\//, 'https://rockymountainvending.com/');
                } else if (finalSrc.startsWith('https://wp-content') || finalSrc.startsWith('http://wp-content')) {
                  finalSrc = finalSrc.replace(/^https?:\/\/wp-content/, 'https://rockymountainvending.com/wp-content');
                } else if (finalSrc.startsWith('http')) {
                  finalSrc = finalSrc; // Keep as-is if valid URL
                } else if (finalSrc.startsWith('/')) {
                  finalSrc = `https://rockymountainvending.com${finalSrc}`;
                } else {
                  finalSrc = `https://rockymountainvending.com/${finalSrc}`;
                }
              }
            }
            
            return {
              src: finalSrc,
              alt: alt,
              title: img.title
            };
          });
          
          sectionComponents.push(
            <div
              key={`slider-${sectionIndex}-${element.index}`}
              className="my-8 w-full"
            >
              <ImageCarousel 
                images={carouselImages}
                autoScrollInterval={3000}
              />
            </div>
          );
        } else if (element.type === 'gallery') {
          const imagePath = getImagePath(element.src, imageMapping);
          const alt = getImageAlt(element.src, imageMapping, element.alt);

          // Use the mapped local path if available, otherwise fix malformed URLs
          let finalSrc = imagePath;

          if (imagePath.startsWith('/') && !imagePath.startsWith('//')) {
            finalSrc = imagePath;
          } else {
            if (imagePath.startsWith('https:///') || imagePath.startsWith('http:///')) {
              finalSrc = imagePath.replace(/^https?:\/\//, 'https://rockymountainvending.com/');
            } else if (imagePath.startsWith('https://wp-content') || imagePath.startsWith('http://wp-content')) {
              finalSrc = imagePath.replace(
                /^https?:\/\/wp-content/,
                'https://rockymountainvending.com/wp-content'
              );
            } else if (imagePath.startsWith('http')) {
              finalSrc = imagePath;
            } else {
              finalSrc = element.src;
              if (finalSrc.startsWith('https:///') || finalSrc.startsWith('http:///')) {
                finalSrc = finalSrc.replace(/^https?:\/\//, 'https://rockymountainvending.com/');
              } else if (finalSrc.startsWith('https://wp-content') || finalSrc.startsWith('http://wp-content')) {
                finalSrc = finalSrc.replace(
                  /^https?:\/\/wp-content/,
                  'https://rockymountainvending.com/wp-content'
                );
              } else if (finalSrc.startsWith('http')) {
                finalSrc = finalSrc;
              } else if (finalSrc.startsWith('/')) {
                finalSrc = `https://rockymountainvending.com${finalSrc}`;
              } else {
                finalSrc = `https://rockymountainvending.com/${finalSrc}`;
              }
            }
          }

          // Constrain image dimensions per style guide (max 600px for standalone images)
          const constrainedWidth = element.width ? Math.min(element.width, 600) : 600;
          const constrainedHeight = element.height ? Math.min(element.height, 600) : 600;
          
          sectionComponents.push(
            <div
              key={`gallery-${sectionIndex}-${element.index}`}
              className="my-6 w-full max-w-md mx-auto"
            >
              <div className="relative w-full overflow-hidden rounded-lg bg-muted shadow-sm">
                {element.width && element.height ? (
                  <Image
                    src={finalSrc}
                    alt={alt}
                    width={constrainedWidth}
                    height={constrainedHeight}
                    className="object-contain w-full h-auto"
                    sizes="(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1200px"
                    priority={prioritizeFirstImage && !hasPrioritizedImage}
                  />
                ) : (
                  <div className="relative aspect-video w-full bg-muted">
                    <Image
                      src={finalSrc}
                      alt={alt}
                      fill
                      className="object-contain"
                      sizes="(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1200px"
                      priority={prioritizeFirstImage && !hasPrioritizedImage}
                    />
                  </div>
                )}
              </div>
            </div>
          );
          if (prioritizeFirstImage && !hasPrioritizedImage) {
            hasPrioritizedImage = true;
          }
        } else if (element.type === 'image-group') {
          // Render grouped images side-by-side
          const groupImages = element.images;
          const imageCount = groupImages.length;
          
          sectionComponents.push(
            <div
              key={`image-group-${sectionIndex}-${element.index}`}
              className="my-6 w-full"
            >
              <div className={`flex flex-col md:flex-row gap-4 ${imageCount === 2 ? 'md:gap-6' : 'md:gap-4'}`}>
                {groupImages.map((img, imgIdx) => {
                  const imagePath = getImagePath(img.src, imageMapping);
                  const alt = getImageAlt(img.src, imageMapping, img.alt);
                  
                  // Use the mapped local path if available, otherwise fix malformed URLs
                  let finalSrc = imagePath;
                  
                  // If imagePath is a local path (starts with /), use it directly
                  if (imagePath.startsWith('/') && !imagePath.startsWith('//')) {
                    finalSrc = imagePath;
                  } else {
                    // Fix malformed URLs in imagePath first
                    if (imagePath.startsWith('https:///') || imagePath.startsWith('http:///')) {
                      finalSrc = imagePath.replace(/^https?:\/\//, 'https://rockymountainvending.com/');
                    } else if (imagePath.startsWith('https://wp-content') || imagePath.startsWith('http://wp-content')) {
                      finalSrc = imagePath.replace(/^https?:\/\/wp-content/, 'https://rockymountainvending.com/wp-content');
                    } else if (imagePath.startsWith('http')) {
                      finalSrc = imagePath; // Keep as-is if valid URL
                    } else {
                      // Fallback to original src and fix it
                      finalSrc = img.src;
                      if (finalSrc.startsWith('https:///') || finalSrc.startsWith('http:///')) {
                        finalSrc = finalSrc.replace(/^https?:\/\//, 'https://rockymountainvending.com/');
                      } else if (finalSrc.startsWith('https://wp-content') || finalSrc.startsWith('http://wp-content')) {
                        finalSrc = finalSrc.replace(/^https?:\/\/wp-content/, 'https://rockymountainvending.com/wp-content');
                      } else if (finalSrc.startsWith('http')) {
                        finalSrc = finalSrc; // Keep as-is if valid URL
                      } else if (finalSrc.startsWith('/')) {
                        finalSrc = `https://rockymountainvending.com${finalSrc}`;
                      } else {
                        finalSrc = `https://rockymountainvending.com/${finalSrc}`;
                      }
                    }
                  }
                  
                  // Constrain image dimensions per style guide (max 300px for grid images)
                  const constrainedWidth = img.width ? Math.min(img.width, 300) : 300;
                  const constrainedHeight = img.height ? Math.min(img.height, 300) : 300;
                  
                  return (
                    <div
                      key={imgIdx}
                      className={`flex-1 max-w-xs mx-auto ${imageCount === 2 ? 'md:w-1/2' : imageCount === 3 ? 'md:w-1/3' : 'md:w-1/4'}`}
                    >
                      <div className="relative w-full overflow-hidden rounded-lg bg-muted shadow-sm">
                        {img.width && img.height ? (
                          <Image
                            src={finalSrc}
                            alt={alt}
                            width={constrainedWidth}
                            height={constrainedHeight}
                            className="object-contain w-full h-auto"
                            sizes={imageCount === 2 ? "(max-width: 768px) 100vw, 50vw" : imageCount === 3 ? "(max-width: 768px) 100vw, 33vw" : "(max-width: 768px) 100vw, 25vw"}
                            priority={prioritizeFirstImage && !hasPrioritizedImage}
                          />
                        ) : (
                          <div className="relative aspect-video w-full bg-muted">
                            <Image
                              src={finalSrc}
                              alt={alt}
                              fill
                              className="object-contain"
                              sizes={imageCount === 2 ? "(max-width: 768px) 100vw, 50vw" : imageCount === 3 ? "(max-width: 768px) 100vw, 33vw" : "(max-width: 768px) 100vw, 25vw"}
                              priority={prioritizeFirstImage && !hasPrioritizedImage}
                            />
                          </div>
                        )}
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          );
          if (prioritizeFirstImage && !hasPrioritizedImage) {
            hasPrioritizedImage = true;
          }
        } else if (element.type === 'image') {
          const imagePath = getImagePath(element.src, imageMapping);
          const alt = getImageAlt(element.src, imageMapping, element.alt);
          
          // Use the mapped local path if available, otherwise fix malformed URLs
          let finalSrc = imagePath;
          
          // If imagePath is a local path (starts with /), use it directly
          if (imagePath.startsWith('/') && !imagePath.startsWith('//')) {
            finalSrc = imagePath;
          } else {
            // Fix malformed URLs in imagePath first
            if (imagePath.startsWith('https:///') || imagePath.startsWith('http:///')) {
              finalSrc = imagePath.replace(/^https?:\/\//, 'https://rockymountainvending.com/');
            } else if (imagePath.startsWith('https://wp-content') || imagePath.startsWith('http://wp-content')) {
              finalSrc = imagePath.replace(/^https?:\/\/wp-content/, 'https://rockymountainvending.com/wp-content');
            } else if (imagePath.startsWith('http')) {
              finalSrc = imagePath; // Keep as-is if valid URL
            } else {
              // Fallback to original src and fix it
              finalSrc = element.src;
              if (finalSrc.startsWith('https:///') || finalSrc.startsWith('http:///')) {
                finalSrc = finalSrc.replace(/^https?:\/\//, 'https://rockymountainvending.com/');
              } else if (finalSrc.startsWith('https://wp-content') || finalSrc.startsWith('http://wp-content')) {
                finalSrc = finalSrc.replace(/^https?:\/\/wp-content/, 'https://rockymountainvending.com/wp-content');
              } else if (finalSrc.startsWith('http')) {
                finalSrc = finalSrc; // Keep as-is if valid URL
              } else if (finalSrc.startsWith('/')) {
                finalSrc = `https://rockymountainvending.com${finalSrc}`;
              } else {
                finalSrc = `https://rockymountainvending.com/${finalSrc}`;
              }
            }
          }
          
          // Check if this image was in a column layout by looking at surrounding HTML
          // Look for elementor-col classes near this image's position
          const imageContext = sectionHtml.substring(
            Math.max(0, element.index - 1000),
            Math.min(sectionHtml.length, element.index + 1000)
          );
          const hasColumn33 = /elementor-col-33|elementor-col-25/i.test(imageContext);
          const hasColumn50 = /elementor-col-50/i.test(imageContext);
          const hasColumn66 = /elementor-col-66|elementor-col-75/i.test(imageContext);
          
          // Check if there are multiple images in the same section (side-by-side layout)
          const imagesInSection = images.filter(img => 
            img.index >= element.index - 2000 && 
            img.index <= element.index + 2000 &&
            img.index !== element.index
          );
          
          // Determine container width based on original layout - follow style guide
          let containerClass = 'w-full';
          let maxWidthClass = 'max-w-md';
          let imageMaxWidth = 600; // Max 600px for standalone images per style guide
          let imageMaxHeight = 600;
          
          if (hasColumn33 || (imagesInSection.length >= 2 && imagesInSection.length < 4)) {
            containerClass = 'w-full md:w-1/3';
            maxWidthClass = 'max-w-xs';
            imageMaxWidth = 300; // Max 300px for grid images per style guide
            imageMaxHeight = 300;
          } else if (hasColumn50 || (imagesInSection.length === 1)) {
            containerClass = 'w-full md:w-1/2';
            maxWidthClass = 'max-w-sm';
            imageMaxWidth = 300; // Max 300px for grid images per style guide
            imageMaxHeight = 300;
          } else if (hasColumn66) {
            containerClass = 'w-full md:w-2/3';
            maxWidthClass = 'max-w-md';
            imageMaxWidth = 500; // Slightly larger for 2/3 width
            imageMaxHeight = 500;
          }
          
          // Constrain image dimensions per style guide
          const constrainedWidth = element.width ? Math.min(element.width, imageMaxWidth) : imageMaxWidth;
          const constrainedHeight = element.height ? Math.min(element.height, imageMaxHeight) : imageMaxHeight;
          
          sectionComponents.push(
            <div
              key={`image-${sectionIndex}-${element.index}`}
              className={`my-6 ${containerClass} ${maxWidthClass} mx-auto`}
            >
              <div className="relative w-full overflow-hidden rounded-lg bg-muted shadow-sm">
                {element.width && element.height ? (
                  <Image
                    src={finalSrc}
                    alt={alt}
                    width={constrainedWidth}
                    height={constrainedHeight}
                    className="object-contain w-full h-auto"
                    sizes={hasColumn33 ? "(max-width: 768px) 100vw, 33vw" : hasColumn50 ? "(max-width: 768px) 100vw, 50vw" : hasColumn66 ? "(max-width: 768px) 100vw, 66vw" : "(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1200px"}
                    priority={prioritizeFirstImage && !hasPrioritizedImage}
                  />
                ) : (
                  <div className="relative aspect-video w-full bg-muted">
                    <Image
                      src={finalSrc}
                      alt={alt}
                      fill
                      className="object-contain"
                      sizes={hasColumn33 ? "(max-width: 768px) 100vw, 33vw" : hasColumn50 ? "(max-width: 768px) 100vw, 50vw" : hasColumn66 ? "(max-width: 768px) 100vw, 66vw" : "(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1200px"}
                      priority={prioritizeFirstImage && !hasPrioritizedImage}
                    />
                  </div>
                )}
              </div>
            </div>
          );
          if (prioritizeFirstImage && !hasPrioritizedImage) {
            hasPrioritizedImage = true;
          }
        } else if (element.type === 'paragraph') {
          // Process paragraph HTML to handle nested tags (em, strong, links, etc.)
          let processedHtml = element.content;
          
          // Convert strong/bold
          processedHtml = processedHtml.replace(/<strong[^>]*>(.*?)<\/strong>/gi, '<strong>$1</strong>');
          processedHtml = processedHtml.replace(/<b[^>]*>(.*?)<\/b>/gi, '<strong>$1</strong>');
          
          // Convert emphasis/italic
          processedHtml = processedHtml.replace(/<em[^>]*>(.*?)<\/em>/gi, '<em>$1</em>');
          processedHtml = processedHtml.replace(/<i[^>]*>(.*?)<\/i>/gi, '<em>$1</em>');
          
          // Convert links
          processedHtml = processedHtml.replace(/<a[^>]+href=["']([^"']+)["'][^>]*>(.*?)<\/a>/gi, (_match: string, href: string, text: string) => {
            return `<a href="${href}" class="text-secondary hover:underline font-medium">${text}</a>`;
          });
          
          // Clean HTML entities
          processedHtml = cleanHtmlEntities(processedHtml);
          
          sectionComponents.push(
            <p
              key={`para-${sectionIndex}-${element.index}`}
              className="mb-6 text-lg leading-relaxed text-muted-foreground"
              dangerouslySetInnerHTML={{ __html: processedHtml }}
            />
          );
        } else if (element.type === 'list') {
          const listElement = element as { type: 'list'; listType: 'ul' | 'ol'; items: Array<{ text: string; html: string }>; index: number };
          const ListTag = listElement.listType === 'ul' ? 'ul' : 'ol';
          
          // Process list items to handle nested HTML
          const processedItems = listElement.items.map((item: { text: string; html: string }) => {
            // Extract and process nested HTML (strong, em, links, etc.)
            let processed = item.html;
            
            // Convert strong/bold
            processed = processed.replace(/<strong[^>]*>(.*?)<\/strong>/gi, '<strong>$1</strong>');
            processed = processed.replace(/<b[^>]*>(.*?)<\/b>/gi, '<strong>$1</strong>');
            
            // Convert emphasis/italic
            processed = processed.replace(/<em[^>]*>(.*?)<\/em>/gi, '<em>$1</em>');
            processed = processed.replace(/<i[^>]*>(.*?)<\/i>/gi, '<em>$1</em>');
            
            // Convert links
            processed = processed.replace(/<a[^>]+href=["']([^"']+)["'][^>]*>(.*?)<\/a>/gi, (match, href, text) => {
              return `<a href="${href}" class="text-secondary hover:underline font-medium">${text}</a>`;
            });
            
            // Clean remaining HTML entities
            processed = cleanHtmlEntities(processed);
            
            return processed;
          });
          
          sectionComponents.push(
            <ListTag
              key={`list-${sectionIndex}-${listElement.index}`}
              className={`mb-8 space-y-3 ${
                listElement.listType === 'ul' ? 'list-disc' : 'list-decimal'
              } ml-6 text-lg text-muted-foreground`}
            >
              {processedItems.map((item: string, itemIndex: number) => (
                <li 
                  key={itemIndex} 
                  className="leading-relaxed"
                  dangerouslySetInnerHTML={{ __html: item }}
                />
              ))}
            </ListTag>
          );
        } else if (element.type === 'machine-cards') {
          // Render machine cards using the same component from machines-we-use page
          sectionComponents.push(
            <div
              key={`machine-cards-${sectionIndex}-${element.index}`}
              className="my-12"
            >
              <div className="grid gap-6 md:gap-8 md:grid-cols-2 lg:grid-cols-3">
                {gymMachines.map((machine) => (
                  <VendingMachineCard
                    key={machine.name}
                    name={machine.name}
                    description={machine.description}
                    image={machine.image}
                    alt={machine.alt}
                    selections={machine.selections}
                    items={machine.items}
                  />
                ))}
              </div>
            </div>
          );
        }
      });

      // If we have components, wrap them in a section
      if (sectionComponents.length > 0) {
        components.push(
          <section
            key={`section-${sectionIndex}`}
            className="mb-12 last:mb-0"
          >
            {sectionComponents}
          </section>
        );
      }
    });

    // If no components were created, create a fallback
    if (components.length === 0) {
      const textContent = cleanHtmlEntities(
        html.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim()
      );
      
      if (textContent.length > 50) {
        components.push(
          <div key="fallback" className="prose prose-lg max-w-none">
            <p className="mb-4 text-muted-foreground leading-relaxed">{textContent}</p>
          </div>
        );
      }
    }

    return components;
  } catch (error) {
    // Enhanced error logging for development
    if (process.env.NODE_ENV === 'development') {
      console.error('Error cleaning WordPress content:', error);
      if (error instanceof Error) {
        console.error('Error message:', error.message);
        console.error('Error stack:', error.stack);
      }
      console.error('HTML length:', html?.length || 0);
      console.error('HTML preview:', html?.substring(0, 500) || 'No HTML provided');
    } else {
      // Minimal logging in production
      console.error('Error processing WordPress content');
    }
    
    // Return error fallback with raw content preview
    return [
      <div key="error" className="prose max-w-none">
        <p className="text-red-600 mb-4">Error processing content.</p>
        {process.env.NODE_ENV === 'development' && error instanceof Error && (
          <p className="text-sm text-muted-foreground mb-2">
            {error.message}
          </p>
        )}
        {html && html.length > 0 && (
          <div
            className="prose prose-lg max-w-none"
            dangerouslySetInnerHTML={{
              __html: html
            }}
          />
        )}
      </div>
    ];
  }
}
