import { useState } from 'react';
import partsData from '../data/index.js';
import { formatPrice, getNumericPrice } from '../utils/priceFormat';
import JSZip from 'jszip';
import * as XLSX from 'xlsx';
import { createShareLink } from '../utils/shareService';
import { generateMarkdownOverview, generateExcelBOM, generateExcelPrintList } from '../utils/exportUtils';

export default function BOMSummary({ config }) {
  const [isExportingZip, setIsExportingZip] = useState(false);
  const [zipProgress, setZipProgress] = useState({ current: 0, total: 0, currentFile: '' });
  const [hardwareViewMode, setHardwareViewMode] = useState('unified'); // 'unified' or 'expanded'
  const [activeTab, setActiveTab] = useState('overview'); // 'overview', 'printed', 'hardware'
  const calculateTotal = () => {
    let total = 0;

    if (config.motor) total += getNumericPrice(config.motor.price);
    if (config.powerSupply) total += getNumericPrice(config.powerSupply.price);
    
    if (config.mount) {
      const mountOption = partsData.options?.mounts?.find(m => m.id === config.mount.id);
      if (mountOption?.hardwareCost) total += getNumericPrice(mountOption.hardwareCost);
    }
    
    if (config.standHinge) {
      // Check new structure (systems) first, then fall back to options
      const hingeSystem = partsData.components?.hinges?.systems?.[config.standHinge.id];
      if (hingeSystem?.hardwareCost) {
        total += getNumericPrice(hingeSystem.hardwareCost);
      } else {
        const hingeOption = partsData.options?.standHinges?.find(h => h.id === config.standHinge.id);
        if (hingeOption?.hardwareCost) total += getNumericPrice(hingeOption.hardwareCost);
      }
    }
    
    if (config.standFeet) {
      const feetOption = partsData.options?.standFeet?.find(f => f.id === config.standFeet.id);
      if (feetOption?.hardwareCost) total += getNumericPrice(feetOption.hardwareCost);
    }
    
    if (config.standCrossbarSupports) {
      config.standCrossbarSupports.forEach((support) => {
        const supportOption = partsData.options?.standCrossbarSupports?.find(s => s.id === support.id);
        if (supportOption?.hardwareCost) total += getNumericPrice(supportOption.hardwareCost);
      });
    }

    return total;
  };

  const getRequiredPrintedParts = () => {
    const parts = [];
    const isMiddlePivotSelected = config.mount?.id === 'middle-pivot';
    const coverId = config.cover?.id;
    const isStandardCover = coverId === 'standard-cover';
    const isBlankCover = coverId === 'blank-cover';
    const isCustomCover = config.cover !== null && !isStandardCover && !isBlankCover;

    // Always include actuator parts, but exclude ossm-actuator-body-middle if middlePivot is selected
    // and exclude ossm-actuator-body-cover if a non-standard cover is selected
    if (partsData.components?.actuator?.printedParts) {
      partsData.components.actuator.printedParts.forEach((part) => {
        if (part.required) {
          // Skip the actuator body middle part if middle pivot is selected
          if (isMiddlePivotSelected && part.id === 'ossm-actuator-body-middle') {
            return;
          }
          // Skip the default cover if a non-standard cover is selected (blank or custom)
          if ((isBlankCover || isCustomCover) && part.id === 'ossm-actuator-body-cover') {
            return;
          }
          parts.push({ ...part, category: 'Actuator Body' });
        }
      });
    }

    // Include mount-specific parts based on selection
    if (config.mount) {
      const mountId = config.mount.id;
      if (mountId === 'middle-pivot' && partsData.components?.middlePivot?.printedParts) {
        partsData.components.middlePivot.printedParts.forEach((part) => {
          if (part.required) {
            parts.push({ ...part, category: 'Mount', replacesActuatorMiddle: true });
          }
        });
      } else if (mountId === 'pitclamp' && partsData.components?.pitClamp?.printedParts) {
        const selectedMotorId = config.motor?.id;
        partsData.components.pitClamp.printedParts.forEach((part) => {
          if (part.required) {
            // Filter motor-specific parts - only include the one that matches the selected motor
            const isMotorSpecificPart = part.id.includes('57AIM30') || part.id.includes('42AIM30') || part.id.includes('iHSV57');
            if (isMotorSpecificPart) {
              // Only include if it matches the selected motor
              const expectedPartId = `ossm-pitclamp-mini-${selectedMotorId}`;
              if (part.id === expectedPartId) {
                parts.push({ ...part, category: 'Mount' });
              }
            } else {
              // Include non-motor-specific parts (lower, upper, handle, dogbone-nuts)
              parts.push({ ...part, category: 'Mount' });
            }
          }
        });
      }
      
      // Include mount option part
      if (partsData.components?.mounts?.printedParts) {
        const mountPart = partsData.components.mounts.printedParts.find(p => p.id === mountId);
        if (mountPart) {
          parts.push({ ...mountPart, category: 'Mount' });
        }
      }
    }

    // Include custom cover if selected (replaces default cover)
    // Skip blank cover and standard cover (standard uses the component, blank uses nothing)
    if (isCustomCover) {
      const coverOption = config.cover;
      // Convert cover option to part format for BOM
      parts.push({
        id: coverOption.id,
        name: coverOption.name,
        description: coverOption.description || coverOption.name,
        filamentEstimate: coverOption.filamentEstimate ? parseFloat(coverOption.filamentEstimate.replace('~', '').replace('g', '')) : 0,
        filePath: `${coverOption.id}.3mf`,
        category: 'Cover',
        required: true,
        colour: 'primary',
      });
    }

    // Include PCB mount parts if a PCB mount is selected
    if (config.pcbMount) {
      const pcbMountId = config.pcbMount.id;
      const pcbMountComponent = partsData.components?.[pcbMountId];
      if (pcbMountComponent?.printedParts) {
        pcbMountComponent.printedParts.forEach((part) => {
          if (part.required) {
            parts.push({ ...part, category: 'PCB Mount' });
          }
        });
      }
    }

    // Include toy mount parts if any toy mounts are selected
    if (config.toyMountOptions && config.toyMountOptions.length > 0) {
      if (partsData.components?.toyMounts?.printedParts) {
        const selectedToyMountIds = new Set(config.toyMountOptions.map(opt => opt.id));
        partsData.components.toyMounts.printedParts.forEach((part) => {
          if (selectedToyMountIds.has(part.id)) {
            parts.push({ ...part, category: 'Toy Mounts' });
          }
        });
      }
    }

    // Include stand parts if stand options are selected
    if (config.standHinge || config.standFeet || (config.standCrossbarSupports && config.standCrossbarSupports.length > 0)) {
      if (partsData.components?.stand?.printedParts) {
        partsData.components.stand.printedParts.forEach((part) => {
          if (part.required) {
            parts.push({ ...part, category: 'Stand' });
          }
        });
      }
    }

    // Include stand hinge system parts
    if (config.standHinge && partsData.components?.hinges?.systems) {
      const hingeSystem = partsData.components.hinges.systems[config.standHinge.id];
      if (hingeSystem?.printedParts) {
        hingeSystem.printedParts.forEach((part) => {
          if (part.required) {
            parts.push({ ...part, category: 'Stand Hinges' });
          }
        });
      }
    }

    // Include stand feet option part
    if (config.standFeet && partsData.components?.feet?.printedParts) {
      const feetPart = partsData.components.feet.printedParts.find(p => p.id === config.standFeet.id);
      if (feetPart) {
        parts.push({ ...feetPart, category: 'Stand Feet' });
      }
    }

    // Include stand crossbar support option parts
    if (config.standCrossbarSupports && config.standCrossbarSupports.length > 0 && partsData.components?.crossbarSupports?.printedParts) {
      const selectedSupportIds = new Set(config.standCrossbarSupports.map(opt => opt.id));
      partsData.components.crossbarSupports.printedParts.forEach((part) => {
        if (selectedSupportIds.has(part.id)) {
          // Skip hardware-only parts (e.g., aluminum standard-90-degree-support)
          // These should only appear in the hardware list
          if (part.isHardwareOnly) {
            return;
          }
          parts.push({ ...part, category: 'Stand Crossbar Supports' });
        }
      });
    }

    // Include remote system parts if a remote knob is selected
    if (config.remoteKnob && partsData.components?.remotes?.systems) {
      // Find which system contains this knob
      let remoteSystem = null;
      Object.values(partsData.components.remotes.systems).forEach((system) => {
        if (system.knobs && system.knobs.find(k => k.id === config.remoteKnob.id)) {
          remoteSystem = system;
        }
      });

      if (remoteSystem) {
        // Include body parts from the system
        if (remoteSystem.bodyParts) {
          remoteSystem.bodyParts.forEach((part) => {
            if (part.required) {
              parts.push({ ...part, category: 'Remote Body' });
            }
          });
        }

        // Include the selected remote knob part
        const knobPart = remoteSystem.knobs?.find(p => p.id === config.remoteKnob.id);
        if (knobPart) {
          parts.push({ ...knobPart, category: 'Remote Knobs' });
        }
      }
    }

    return parts;
  };

  // Helper function to categorize hardware by type
  const getHardwareType = (hardware) => {
    const id = hardware.id?.toLowerCase() || '';
    const name = hardware.name?.toLowerCase() || '';
    
    // Fasteners
    if (id.includes('fastener') || id.includes('screw') || id.includes('nut') || id.includes('washer') || 
        id.includes('bolt') || id.includes('handle') || name.includes('fastener') || name.includes('screw') || 
        name.includes('nut') || name.includes('washer') || name.includes('bolt') || name.includes('handle')) {
      return 'Fasteners';
    }
    
    // Motion components
    if (id.includes('bearing') || id.includes('pulley') || id.includes('belt') || id.includes('gear') ||
        id.includes('motor') || id.includes('rail') || id.includes('linear') ||
        name.includes('bearing') || name.includes('pulley') || name.includes('belt') ||
        name.includes('gear') || name.includes('motor') || name.includes('rail') || name.includes('linear')) {
      return 'Motion Components';
    }
    
    // Aluminum extrusion / 3030
    if (id.includes('3030') || id.includes('extrusion') || id.includes('aluminum') || id.includes('support') ||
        name.includes('3030') || name.includes('extrusion') || name.includes('aluminum') || name.includes('90 degree support')) {
      return 'Aluminum Extrusion';
    }
    
    // Electronics
    if (id.includes('pcb') || id.includes('board') || id.includes('circuit') || id.includes('sensor') ||
        id.includes('switch') || id.includes('led') || name.includes('pcb') || name.includes('board') ||
        name.includes('circuit') || name.includes('sensor') || name.includes('switch') || name.includes('led')) {
      return 'Electronics';
    }
    
    // Other / General Hardware
    return 'Other Hardware';
  };

  const getRequiredHardwareParts = () => {
    const printedParts = getRequiredPrintedParts();
    const printedPartIds = new Set(printedParts.map(p => p.id));
    const hardwareParts = [];
    const hardwareMap = new Map(); // To aggregate quantities for same hardware part

    // Collect all selected option IDs (including hardware-only options)
    const selectedOptionIds = new Set();
    
    // Add selected crossbar supports (may include hardware-only options)
    if (config.standCrossbarSupports && config.standCrossbarSupports.length > 0) {
      config.standCrossbarSupports.forEach(opt => selectedOptionIds.add(opt.id));
    }
    
    // Add other selected options that might be hardware-only
    if (config.standHinge) selectedOptionIds.add(config.standHinge.id);
    if (config.standFeet) selectedOptionIds.add(config.standFeet.id);
    if (config.mount) selectedOptionIds.add(config.mount.id);
    if (config.cover) selectedOptionIds.add(config.cover.id);
    if (config.pcbMount) selectedOptionIds.add(config.pcbMount.id);
    if (config.remoteKnob) selectedOptionIds.add(config.remoteKnob.id);
    if (config.toyMountOptions && config.toyMountOptions.length > 0) {
      config.toyMountOptions.forEach(opt => selectedOptionIds.add(opt.id));
    }

    // Handle hinges systems (new structure)
    if (config.standHinge && partsData.components?.hinges?.systems) {
      const hingeSystem = partsData.components.hinges.systems[config.standHinge.id];
      if (hingeSystem?.hardwareParts) {
        hingeSystem.hardwareParts.forEach((hardware) => {
          if (!hardware.required) return;
          const key = hardware.id;
          if (hardwareMap.has(key)) {
            const existing = hardwareMap.get(key);
            existing.quantity = (existing.quantity || 1) + (hardware.quantity || 1);
          } else {
            hardwareMap.set(key, {
              ...hardware,
              quantity: hardware.quantity || 1,
              category: partsData.components.hinges.category || 'Hardware',
              hardwareType: getHardwareType(hardware)
            });
          }
        });
      }
    }

    // Handle remote systems (new structure)
    if (config.remoteKnob && partsData.components?.remotes?.systems) {
      // Find which system contains this knob
      let remoteSystem = null;
      Object.values(partsData.components.remotes.systems).forEach((system) => {
        if (system.knobs && system.knobs.find(k => k.id === config.remoteKnob.id)) {
          remoteSystem = system;
        }
      });

      if (remoteSystem?.hardwareParts) {
        remoteSystem.hardwareParts.forEach((hardware) => {
          if (!hardware.required) return;
          const key = hardware.id;
          if (hardwareMap.has(key)) {
            const existing = hardwareMap.get(key);
            existing.quantity = (existing.quantity || 1) + (hardware.quantity || 1);
          } else {
            hardwareMap.set(key, {
              ...hardware,
              quantity: hardware.quantity || 1,
              category: partsData.components.remotes.category || 'Hardware'
            });
          }
        });
      }
    }

    // Build a map of component keys to their printed part IDs for quick lookup
    const componentPrintedPartIds = new Map();
    Object.entries(partsData.components || {}).forEach(([componentKey, component]) => {
      // Skip hinges and remotes as they're handled separately above
      if (componentKey === 'hinges' || componentKey === 'remotes') return;
      
      if (component.printedParts) {
        const partIds = component.printedParts.map(p => p.id);
        componentPrintedPartIds.set(componentKey, new Set(partIds));
      }
    });

    // Iterate through all components to find hardware parts (excluding hinges and remotes)
    Object.entries(partsData.components || {}).forEach(([componentKey, component]) => {
      // Skip hinges and remotes as they're handled separately above
      if (componentKey === 'hinges' || componentKey === 'remotes') return;
      
      if (!component.hardwareParts) return;

      // Check if this component has any selected printed parts OR selected options
      const componentPartIds = componentPrintedPartIds.get(componentKey);
      const hasSelectedParts = componentPartIds && Array.from(componentPartIds).some(id => printedPartIds.has(id) || selectedOptionIds.has(id));

      component.hardwareParts.forEach((hardware) => {
        if (!hardware.required) return;

        // If component has selected parts, check if hardware should be included
        let shouldInclude = false;
        
        if (hasSelectedParts) {
          const relatedParts = hardware.relatedParts || [];
          // If no relatedParts specified, include if component has selected parts
          // If relatedParts specified, include if any related part is selected (printed or option)
          if (relatedParts.length === 0) {
            shouldInclude = true;
          } else {
            shouldInclude = relatedParts.some(partId => printedPartIds.has(partId) || selectedOptionIds.has(partId));
          }
        }

        if (shouldInclude) {
          const key = hardware.id;
          if (hardwareMap.has(key)) {
            // Aggregate quantities if same hardware appears multiple times
            const existing = hardwareMap.get(key);
            existing.quantity = (existing.quantity || 1) + (hardware.quantity || 1);
          } else {
            hardwareMap.set(key, {
              ...hardware,
              quantity: hardware.quantity || 1,
              category: component.category || 'Hardware',
              hardwareType: getHardwareType(hardware)
            });
          }
        }
      });
    });

    // Convert map to array
    hardwareMap.forEach((hardware) => {
      hardwareParts.push(hardware);
    });

    return hardwareParts;
  };

  // Parse time estimate string (e.g., "2h14m", "1h3m", "40m25s") to minutes
  const parseTimeToMinutes = (timeStr) => {
    if (!timeStr || typeof timeStr !== 'string') return 0;
    
    let totalMinutes = 0;
    const hourMatch = timeStr.match(/(\d+)h/);
    const minuteMatch = timeStr.match(/(\d+)m/);
    const secondMatch = timeStr.match(/(\d+)s/);
    
    if (hourMatch) totalMinutes += parseInt(hourMatch[1], 10) * 60;
    if (minuteMatch) totalMinutes += parseInt(minuteMatch[1], 10);
    if (secondMatch) totalMinutes += parseFloat(secondMatch[1]) / 60;
    
    return totalMinutes;
  };

  // Format minutes to readable string (e.g., "2h 14m")
  const formatTimeFromMinutes = (minutes) => {
    if (minutes === 0) return '0m';
    
    const hours = Math.floor(minutes / 60);
    const mins = Math.round(minutes % 60);
    
    if (hours > 0 && mins > 0) {
      return `${hours}h ${mins}m`;
    } else if (hours > 0) {
      return `${hours}h`;
    } else {
      return `${mins}m`;
    }
  };

  const getTotalFilamentEstimate = () => {
    const parts = getRequiredPrintedParts();
    const totals = {
      primary: 0,
      secondary: 0,
      total: 0
    };

    parts.forEach((part) => {
      let estimate = 0;
      
      // Handle both numeric and string values (e.g., "~147g" or 147.19)
      if (typeof part.filamentEstimate === 'number') {
        estimate = part.filamentEstimate;
      } else if (typeof part.filamentEstimate === 'string') {
        // Parse string format like "~147g" or "147g"
        const cleaned = part.filamentEstimate.replace(/[~g]/g, '').trim();
        estimate = parseFloat(cleaned) || 0;
      }
      
      // Multiply by quantity if specified (default to 1)
      const quantity = part.quantity || 1;
      estimate = estimate * quantity;
      
      const colour = part.colour || 'primary';
      
      if (colour === 'primary') {
        totals.primary += estimate;
      } else if (colour === 'secondary') {
        totals.secondary += estimate;
      }
      totals.total += estimate;
    });

    return totals;
  };

  const getTotalTimeEstimate = () => {
    const parts = getRequiredPrintedParts();
    let totalMinutes = 0;

    parts.forEach((part) => {
      if (part.timeEstimate) {
        const timeMinutes = parseTimeToMinutes(part.timeEstimate);
        // Multiply by quantity if specified (default to 1)
        const quantity = part.quantity || 1;
        totalMinutes += timeMinutes * quantity;
      }
    });

    return formatTimeFromMinutes(totalMinutes);
  };

  const getColorName = (colorId, type = 'primary') => {
    const colors = type === 'primary' ? partsData.colors.primary : partsData.colors.accent;
    const color = colors.find((c) => c.id === colorId);
    return color ? color.name : colorId;
  };

  const getColorHex = (colorId, type = 'primary') => {
    const colors = type === 'primary' ? partsData.colors.primary : partsData.colors.accent;
    const color = colors.find((c) => c.id === colorId);
    return color ? color.hex : '#000000';
  };

  const total = calculateTotal();
  const printedParts = getRequiredPrintedParts();
  const hardwareParts = getRequiredHardwareParts();
  const filamentTotals = getTotalFilamentEstimate();
  const totalTime = getTotalTimeEstimate();

  // Group parts by category
  const partsByCategory = printedParts.reduce((acc, part) => {
    if (!acc[part.category]) {
      acc[part.category] = [];
    }
    acc[part.category].push(part);
    return acc;
  }, {});

  // Group hardware parts by category (unified view - aggregated quantities)
  const hardwareByCategory = hardwareParts.reduce((acc, part) => {
    if (!acc[part.category]) {
      acc[part.category] = [];
    }
    acc[part.category].push(part);
    return acc;
  }, {});

  // Group hardware parts by type for unified view (Fasteners, Motion Components, etc.)
  const hardwareByType = hardwareParts.reduce((acc, part) => {
    const type = part.hardwareType || 'Other Hardware';
    if (!acc[type]) {
      acc[type] = [];
    }
    acc[type].push(part);
    return acc;
  }, {});

  // Expanded view: Get hardware parts grouped by component (for expanded view)
  const getExpandedHardwareParts = () => {
    const printedParts = getRequiredPrintedParts();
    const printedPartIds = new Set(printedParts.map(p => p.id));
    const expandedHardware = [];
    const selectedOptionIds = new Set();
    
    if (config.standCrossbarSupports && config.standCrossbarSupports.length > 0) {
      config.standCrossbarSupports.forEach(opt => selectedOptionIds.add(opt.id));
    }
    if (config.standHinge) selectedOptionIds.add(config.standHinge.id);
    if (config.standFeet) selectedOptionIds.add(config.standFeet.id);
    if (config.mount) selectedOptionIds.add(config.mount.id);
    if (config.cover) selectedOptionIds.add(config.cover.id);
    if (config.pcbMount) selectedOptionIds.add(config.pcbMount.id);
    if (config.remoteKnob) selectedOptionIds.add(config.remoteKnob.id);
    if (config.toyMountOptions && config.toyMountOptions.length > 0) {
      config.toyMountOptions.forEach(opt => selectedOptionIds.add(opt.id));
    }

    // Handle hinges systems
    if (config.standHinge && partsData.components?.hinges?.systems) {
      const hingeSystem = partsData.components.hinges.systems[config.standHinge.id];
      if (hingeSystem?.hardwareParts) {
        const componentHardware = [];
        hingeSystem.hardwareParts.forEach((hardware) => {
          if (hardware.required) {
            componentHardware.push({
              ...hardware,
              quantity: hardware.quantity || 1,
              hardwareType: getHardwareType(hardware)
            });
          }
        });
        if (componentHardware.length > 0) {
          expandedHardware.push({
            component: partsData.components.hinges.category || 'Hinges',
            parts: componentHardware,
          });
        }
      }
    }

    // Handle remote systems
    if (config.remoteKnob && partsData.components?.remotes?.systems) {
      let remoteSystem = null;
      Object.values(partsData.components.remotes.systems).forEach((system) => {
        if (system.knobs && system.knobs.find(k => k.id === config.remoteKnob.id)) {
          remoteSystem = system;
        }
      });
      if (remoteSystem?.hardwareParts) {
        const componentHardware = [];
        remoteSystem.hardwareParts.forEach((hardware) => {
          if (hardware.required) {
            componentHardware.push({
              ...hardware,
              quantity: hardware.quantity || 1,
              hardwareType: getHardwareType(hardware)
            });
          }
        });
        if (componentHardware.length > 0) {
          expandedHardware.push({
            component: partsData.components.remotes.category || 'Remote',
            parts: componentHardware,
          });
        }
      }
    }

    // Handle other components
    const componentPrintedPartIds = new Map();
    Object.entries(partsData.components || {}).forEach(([componentKey, component]) => {
      if (componentKey === 'hinges' || componentKey === 'remotes') return;
      if (component.printedParts) {
        const partIds = component.printedParts.map(p => p.id);
        componentPrintedPartIds.set(componentKey, new Set(partIds));
      }
    });

    Object.entries(partsData.components || {}).forEach(([componentKey, component]) => {
      if (componentKey === 'hinges' || componentKey === 'remotes') return;
      if (!component.hardwareParts) return;

      const componentPartIds = componentPrintedPartIds.get(componentKey);
      const hasSelectedParts = componentPartIds && Array.from(componentPartIds).some(id => printedPartIds.has(id) || selectedOptionIds.has(id));

      const componentHardware = [];
      component.hardwareParts.forEach((hardware) => {
        if (!hardware.required) return;

        let shouldInclude = false;
        if (hasSelectedParts) {
          const relatedParts = hardware.relatedParts || [];
          if (relatedParts.length === 0) {
            shouldInclude = true;
          } else {
            shouldInclude = relatedParts.some(partId => printedPartIds.has(partId) || selectedOptionIds.has(partId));
          }
        }

        if (shouldInclude) {
          componentHardware.push({
            ...hardware,
            quantity: hardware.quantity || 1,
          });
        }
      });

      if (componentHardware.length > 0) {
        expandedHardware.push({
          component: component.category || componentKey,
          parts: componentHardware,
        });
      }
    });

    return expandedHardware;
  };

  const expandedHardwareByComponent = getExpandedHardwareParts();

  // Define main sections and their subcategories
  const mainSections = {
    'Actuator + Mount': ['Actuator Body', 'Mount', 'Cover', 'PCB Mount'],
    'Stand': ['Stand', 'Stand Hinges', 'Stand Feet', 'Stand Crossbar Supports'],
    'Remote': ['Remote Body', 'Remote Knobs'],
  };

  // Helper to check if a section has any parts
  const sectionHasParts = (subcategories) => {
    return subcategories.some(cat => partsByCategory[cat] && partsByCategory[cat].length > 0);
  };

  // Define tabs
  const tabs = [
    { id: 'overview', label: 'Overview' },
    { id: 'printed', label: 'Printed Parts' },
    { id: 'hardware', label: 'Hardware' },
  ];

  return (
    <div>
      <h2 className="text-2xl font-bold mb-4 text-gray-900 dark:text-white">BOM Summary</h2>
      <p className="text-gray-600 dark:text-gray-300 mb-6">
        Review your configuration and bill of materials.
      </p>

      {/* Tab Navigation */}
      <div className="border-b border-gray-200 dark:border-gray-700 mb-6">
        <nav className="-mb-px flex space-x-8">
          {tabs.map((tab) => (
            <button
              key={tab.id}
              onClick={() => setActiveTab(tab.id)}
              className={`
                py-4 px-1 border-b-2 font-medium text-sm transition-colors
                ${
                  activeTab === tab.id
                    ? 'border-blue-500 dark:border-blue-400 text-blue-600 dark:text-blue-400'
                    : 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-600'
                }
              `}
            >
              {tab.label}
            </button>
          ))}
        </nav>
      </div>

      {/* Tab Content */}
      <div className="space-y-6">
        {/* Overview Tab */}
        {activeTab === 'overview' && (
          <div className="space-y-6">
            {/* Hardware (Motor & Power Supply) */}
            {(config.motor || config.powerSupply) && (
              <div className="border-b border-gray-200 dark:border-gray-700 pb-4">
                <h3 className="text-lg font-semibold mb-4 text-gray-900 dark:text-white">Hardware</h3>
                <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4">
                  {config.motor && (
                    <div className="flex flex-col items-center">
                      {config.motor.image && (
                        <img
                          src={config.motor.image}
                          alt={config.motor.name}
                          className="h-32 w-32 object-contain rounded-lg bg-gray-100 dark:bg-gray-700 mb-2"
                          onError={(e) => {
                            e.target.style.display = 'none';
                          }}
                        />
                      )}
                      <span className="text-xs text-center text-gray-700 dark:text-gray-300 font-medium">{config.motor.name}</span>
                      <span className="text-xs text-center text-gray-600 dark:text-gray-400 mt-1">{formatPrice(config.motor.price)}</span>
                    </div>
                  )}
                  {config.powerSupply && (
                    <div className="flex flex-col items-center">
                      {config.powerSupply.image && (
                        <img
                          src={config.powerSupply.image}
                          alt={config.powerSupply.name}
                          className="h-32 w-32 object-contain rounded-lg bg-gray-100 dark:bg-gray-700 mb-2"
                          onError={(e) => {
                            e.target.style.display = 'none';
                          }}
                        />
                      )}
                      <span className="text-xs text-center text-gray-700 dark:text-gray-300 font-medium">{config.powerSupply.name}</span>
                      <span className="text-xs text-center text-gray-600 dark:text-gray-400 mt-1">{formatPrice(config.powerSupply.price)}</span>
                    </div>
                  )}
                </div>
              </div>
            )}

        {/* Filament Usage */}
        {(filamentTotals.total > 0 || totalTime !== '0m') && (
          <div className="border-b border-gray-200 dark:border-gray-700 pb-4">
            <h3 className="text-lg font-semibold mb-2 text-gray-900 dark:text-white">Filament Usage</h3>
            <div className="space-y-2">
              {filamentTotals.total > 0 && (
                <div className="space-y-1">
                  <div className="flex justify-between items-center">
                    <span className="font-semibold text-gray-700 dark:text-gray-300">Total Filament:</span>
                    <span className="font-bold text-gray-900 dark:text-white">{Math.round(filamentTotals.total)}g</span>
                  </div>
                  {filamentTotals.primary > 0 && (
                    <div className="flex justify-between items-center text-sm text-gray-600 dark:text-gray-400 ml-4">
                      <div className="flex items-center gap-2">
                        <div
                          className="w-4 h-4 rounded-full border border-gray-300 dark:border-gray-600"
                          style={{ backgroundColor: getColorHex(config.primaryColor, 'primary') }}
                        />
                        <span>Primary ({getColorName(config.primaryColor, 'primary')}):</span>
                      </div>
                      <span>{Math.round(filamentTotals.primary)}g</span>
                    </div>
                  )}
                  {filamentTotals.secondary > 0 && (
                    <div className="flex justify-between items-center text-sm text-gray-600 dark:text-gray-400 ml-4">
                      <div className="flex items-center gap-2">
                        <div
                          className="w-4 h-4 rounded-full border border-gray-300 dark:border-gray-600"
                          style={{ backgroundColor: getColorHex(config.accentColor, 'accent') }}
                        />
                        <span>Secondary ({getColorName(config.accentColor, 'accent')}):</span>
                      </div>
                      <span>{Math.round(filamentTotals.secondary)}g</span>
                    </div>
                  )}
                </div>
              )}
              {totalTime !== '0m' && (
                <div className="flex justify-between items-center pt-2 border-t border-gray-100 dark:border-gray-800">
                  <span className="font-semibold text-gray-700 dark:text-gray-300">Total Printing Time:</span>
                  <span className="font-bold text-gray-900 dark:text-white">{totalTime}</span>
                </div>
              )}
            </div>
          </div>
        )}

        {/* Selected Options/Kit */}
        {(config.mount || config.cover || config.pcbMount || config.standHinge || config.standFeet || 
          (config.standCrossbarSupports && config.standCrossbarSupports.length > 0) || 
          (config.remoteType || config.remote?.id)) && (
          <div className="border-b border-gray-200 dark:border-gray-700 pb-4">
            <h3 className="text-lg font-semibold mb-4 text-gray-900 dark:text-white">Selected Options</h3>
            <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4">
              {config.mount && (
                <div className="flex flex-col items-center">
                  {config.mount.image && (
                    <img
                      src={config.mount.image}
                      alt={config.mount.name}
                      className="h-32 w-32 object-contain rounded-lg bg-gray-100 mb-2"
                      onError={(e) => {
                        e.target.style.display = 'none';
                      }}
                    />
                  )}
                      <span className="text-xs text-center text-gray-700 dark:text-gray-300 font-medium">{config.mount.name}</span>
                </div>
              )}
              {config.cover && (
                <div className="flex flex-col items-center">
                  {config.cover.image && (
                    <img
                      src={config.cover.image}
                      alt={config.cover.name}
                      className="h-32 w-32 object-contain rounded-lg bg-gray-100 mb-2"
                      onError={(e) => {
                        e.target.style.display = 'none';
                      }}
                    />
                  )}
                      <span className="text-xs text-center text-gray-700 dark:text-gray-300 font-medium">{config.cover.name}</span>
                </div>
              )}
              {config.pcbMount && (
                <div className="flex flex-col items-center">
                  {config.pcbMount.image && (
                    <img
                      src={config.pcbMount.image}
                      alt={config.pcbMount.name}
                      className="h-32 w-32 object-contain rounded-lg bg-gray-100 mb-2"
                      onError={(e) => {
                        e.target.style.display = 'none';
                      }}
                    />
                  )}
                      <span className="text-xs text-center text-gray-700 dark:text-gray-300 font-medium">{config.pcbMount.name}</span>
                </div>
              )}
              {config.standHinge && (
                <div className="flex flex-col items-center">
                  {config.standHinge.image && (
                    <img
                      src={config.standHinge.image}
                      alt={config.standHinge.name}
                      className="h-32 w-32 object-contain rounded-lg bg-gray-100 mb-2"
                      onError={(e) => {
                        e.target.style.display = 'none';
                      }}
                    />
                  )}
                      <span className="text-xs text-center text-gray-700 dark:text-gray-300 font-medium">{config.standHinge.name}</span>
                </div>
              )}
              {config.standFeet && (
                <div className="flex flex-col items-center">
                  {config.standFeet.image && (
                    <img
                      src={config.standFeet.image}
                      alt={config.standFeet.name}
                      className="h-32 w-32 object-contain rounded-lg bg-gray-100 mb-2"
                      onError={(e) => {
                        e.target.style.display = 'none';
                      }}
                    />
                  )}
                      <span className="text-xs text-center text-gray-700 dark:text-gray-300 font-medium">{config.standFeet.name}</span>
                </div>
              )}
              {config.standCrossbarSupports && config.standCrossbarSupports.length > 0 && (
                <>
                  {config.standCrossbarSupports.map((support) => (
                    <div key={support.id} className="flex flex-col items-center">
                      {support.image && (
                        <img
                          src={support.image}
                          alt={support.name}
                          className="h-32 w-32 object-contain rounded-lg bg-gray-100 dark:bg-gray-700 mb-2"
                          onError={(e) => {
                            e.target.style.display = 'none';
                          }}
                        />
                      )}
                      <span className="text-xs text-center text-gray-700 dark:text-gray-300 font-medium">{support.name}</span>
                    </div>
                  ))}
                </>
              )}
              {(config.remoteType || config.remote?.id) && (() => {
                const remoteId = config.remoteType || config.remote?.id;
                const remoteSystem = partsData.components?.remotes?.systems?.[remoteId];
                return remoteSystem ? (
                  <div className="flex flex-col items-center">
                    {remoteSystem.image && (
                      <img
                        src={remoteSystem.image}
                        alt={remoteSystem.name}
                        className="h-32 w-32 object-contain rounded-lg bg-gray-100 mb-2"
                        onError={(e) => {
                          e.target.style.display = 'none';
                        }}
                      />
                    )}
                    <span className="text-xs text-center text-gray-700 dark:text-gray-300 font-medium">{remoteSystem.name}</span>
                  </div>
                ) : null;
              })()}
            </div>
          </div>
        )}

        {/* Toy Mounts */}
        {config.toyMountOptions && config.toyMountOptions.length > 0 && (
          <div className="border-b border-gray-200 dark:border-gray-700 pb-4">
            <h3 className="text-lg font-semibold mb-4 text-gray-900 dark:text-white">Toy Mounts</h3>
            <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4">
              {config.toyMountOptions.map((toyMount) => (
                <div key={toyMount.id} className="flex flex-col items-center">
                  {toyMount.image && (
                    <img
                      src={toyMount.image}
                      alt={toyMount.name}
                      className="h-32 w-32 object-contain rounded-lg bg-gray-100 mb-2"
                      onError={(e) => {
                        e.target.style.display = 'none';
                      }}
                    />
                  )}
                  <span className="text-xs text-center text-gray-700 dark:text-gray-300 font-medium">{toyMount.name}</span>
                  {toyMount.description && (
                    <span className="text-xs text-center text-gray-500 dark:text-gray-400 mt-1">{toyMount.description}</span>
                  )}
                </div>
              ))}
            </div>
          </div>
        )}

            {/* Total */}
            <div className="pt-4 border-t-2 border-gray-300 dark:border-gray-700">
              <div className="flex justify-between items-center">
                <h3 className="text-xl font-bold text-gray-900 dark:text-white">Total Hardware Cost</h3>
                <p className="text-2xl font-bold text-blue-600 dark:text-blue-400">${total.toFixed(2)}</p>
              </div>
            </div>
          </div>
        )}

        {/* Printed Parts Tab */}
        {activeTab === 'printed' && (
          <div className="space-y-6">
            {printedParts.length > 0 ? (
              <>
                <div className="border-b border-gray-200 dark:border-gray-700 pb-4">
                  <h3 className="text-lg font-semibold mb-4 text-gray-900 dark:text-white">Required Printed Parts</h3>
                </div>
                <div className="space-y-6">
              {Object.entries(mainSections).map(([mainSectionName, subcategories]) => {
                if (!sectionHasParts(subcategories)) {
                  return null;
                }
                
                return (
                  <div key={mainSectionName} className="border-l-2 border-blue-200 dark:border-blue-700 pl-4">
                    <h4 className="text-lg font-semibold text-gray-800 dark:text-gray-200 mb-3">{mainSectionName}</h4>
                    <div className="space-y-4 ml-2">
                      {subcategories.map((category) => {
                        const parts = partsByCategory[category];
                        if (!parts || parts.length === 0) {
                          return null;
                        }
                        
                        return (
                          <div key={category}>
                            <div className="flex items-center gap-2 mb-3">
                              <h5 className="text-md font-medium text-gray-700 dark:text-gray-300">{category}</h5>
                              {parts.some(p => p.replacesActuatorMiddle) && (
                                <span className="text-xs text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/30 px-2 py-1 rounded">
                                  Replaces standard ossm-actuator-body-middle
                                </span>
                              )}
                            </div>
                            <div className="overflow-x-auto">
                              <table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-lg">
                                <thead className="bg-gray-50 dark:bg-gray-800">
                                  <tr>
                                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">Part Name</th>
                                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">Color</th>
                                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">Description</th>
                                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">File Path</th>
                                    <th className="px-4 py-3 text-right text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">Quantity</th>
                                    <th className="px-4 py-3 text-right text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">Filament</th>
                                  </tr>
                                </thead>
                                <tbody className="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
                                  {parts.map((part) => {
                                    const partColour = part.colour || 'primary';
                                    const colorHex = getColorHex(
                                      partColour === 'primary' ? config.primaryColor : config.accentColor,
                                      partColour
                                    );
                                    const colorName = getColorName(
                                      partColour === 'primary' ? config.primaryColor : config.accentColor,
                                      partColour
                                    );
                                    
                                    return (
                                      <tr key={part.id} className="hover:bg-gray-50 dark:hover:bg-gray-700/50">
                                        <td className="px-4 py-3 whitespace-nowrap">
                                          <p className="text-sm font-medium text-gray-900 dark:text-white">{part.name}</p>
                                        </td>
                                        <td className="px-4 py-3 whitespace-nowrap">
                                          <div className="flex items-center gap-2">
                                            <div
                                              className="w-4 h-4 rounded-full border border-gray-300 dark:border-gray-600"
                                              style={{ backgroundColor: colorHex }}
                                              title={`${partColour === 'primary' ? 'Primary' : 'Secondary'} color: ${colorName}`}
                                            />
                                            <span className="text-xs text-gray-600 dark:text-gray-400 capitalize">{partColour}</span>
                                          </div>
                                        </td>
                                        <td className="px-4 py-3">
                                          <p className="text-sm text-gray-600 dark:text-gray-300">{part.description || '-'}</p>
                                        </td>
                                <td className="px-4 py-3">
                                  {part.isHardwareOnly ? (
                                    <span className="text-xs text-blue-600 dark:text-blue-400 italic">Hardware only</span>
                                  ) : part.filePath ? (
                                    <p className="text-xs text-gray-500 dark:text-gray-400 font-mono">{part.filePath}</p>
                                  ) : (
                                    <span className="text-gray-400 dark:text-gray-500">-</span>
                                  )}
                                </td>
                                <td className="px-4 py-3 whitespace-nowrap text-right">
                                  <p className="text-sm font-medium text-gray-700 dark:text-gray-300">{part.quantity || 1}</p>
                                </td>
                                <td className="px-4 py-3 whitespace-nowrap text-right">
                                  {part.isHardwareOnly ? (
                                    <span className="text-xs text-blue-600 dark:text-blue-400">-</span>
                                  ) : part.filamentEstimate !== undefined && part.filamentEstimate > 0 ? (
                                    <p className="text-sm font-medium text-gray-700 dark:text-gray-300">
                                      {typeof part.filamentEstimate === 'number' 
                                        ? (part.filamentEstimate * (part.quantity || 1)).toFixed(1)
                                        : part.filamentEstimate}g
                                      {(part.quantity || 1) > 1 && (
                                        <span className="text-xs text-gray-500 dark:text-gray-400 ml-1">
                                          ({(typeof part.filamentEstimate === 'number' ? part.filamentEstimate : parseFloat(part.filamentEstimate.replace(/[~g]/g, '').trim()) || 0).toFixed(1)}g × {part.quantity})
                                        </span>
                                      )}
                                    </p>
                                  ) : (
                                    <span className="text-gray-400 dark:text-gray-500">-</span>
                                  )}
                                </td>
                                      </tr>
                                    );
                                  })}
                                </tbody>
                              </table>
                            </div>
                          </div>
                        );
                      })}
                    </div>
                  </div>
                );
              })}
              
              {/* Other categories not in main sections (e.g., Toy Mounts) */}
              {Object.entries(partsByCategory).map(([category, parts]) => {
                const isInMainSection = Object.values(mainSections).flat().includes(category);
                if (isInMainSection) {
                  return null;
                }
                
                return (
                  <div key={category}>
                    <div className="flex items-center gap-2 mb-3">
                      <h4 className="text-md font-medium text-gray-700 dark:text-gray-300">{category}</h4>
                      {parts.some(p => p.replacesActuatorMiddle) && (
                        <span className="text-xs text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/30 px-2 py-1 rounded">
                          Replaces standard ossm-actuator-body-middle
                        </span>
                      )}
                    </div>
                    <div className="overflow-x-auto">
                      <table className="min-w-full divide-y divide-gray-200 border border-gray-200 rounded-lg">
                        <thead className="bg-gray-50">
                          <tr>
                            <th className="px-4 py-3 text-left text-xs font-medium text-gray-700 uppercase tracking-wider">Part Name</th>
                            <th className="px-4 py-3 text-left text-xs font-medium text-gray-700 uppercase tracking-wider">Color</th>
                            <th className="px-4 py-3 text-left text-xs font-medium text-gray-700 uppercase tracking-wider">Description</th>
                            <th className="px-4 py-3 text-left text-xs font-medium text-gray-700 uppercase tracking-wider">File Path</th>
                            <th className="px-4 py-3 text-right text-xs font-medium text-gray-700 uppercase tracking-wider">Quantity</th>
                            <th className="px-4 py-3 text-right text-xs font-medium text-gray-700 uppercase tracking-wider">Filament</th>
                          </tr>
                        </thead>
                        <tbody className="bg-white divide-y divide-gray-200">
                          {parts.map((part) => {
                            const partColour = part.colour || 'primary';
                            const colorHex = getColorHex(
                              partColour === 'primary' ? config.primaryColor : config.accentColor,
                              partColour
                            );
                            const colorName = getColorName(
                              partColour === 'primary' ? config.primaryColor : config.accentColor,
                              partColour
                            );
                            
                            return (
                              <tr key={part.id} className="hover:bg-gray-50">
                                <td className="px-4 py-3 whitespace-nowrap">
                                  <p className="text-sm font-medium text-gray-900">{part.name}</p>
                                </td>
                                <td className="px-4 py-3 whitespace-nowrap">
                                  <div className="flex items-center gap-2">
                                    <div
                                      className="w-4 h-4 rounded-full border border-gray-300"
                                      style={{ backgroundColor: colorHex }}
                                      title={`${partColour === 'primary' ? 'Primary' : 'Secondary'} color: ${colorName}`}
                                    />
                                    <span className="text-xs text-gray-600 capitalize">{partColour}</span>
                                  </div>
                                </td>
                                <td className="px-4 py-3">
                                  <p className="text-sm text-gray-600">{part.description || '-'}</p>
                                </td>
                                <td className="px-4 py-3">
                                  {part.isHardwareOnly ? (
                                    <span className="text-xs text-blue-600 italic">Hardware only</span>
                                  ) : part.filePath ? (
                                    <p className="text-xs text-gray-500 font-mono">{part.filePath}</p>
                                  ) : (
                                    <span className="text-gray-400 dark:text-gray-500">-</span>
                                  )}
                                </td>
                                <td className="px-4 py-3 whitespace-nowrap text-right">
                                  <p className="text-sm font-medium text-gray-700">{part.quantity || 1}</p>
                                </td>
                                <td className="px-4 py-3 whitespace-nowrap text-right">
                                  {part.filamentEstimate !== undefined && part.filamentEstimate > 0 ? (
                                    <p className="text-sm font-medium text-gray-700">
                                      {typeof part.filamentEstimate === 'number' 
                                        ? (part.filamentEstimate * (part.quantity || 1)).toFixed(1)
                                        : part.filamentEstimate}g
                                      {(part.quantity || 1) > 1 && (
                                        <span className="text-xs text-gray-500 dark:text-gray-400 ml-1">
                                          ({(typeof part.filamentEstimate === 'number' ? part.filamentEstimate : parseFloat(part.filamentEstimate.replace(/[~g]/g, '').trim()) || 0).toFixed(1)}g × {part.quantity})
                                        </span>
                                      )}
                                    </p>
                                  ) : (
                                    <span className="text-gray-400 dark:text-gray-500">-</span>
                                  )}
                                </td>
                              </tr>
                            );
                          })}
                        </tbody>
                      </table>
                    </div>
                  </div>
                );
              })}
              {(filamentTotals.total > 0 || totalTime !== '0m') && (
                <div className="mt-4 pt-4 border-t border-gray-200 dark:border-gray-700 space-y-2">
                  {filamentTotals.total > 0 && (
                    <div className="space-y-1">
                      <div className="flex justify-between items-center">
                        <span className="font-semibold text-gray-700 dark:text-gray-300">Total Filament Estimate:</span>
                        <span className="font-bold text-gray-900 dark:text-white">{Math.round(filamentTotals.total)}g</span>
                      </div>
                      {filamentTotals.primary > 0 && (
                        <div className="flex justify-between items-center text-sm text-gray-600 dark:text-gray-400 ml-4">
                          <span>Primary ({getColorName(config.primaryColor, 'primary')}):</span>
                          <span>{Math.round(filamentTotals.primary)}g</span>
                        </div>
                      )}
                      {filamentTotals.secondary > 0 && (
                        <div className="flex justify-between items-center text-sm text-gray-600 dark:text-gray-400 ml-4">
                          <span>Secondary ({getColorName(config.accentColor, 'accent')}):</span>
                          <span>{Math.round(filamentTotals.secondary)}g</span>
                        </div>
                      )}
                    </div>
                  )}
                  {totalTime !== '0m' && (
                    <div className="flex justify-between items-center pt-2 border-t border-gray-100 dark:border-gray-800">
                      <span className="font-semibold text-gray-700 dark:text-gray-300">Total Printing Time:</span>
                      <span className="font-bold text-gray-900 dark:text-white">{totalTime}</span>
                    </div>
                  )}
                </div>
              )}
                </div>
              </>
            ) : (
              <div className="text-center py-12 text-gray-500 dark:text-gray-400">
                <p>No printed parts required for this configuration.</p>
              </div>
            )}
          </div>
        )}

        {/* Hardware Tab */}
        {activeTab === 'hardware' && (
          <div className="space-y-6">
            {hardwareParts.length > 0 ? (
              <>
                <div className="border-b border-gray-200 dark:border-gray-700 pb-4">
                  <div className="flex items-center justify-between mb-4">
                    <h3 className="text-lg font-semibold text-gray-900 dark:text-white">Required Hardware Parts</h3>
                    <div className="flex gap-2">
                      <button
                        onClick={() => setHardwareViewMode('unified')}
                        className={`px-3 py-1.5 text-sm font-medium rounded-lg transition-colors ${
                          hardwareViewMode === 'unified'
                            ? 'bg-blue-600 dark:bg-blue-500 text-white'
                            : 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-300 dark:hover:bg-gray-600'
                        }`}
                      >
                        Unified View
                      </button>
                      <button
                        onClick={() => setHardwareViewMode('expanded')}
                        className={`px-3 py-1.5 text-sm font-medium rounded-lg transition-colors ${
                          hardwareViewMode === 'expanded'
                            ? 'bg-blue-600 dark:bg-blue-500 text-white'
                            : 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-300 dark:hover:bg-gray-600'
                        }`}
                      >
                        Expanded View
                      </button>
                    </div>
                  </div>
                </div>
                <div className="space-y-4">
              {hardwareViewMode === 'unified' ? (
                // Unified view: Group by hardware type (Fasteners, Motion Components, etc.)
                Object.entries(hardwareByType).sort(([a], [b]) => {
                  // Sort order: Fasteners, Motion Components, Aluminum Extrusion, Electronics, Other Hardware
                  const order = ['Fasteners', 'Motion Components', 'Aluminum Extrusion', 'Electronics', 'Other Hardware'];
                  const indexA = order.indexOf(a);
                  const indexB = order.indexOf(b);
                  if (indexA === -1 && indexB === -1) return a.localeCompare(b);
                  if (indexA === -1) return 1;
                  if (indexB === -1) return -1;
                  return indexA - indexB;
                }).map(([type, parts]) => (
                  <div key={type}>
                    <h4 className="text-md font-medium text-gray-700 dark:text-gray-300 mb-3">{type}</h4>
                    <div className="overflow-x-auto">
                      <table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-lg">
                        <thead className="bg-gray-50 dark:bg-gray-800">
                          <tr>
                            <th className="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">Part Name</th>
                            <th className="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">Description</th>
                            <th className="px-4 py-3 text-right text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">Quantity</th>
                            <th className="px-4 py-3 text-right text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">Price</th>
                          </tr>
                        </thead>
                        <tbody className="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
                          {parts.map((part) => (
                            <tr key={part.id} className="hover:bg-gray-50 dark:hover:bg-gray-700/50">
                              <td className="px-4 py-3 whitespace-nowrap">
                                <p className="text-sm font-medium text-gray-900 dark:text-white">{part.name}</p>
                              </td>
                              <td className="px-4 py-3">
                                <p className="text-sm text-gray-600 dark:text-gray-300">{part.description || '-'}</p>
                              </td>
                              <td className="px-4 py-3 whitespace-nowrap text-right">
                                <p className="text-sm font-medium text-gray-700 dark:text-gray-300">{part.quantity || 1}</p>
                              </td>
                              <td className="px-4 py-3 whitespace-nowrap text-right">
                                {part.price && part.price > 0 ? (
                                  <p className="text-sm font-medium text-gray-700 dark:text-gray-300">{formatPrice(part.price)}</p>
                                ) : (
                                  <span className="text-gray-400 dark:text-gray-500">-</span>
                                )}
                              </td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    </div>
                  </div>
                ))
              ) : (
                // Expanded view: Group by component BOMs (shows hardware breakdown by component)
                expandedHardwareByComponent.map(({ component, parts }) => (
                  <div key={component}>
                    <h4 className="text-md font-medium text-gray-700 dark:text-gray-300 mb-3">{component}</h4>
                    <div className="overflow-x-auto">
                      <table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-lg">
                        <thead className="bg-gray-50 dark:bg-gray-800">
                          <tr>
                            <th className="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">Part Name</th>
                            <th className="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">Description</th>
                            <th className="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">Type</th>
                            <th className="px-4 py-3 text-right text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">Quantity</th>
                            <th className="px-4 py-3 text-right text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">Price</th>
                          </tr>
                        </thead>
                        <tbody className="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
                          {parts.map((part) => (
                            <tr key={part.id} className="hover:bg-gray-50 dark:hover:bg-gray-700/50">
                              <td className="px-4 py-3 whitespace-nowrap">
                                <p className="text-sm font-medium text-gray-900 dark:text-white">{part.name}</p>
                              </td>
                              <td className="px-4 py-3">
                                <p className="text-sm text-gray-600 dark:text-gray-300">{part.description || '-'}</p>
                              </td>
                              <td className="px-4 py-3 whitespace-nowrap">
                                <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 dark:bg-blue-900/30 text-blue-800 dark:text-blue-300">
                                  {part.hardwareType || 'Other Hardware'}
                                </span>
                              </td>
                              <td className="px-4 py-3 whitespace-nowrap text-right">
                                <p className="text-sm font-medium text-gray-700 dark:text-gray-300">{part.quantity || 1}</p>
                              </td>
                              <td className="px-4 py-3 whitespace-nowrap text-right">
                                {part.price && part.price > 0 ? (
                                  <p className="text-sm font-medium text-gray-700 dark:text-gray-300">{formatPrice(part.price)}</p>
                                ) : (
                                  <span className="text-gray-400 dark:text-gray-500">-</span>
                                )}
                              </td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    </div>
                  </div>
                ))
              )}
            </div>
              </>
            ) : (
              <div className="text-center py-12 text-gray-500 dark:text-gray-400">
                <p>No hardware parts required for this configuration.</p>
              </div>
            )}
          </div>
        )}

        {/* Export & Share Buttons - Show on all tabs */}
        <div className="pt-4 space-y-3">
          <div className="grid grid-cols-2 gap-3">
            {/* Share Button */}
            <button
              onClick={() => {
                try {
                  const shareUrl = createShareLink(config);
                  // Copy to clipboard
                  navigator.clipboard.writeText(shareUrl).then(() => {
                    alert(`Share link copied to clipboard!\n\n${shareUrl}\n\nThis link will expire in 7 days.`);
                  }).catch(() => {
                    // Fallback: show the URL in a prompt
                    prompt('Share link (valid for 7 days):', shareUrl);
                  });
                } catch (error) {
                  console.error('Error creating share link:', error);
                  alert('Error creating share link. Please try again.');
                }
              }}
              className="w-full px-6 py-3 bg-purple-600 dark:bg-purple-500 text-white rounded-lg font-medium hover:bg-purple-700 dark:hover:bg-purple-600 transition-colors"
            >
              Share Link (7 days)
            </button>
            
            {/* Export Button */}
            <button
              onClick={async () => {
                try {
                  setIsExportingZip(true);
                  setZipProgress({ current: 0, total: 0, currentFile: 'Preparing export...' });
                  
                  const zip = new JSZip();
                  
                  // 1. Generate and add markdown overview
                  setZipProgress({ current: 1, total: 100, currentFile: 'Generating overview...' });
                  const markdownOverview = generateMarkdownOverview(
                    config,
                    printedParts,
                    hardwareParts,
                    filamentTotals,
                    totalTime,
                    total
                  );
                  zip.file('README.md', markdownOverview);
                  
                  // 2. Generate and add Excel BOM
                  setZipProgress({ current: 20, total: 100, currentFile: 'Generating BOM...' });
                  const bomWorkbook = generateExcelBOM(hardwareParts, printedParts, config);
                  const bomBuffer = XLSX.write(bomWorkbook, { type: 'array', bookType: 'xlsx' });
                  zip.file('BOM.xlsx', bomBuffer);
                  
                  // 3. Generate and add Excel Print List
                  setZipProgress({ current: 40, total: 100, currentFile: 'Generating print list...' });
                  const printListWorkbook = generateExcelPrintList(printedParts, filamentTotals);
                  const printListBuffer = XLSX.write(printListWorkbook, { type: 'array', bookType: 'xlsx' });
                  zip.file('Print_List.xlsx', printListBuffer);
                  
                  // 4. Download and organize print files by component and colors
                  setZipProgress({ current: 50, total: 100, currentFile: 'Organizing print files...' });
                  const partsToDownload = printedParts.filter(part => part.url && !part.isHardwareOnly);
                  
                  if (partsToDownload.length > 0) {
                    // Convert GitHub blob URLs to raw.githubusercontent.com URLs
                    const convertGitHubUrl = (url) => {
                      if (!url) return url;
                      const blobMatch = url.match(/https:\/\/github\.com\/([^\/]+)\/([^\/]+)\/blob\/([^\/\?]+)\/(.+?)(\?raw=true)?$/);
                      if (blobMatch) {
                        const [, owner, repo, branch, encodedPath] = blobMatch;
                        const decodedPath = decodeURIComponent(encodedPath);
                        const baseUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/`;
                        const urlObj = new URL(decodedPath, baseUrl);
                        return urlObj.href;
                      }
                      return url;
                    };
                    
                    // Download files with concurrency limit
                    const downloadFile = async (part, index) => {
                      try {
                        const progress = 50 + Math.floor((index / partsToDownload.length) * 40);
                        setZipProgress({ 
                          current: progress, 
                          total: 100, 
                          currentFile: `Downloading ${part.filePath || part.name}...` 
                        });
                        
                        const rawUrl = convertGitHubUrl(part.url);
                        const controller = new AbortController();
                        const timeoutId = setTimeout(() => controller.abort(), 30000);
                        
                        const response = await fetch(rawUrl, { signal: controller.signal });
                        clearTimeout(timeoutId);
                        
                        if (!response.ok) {
                          throw new Error(`Failed to download ${part.filePath}: ${response.status} ${response.statusText}`);
                        }
                        const arrayBuffer = await response.arrayBuffer();
                        
                        // Organize by component/color: Print_Files/Component/Color/filename
                        const componentDir = part.category || 'Other';
                        const colourDir = part.colour === 'primary' ? 'Primary' : part.colour === 'secondary' ? 'Accent' : 'Other';
                        const filename = part.filePath || `${part.id}.stl`;
                        const zipPath = `Print_Files/${componentDir}/${colourDir}/${filename}`;
                        
                        zip.file(zipPath, arrayBuffer);
                        return { success: true, part: part.filePath };
                      } catch (error) {
                        if (error.name === 'AbortError') {
                          console.error(`Timeout downloading ${part.filePath}`);
                        } else {
                          console.error(`Error downloading ${part.filePath}:`, error);
                        }
                        return { success: false, part: part.filePath, error: error.message };
                      }
                    };
                    
                    // Download files with concurrency limit (3 at a time)
                    const concurrencyLimit = 3;
                    const results = [];
                    for (let i = 0; i < partsToDownload.length; i += concurrencyLimit) {
                      const batch = partsToDownload.slice(i, i + concurrencyLimit);
                      const batchPromises = batch.map((part, batchIndex) => downloadFile(part, i + batchIndex));
                      const batchResults = await Promise.all(batchPromises);
                      results.push(...batchResults);
                    }
                    
                    const successful = results.filter(r => r.success).length;
                    const failed = results.filter(r => !r.success);
                    
                    if (failed.length > 0) {
                      console.warn(`Failed to download ${failed.length} file(s):`, failed.map(f => f.part));
                    }
                  }
                  
                  // 5. Generate final zip
                  setZipProgress({ current: 95, total: 100, currentFile: 'Creating ZIP file...' });
                  const zipBlob = await zip.generateAsync({ 
                    type: 'blob',
                    compression: 'DEFLATE',
                    compressionOptions: { level: 6 }
                  });
                  
                  // 6. Download
                  setZipProgress({ current: 100, total: 100, currentFile: 'Complete!' });
                  const url = URL.createObjectURL(zipBlob);
                  const a = document.createElement('a');
                  a.href = url;
                  a.download = 'ossm-build-export.zip';
                  a.style.display = 'none';
                  document.body.appendChild(a);
                  
                  await new Promise(resolve => setTimeout(resolve, 100));
                  a.click();
                  
                  setTimeout(() => {
                    document.body.removeChild(a);
                    URL.revokeObjectURL(url);
                  }, 200);
                  
                  setZipProgress({ current: 0, total: 0, currentFile: '' });
                  setIsExportingZip(false);
                } catch (error) {
                  console.error('Error creating export:', error);
                  alert('Error creating export. Please try again.');
                  setZipProgress({ current: 0, total: 0, currentFile: '' });
                  setIsExportingZip(false);
                }
              }}
              disabled={isExportingZip}
              className="w-full px-6 py-3 bg-green-600 dark:bg-green-500 text-white rounded-lg font-medium hover:bg-green-700 dark:hover:bg-green-600 transition-colors disabled:bg-gray-400 dark:disabled:bg-gray-600 disabled:cursor-not-allowed"
            >
              {isExportingZip ? (
                <div className="flex flex-col items-center">
                  <span>Exporting...</span>
                  {zipProgress.total > 0 && (
                    <div className="mt-2 w-full">
                      <div className="flex justify-between text-xs mb-1">
                        <span>{zipProgress.current}%</span>
                      </div>
                      <div className="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2">
                        <div 
                          className="bg-blue-600 dark:bg-blue-500 h-2 rounded-full transition-all duration-300"
                          style={{ width: `${zipProgress.current}%` }}
                        />
                      </div>
                      {zipProgress.currentFile && (
                        <p className="text-xs text-gray-600 dark:text-gray-400 mt-1 truncate">{zipProgress.currentFile}</p>
                      )}
                    </div>
                  )}
                </div>
              ) : (
                'Export All'
              )}
            </button>
          </div>
          
          {/* Legacy export buttons (hidden but kept for backward compatibility) */}
          <div className="text-xs text-gray-500 dark:text-gray-400 text-center">
            Export includes: Overview (Markdown), BOM (Excel), Print List (Excel), and Print Files (organized by component/color)
          </div>
        </div>
      </div>
    </div>
  );
}
