/**
 * Puck Editor Configuration for CMS
 *
 * This file defines all the components available in the Puck visual editor.
 * Components include: RichText, Accordion, Tabs, Heading, and more.
 */

'use client';

import type { Config, Data } from '@measured/puck';
import React, { useState } from 'react';
import { LexicalField } from './LexicalField';
import { ImagePickerField } from './ImagePickerField';
import { ColorPickerField } from './ColorPickerField';
import { sanitizeHtmlWithSecureLinks, sanitizeHtmlRelaxed } from './sanitize-client';
import {
  parseYouTubeUrl,
  parseVimeoUrl,
  getYouTubeEmbedUrl,
  getVimeoEmbedUrl,
  sanitizeEmbedCode,
  isValidVideoUrl,
  ASPECT_RATIOS,
} from './video-utils';

// ==================== COMPONENT TYPES ====================

export interface RichTextProps {
  content: string;
}

export interface HeadingProps {
  text: string;
  level: 'h2' | 'h3' | 'h4';
  alignment: 'left' | 'center' | 'right';
  fontSize?: number;
  color?: string;
}

export interface AccordionItem {
  id: string;
  title: string;
  content: string;
}

export interface AccordionProps {
  items: AccordionItem[];
  allowMultiple: boolean;
}

export interface TabItem {
  id: string;
  title: string;
  content: string;
}

export interface TabsProps {
  items: TabItem[];
}

export interface SpacerProps {
  size: 'small' | 'medium' | 'large';
}

export interface DividerProps {
  style: 'solid' | 'dashed' | 'dotted';
}

export interface HeroProps {
  headline: string;
  subheadline: string;
  backgroundImage?: string;
  buttonText?: string;
  buttonUrl?: string;
}

export interface ImageProps {
  src: string;
  alt: string;
  width?: 'auto' | 'full' | 'half';
  alignment: 'left' | 'center' | 'right';
  caption?: string;
  linkUrl?: string;
  linkBehavior?: 'navigate' | 'lightbox';
  openInNewTab?: boolean;
}

export interface TwoColumnProps {
  columnRatio: '50-50' | '33-67' | '67-33';
  gap: 'small' | 'medium' | 'large';
  leftColumn: React.FC;
  rightColumn: React.FC;
}

export interface VideoProps {
  embedType: 'youtube' | 'vimeo' | 'url' | 'embed';
  videoId?: string;
  videoUrl?: string;
  embedCode?: string;
  aspectRatio: '16:9' | '4:3' | '1:1' | '9:16';
  autoplay: boolean;
  loop: boolean;
  showControls: boolean;
}

export interface GridProps {
  columns: 2 | 3 | 4;
  gap: 'none' | 'small' | 'medium' | 'large';
  verticalAlign: 'top' | 'center' | 'bottom';
  column1: React.FC;
  column2: React.FC;
  column3?: React.FC;
  column4?: React.FC;
}

export interface HtmlEmbedProps {
  code: string;
}

// ==================== COMPONENT IMPLEMENTATIONS ====================

// RichText Component
function RichTextComponent({ content }: RichTextProps) {
  return (
    <div
      className="cms-rich-text"
      // SECURITY: Content sanitized with DOMPurify to prevent XSS
      dangerouslySetInnerHTML={{
        __html: sanitizeHtmlWithSecureLinks(content || '<p>Enter your content here...</p>'),
      }}
      style={{
        lineHeight: 1.6,
        fontSize: '1rem',
        color: '#000000',
      }}
    />
  );
}

// Heading Component
function HeadingComponent({ text, level, alignment, fontSize, color }: HeadingProps) {
  const Tag = level as 'h2' | 'h3' | 'h4';
  const defaultSizes = {
    h2: 32,
    h3: 24,
    h4: 20,
  };

  const actualSize = fontSize || defaultSizes[level];

  return (
    <Tag
      className="cms-heading"
      style={{
        fontSize: `${actualSize / 16}rem`,
        fontWeight: 600,
        textAlign: alignment,
        marginBottom: '1rem',
        color: color || '#093b66',
        lineHeight: 1.2,
      }}
    >
      {text || 'Heading'}
    </Tag>
  );
}

// Accordion Component
function AccordionComponent({ items, allowMultiple }: AccordionProps) {
  const [openItems, setOpenItems] = useState<string[]>([]);

  const toggleItem = (id: string) => {
    if (allowMultiple) {
      setOpenItems((prev) => (prev.includes(id) ? prev.filter((i) => i !== id) : [...prev, id]));
    } else {
      setOpenItems((prev) => (prev.includes(id) ? [] : [id]));
    }
  };

  if (!items || items.length === 0) {
    return (
      <div style={{ padding: '2rem', textAlign: 'center', color: '#757575' }}>
        Add accordion items to get started
      </div>
    );
  }

  return (
    <div className="cms-accordion" style={{ marginBottom: '1.5rem' }}>
      {items.map((item) => (
        <div
          key={item.id}
          style={{
            border: '1px solid #c6c6c6',
            borderRadius: '8px',
            marginBottom: '0.5rem',
            overflow: 'hidden',
          }}
        >
          <button
            onClick={() => toggleItem(item.id)}
            style={{
              width: '100%',
              padding: '1rem 1.25rem',
              textAlign: 'left',
              background: openItems.includes(item.id) ? '#f0f0f0' : 'white',
              border: 'none',
              cursor: 'pointer',
              display: 'flex',
              justifyContent: 'space-between',
              alignItems: 'center',
              fontSize: '1rem',
              fontWeight: 600,
              color: '#000',
            }}
          >
            {item.title || 'Untitled'}
            <span
              style={{
                color: '#093b66',
                fontSize: '1.25rem',
                fontWeight: 400,
              }}
            >
              {openItems.includes(item.id) ? '−' : '+'}
            </span>
          </button>
          {openItems.includes(item.id) && (
            <div
              style={{
                padding: '1.25rem',
                borderTop: '1px solid #c6c6c6',
                background: 'white',
                color: '#000000',
              }}
              // SECURITY: Content sanitized with DOMPurify to prevent XSS
              dangerouslySetInnerHTML={{
                __html: sanitizeHtmlWithSecureLinks(item.content || ''),
              }}
            />
          )}
        </div>
      ))}
    </div>
  );
}

// Tabs Component
function TabsComponent({ items }: TabsProps) {
  const [activeTab, setActiveTab] = useState(items?.[0]?.id || '');

  if (!items || items.length === 0) {
    return (
      <div style={{ padding: '2rem', textAlign: 'center', color: '#757575' }}>
        Add tab items to get started
      </div>
    );
  }

  const activeItem = items.find((item) => item.id === activeTab) || items[0];

  return (
    <div className="cms-tabs" style={{ marginBottom: '1.5rem' }}>
      <div
        style={{
          display: 'flex',
          borderBottom: '2px solid #c6c6c6',
          marginBottom: '1rem',
        }}
      >
        {items.map((item) => (
          <button
            key={item.id}
            onClick={() => setActiveTab(item.id)}
            style={{
              padding: '0.75rem 1.5rem',
              border: 'none',
              background: 'transparent',
              cursor: 'pointer',
              fontSize: '1rem',
              fontWeight: activeTab === item.id ? 600 : 500,
              color: activeTab === item.id ? '#093b66' : '#757575',
              borderBottom: activeTab === item.id ? '2px solid #093b66' : '2px solid transparent',
              marginBottom: '-2px',
              transition: 'all 0.2s',
            }}
          >
            {item.title || 'Untitled'}
          </button>
        ))}
      </div>
      <div
        style={{ padding: '1.5rem 0', color: '#000000' }}
        // SECURITY: Content sanitized with DOMPurify to prevent XSS
        dangerouslySetInnerHTML={{
          __html: sanitizeHtmlWithSecureLinks(activeItem?.content || ''),
        }}
      />
    </div>
  );
}

// Spacer Component
function SpacerComponent({ size }: SpacerProps) {
  const heights = {
    small: '1rem',
    medium: '2rem',
    large: '4rem',
  };

  return <div className="cms-spacer" style={{ height: heights[size] }} />;
}

// Divider Component
function DividerComponent({ style }: DividerProps) {
  return (
    <hr
      style={{
        border: 'none',
        borderTop: `1px ${style} #c6c6c6`,
        margin: '1.5rem 0',
      }}
    />
  );
}

// Hero Component (currently unused - kept for potential future use)
function _HeroComponent({
  headline,
  subheadline,
  backgroundImage,
  buttonText,
  buttonUrl,
}: HeroProps) {
  return (
    <div
      className="cms-hero"
      style={{
        position: 'relative',
        padding: '5rem 2rem',
        textAlign: 'center',
        color: 'white',
        backgroundImage: backgroundImage ? `url(${backgroundImage})` : 'none',
        backgroundColor: backgroundImage ? undefined : '#1a1a2e',
        backgroundSize: 'cover',
        backgroundPosition: 'center',
      }}
    >
      <div style={{ position: 'relative', zIndex: 10 }}>
        <h2
          style={{
            fontSize: '2.5rem',
            fontWeight: 700,
            marginBottom: '1rem',
          }}
        >
          {headline || 'Welcome'}
        </h2>
        <p
          style={{
            fontSize: '1.25rem',
            marginBottom: '2rem',
            opacity: 0.9,
          }}
        >
          {subheadline || 'Your trusted AMSOIL dealer'}
        </p>
        {buttonText && buttonUrl && (
          <a
            href={buttonUrl}
            style={{
              display: 'inline-block',
              backgroundColor: '#f8981d', // Orange accent from dealer template
              color: '#000000',
              fontWeight: 600,
              padding: '0.75rem 2rem',
              borderRadius: '32.5px', // Pill shape from dealer template
              textDecoration: 'none',
              transition: 'background-color 0.2s, transform 0.2s',
            }}
          >
            {buttonText}
          </a>
        )}
      </div>
      {backgroundImage && (
        <div
          style={{
            position: 'absolute',
            inset: 0,
            backgroundColor: 'black',
            opacity: 0.5,
          }}
        />
      )}
    </div>
  );
}

// Lightbox Modal Component for editor preview
function LightboxModal({
  src,
  alt,
  isOpen,
  onClose,
}: {
  src: string;
  alt: string;
  isOpen: boolean;
  onClose: () => void;
}) {
  // Handle escape key to close
  React.useEffect(() => {
    const handleEscape = (e: KeyboardEvent) => {
      if (e.key === 'Escape' && isOpen) {
        onClose();
      }
    };
    document.addEventListener('keydown', handleEscape);
    return () => document.removeEventListener('keydown', handleEscape);
  }, [isOpen, onClose]);

  if (!isOpen) return null;

  return (
    <div
      style={{
        position: 'fixed',
        inset: 0,
        zIndex: 10000,
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        backgroundColor: 'rgba(0, 0, 0, 0.85)',
      }}
      onClick={onClose}
      role="dialog"
      aria-modal="true"
      aria-label="Image lightbox"
    >
      <button
        type="button"
        onClick={onClose}
        aria-label="Close lightbox"
        style={{
          position: 'absolute',
          top: '20px',
          right: '20px',
          background: 'transparent',
          border: 'none',
          color: 'white',
          fontSize: '2rem',
          cursor: 'pointer',
          padding: '0.5rem',
          lineHeight: 1,
        }}
      >
        &times;
      </button>
      {/* eslint-disable-next-line @next/next/no-img-element -- CMS images use external URLs */}
      <img
        src={src}
        alt={alt}
        onClick={(e) => e.stopPropagation()}
        style={{
          maxWidth: '90vw',
          maxHeight: '85vh',
          objectFit: 'contain',
          borderRadius: '8px',
        }}
      />
    </div>
  );
}

// Image Component
function ImageComponent({
  src,
  alt,
  width,
  alignment,
  caption,
  linkUrl,
  linkBehavior,
  openInNewTab,
}: ImageProps) {
  const [lightboxOpen, setLightboxOpen] = useState(false);

  const widthStyles = {
    auto: 'auto',
    full: '100%',
    half: '50%',
  };

  const alignmentStyles = {
    left: 'flex-start',
    center: 'center',
    right: 'flex-end',
  };

  const hasValidSrc = src && src.trim() !== '';
  const hasLink = linkUrl && linkUrl.trim() !== '';
  const isLightbox = linkBehavior === 'lightbox'; // Lightbox works without requiring a URL

  const imageElement = hasValidSrc ? (
    // eslint-disable-next-line @next/next/no-img-element -- CMS images use external URLs that can't be whitelisted
    <img
      src={src}
      alt={alt || 'Image'}
      style={{
        width: widthStyles[width || 'auto'],
        maxWidth: '100%',
        height: 'auto',
        borderRadius: '8px',
        cursor: isLightbox ? 'zoom-in' : hasLink ? 'pointer' : 'default',
      }}
    />
  ) : (
    <div
      style={{
        width: widthStyles[width || 'auto'],
        minWidth: '200px',
        height: '150px',
        backgroundColor: '#f0f0f0',
        border: '2px dashed #c6c6c6',
        borderRadius: '8px',
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center',
        color: '#757575',
      }}
    >
      <svg
        width="48"
        height="48"
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        strokeWidth="1.5"
      >
        <rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
        <circle cx="8.5" cy="8.5" r="1.5" />
        <polyline points="21 15 16 10 5 21" />
      </svg>
      <span style={{ marginTop: '0.5rem', fontSize: '0.875rem' }}>Select an image</span>
    </div>
  );

  // Wrap in link if linkUrl is provided
  const wrappedImage =
    hasLink && linkBehavior === 'navigate' ? (
      <a
        href={linkUrl}
        target={openInNewTab ? '_blank' : undefined}
        rel={openInNewTab ? 'noopener noreferrer' : undefined}
        style={{ display: 'block' }}
      >
        {imageElement}
      </a>
    ) : isLightbox ? (
      <button
        type="button"
        onClick={() => setLightboxOpen(true)}
        style={{
          border: 'none',
          padding: 0,
          background: 'none',
          cursor: 'zoom-in',
        }}
      >
        {imageElement}
      </button>
    ) : (
      imageElement
    );

  return (
    <>
      <figure
        style={{
          display: 'flex',
          flexDirection: 'column',
          alignItems: alignmentStyles[alignment],
          margin: '1.5rem 0',
        }}
      >
        {wrappedImage}
        {caption && (
          <figcaption
            style={{
              marginTop: '0.5rem',
              fontSize: '0.875rem',
              color: '#757575',
              textAlign: alignment,
            }}
          >
            {caption}
          </figcaption>
        )}
      </figure>
      {isLightbox && hasValidSrc && (
        <LightboxModal
          src={src}
          alt={alt || 'Image'}
          isOpen={lightboxOpen}
          onClose={() => setLightboxOpen(false)}
        />
      )}
    </>
  );
}

// TwoColumn Layout Component
function TwoColumnComponent({
  columnRatio,
  gap,
  leftColumn: LeftColumn,
  rightColumn: RightColumn,
}: TwoColumnProps) {
  const ratioStyles = {
    '50-50': { left: '1fr', right: '1fr' },
    '33-67': { left: '1fr', right: '2fr' },
    '67-33': { left: '2fr', right: '1fr' },
  };

  const gapStyles = {
    small: '1rem',
    medium: '2rem',
    large: '3rem',
  };

  const ratio = ratioStyles[columnRatio];

  return (
    <div
      className="cms-two-column"
      style={{
        display: 'grid',
        gridTemplateColumns: `${ratio.left} ${ratio.right}`,
        gap: gapStyles[gap],
        marginBottom: '1.5rem',
      }}
    >
      <div className="cms-column-left">
        <LeftColumn />
      </div>
      <div className="cms-column-right">
        <RightColumn />
      </div>
    </div>
  );
}

// Video Component
function VideoComponent({
  embedType,
  videoId,
  videoUrl,
  embedCode,
  aspectRatio,
  autoplay,
  loop,
  showControls,
}: VideoProps) {
  const aspectValue = ASPECT_RATIOS[aspectRatio] || '16 / 9';

  const renderContent = () => {
    if (embedType === 'youtube') {
      const id = parseYouTubeUrl(videoId || '');
      if (!id) {
        return (
          <div style={{ padding: '2rem', textAlign: 'center', color: '#757575' }}>
            Enter a valid YouTube URL or video ID
          </div>
        );
      }
      const src = getYouTubeEmbedUrl(id, { autoplay, loop, controls: showControls });
      return (
        <iframe
          src={src}
          style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', border: 'none' }}
          allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
          allowFullScreen
          title="YouTube video"
        />
      );
    }

    if (embedType === 'vimeo') {
      const id = parseVimeoUrl(videoId || '');
      if (!id) {
        return (
          <div style={{ padding: '2rem', textAlign: 'center', color: '#757575' }}>
            Enter a valid Vimeo URL or video ID
          </div>
        );
      }
      const src = getVimeoEmbedUrl(id, { autoplay, loop, controls: showControls });
      return (
        <iframe
          src={src}
          style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', border: 'none' }}
          allow="autoplay; fullscreen; picture-in-picture"
          allowFullScreen
          title="Vimeo video"
        />
      );
    }

    if (embedType === 'url') {
      if (!videoUrl) {
        return (
          <div style={{ padding: '2rem', textAlign: 'center', color: '#757575' }}>
            Enter a video URL
          </div>
        );
      }
      // SECURITY: Validate video URL to prevent dangerous protocols
      if (!isValidVideoUrl(videoUrl)) {
        return (
          <div style={{ padding: '2rem', textAlign: 'center', color: '#dc2626' }}>
            Invalid video URL (javascript: and data: protocols are not allowed)
          </div>
        );
      }
      return (
        <video
          src={videoUrl}
          autoPlay={autoplay}
          muted={autoplay}
          loop={loop}
          controls={showControls}
          style={{
            position: 'absolute',
            inset: 0,
            width: '100%',
            height: '100%',
            objectFit: 'contain',
          }}
        />
      );
    }

    if (embedType === 'embed') {
      const sanitized = sanitizeEmbedCode(embedCode || '');
      if (!sanitized) {
        return (
          <div style={{ padding: '2rem', textAlign: 'center', color: '#757575' }}>
            Enter a valid embed code from YouTube, Vimeo, Wistia, or Loom
          </div>
        );
      }
      return (
        <div
          style={{ position: 'absolute', inset: 0, width: '100%', height: '100%' }}
          dangerouslySetInnerHTML={{ __html: sanitized }}
        />
      );
    }

    return (
      <div style={{ padding: '2rem', textAlign: 'center', color: '#757575' }}>
        Select an embed type to add a video
      </div>
    );
  };

  return (
    <div
      className="cms-video-container"
      style={{
        position: 'relative',
        width: '100%',
        aspectRatio: aspectValue,
        backgroundColor: '#000',
        borderRadius: '8px',
        overflow: 'hidden',
        margin: '1.5rem 0',
      }}
    >
      {renderContent()}
    </div>
  );
}

// Grid Layout Component
function GridComponent({
  columns,
  gap,
  verticalAlign,
  column1: Column1,
  column2: Column2,
  column3: Column3,
  column4: Column4,
}: GridProps) {
  const gapStyles = {
    none: '0',
    small: '1rem',
    medium: '1.5rem',
    large: '2rem',
  };

  const alignStyles = {
    top: 'flex-start',
    center: 'center',
    bottom: 'flex-end',
  };

  const columnCount = columns || 2;
  const columnSlots = [Column1, Column2, Column3, Column4].slice(0, columnCount);

  return (
    <div
      className="cms-grid"
      style={{
        display: 'grid',
        gridTemplateColumns: `repeat(${columnCount}, 1fr)`,
        gap: gapStyles[gap] || '1.5rem',
        alignItems: alignStyles[verticalAlign] || 'flex-start',
        marginBottom: '1.5rem',
      }}
    >
      {columnSlots.map((ColumnSlot, index) => (
        <div key={index} className={`cms-grid-column cms-grid-column-${index + 1}`}>
          {ColumnSlot && <ColumnSlot />}
        </div>
      ))}
    </div>
  );
}

// HTML Embed Component
function HtmlEmbedComponent({ code }: HtmlEmbedProps) {
  if (!code || !code.trim()) {
    return (
      <div
        style={{
          padding: '2rem',
          textAlign: 'center',
          color: '#757575',
          border: '2px dashed #c6c6c6',
          borderRadius: '8px',
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          gap: '0.5rem',
        }}
      >
        <span style={{ fontSize: '2rem', fontFamily: 'monospace' }}>&lt;/&gt;</span>
        <span>Paste HTML embed code</span>
      </div>
    );
  }

  return (
    <div
      className="cms-html-embed"
      // SECURITY: Content sanitized with relaxed DOMPurify allowlist — allows iframes/tables but strips scripts/handlers
      dangerouslySetInnerHTML={{ __html: sanitizeHtmlRelaxed(code) }}
    />
  );
}

// ==================== PUCK CONFIGURATION ====================

// Type-safe wrapper to satisfy Puck's component type requirements
// Puck wraps props with internal types, so we need explicit casts

export const puckConfig: Config = {
  root: {
    fields: {
      title: {
        type: 'text',
        label: 'Page Title',
      },
    },
  },
  components: {
    RichText: {
      label: 'Text',
      fields: {
        content: {
          type: 'custom',
          label: 'Content',
          render: ({ value, onChange }) => (
            <LexicalField value={value || ''} onChange={onChange} enableMediaLibrary />
          ),
        },
      },
      defaultProps: {
        content:
          '<p>Enter your content here. You can use <strong>bold</strong>, <em>italic</em>, and <a href="#">links</a>.</p>',
      },
      render: RichTextComponent as any,
    },

    Heading: {
      fields: {
        text: {
          type: 'text',
          label: 'Heading Text',
        },
        level: {
          type: 'select',
          label: 'Heading Level',
          options: [
            { label: 'H2 - Section Heading', value: 'h2' },
            { label: 'H3 - Subsection', value: 'h3' },
            { label: 'H4 - Minor Heading', value: 'h4' },
          ],
        },
        alignment: {
          type: 'select',
          label: 'Alignment',
          options: [
            { label: 'Left', value: 'left' },
            { label: 'Center', value: 'center' },
            { label: 'Right', value: 'right' },
          ],
        },
        fontSize: {
          type: 'number',
          label: 'Font Size (px)',
          min: 12,
          max: 72,
        },
        color: {
          type: 'custom',
          label: 'Color',
          render: ({ value, onChange }) => (
            <ColorPickerField value={value || '#093b66'} onChange={onChange} />
          ),
        },
      },
      defaultProps: {
        text: 'New Heading',
        level: 'h2',
        alignment: 'left',
        fontSize: 32,
        color: '#093b66',
      },
      render: HeadingComponent as any,
    },

    Accordion: {
      fields: {
        items: {
          type: 'array',
          label: 'Accordion Items',
          arrayFields: {
            title: {
              type: 'text',
              label: 'Title',
            },
            content: {
              type: 'custom',
              label: 'Content',
              render: ({ value, onChange }) => (
                <LexicalField value={value || ''} onChange={onChange} enableMediaLibrary />
              ),
            },
          },
          defaultItemProps: {
            title: '',
            content: '',
          },
          getItemSummary: (item: AccordionItem) => item.title || 'Untitled Item',
        },
        allowMultiple: {
          type: 'radio',
          label: 'Allow Multiple Open',
          options: [
            { label: 'Yes', value: true },
            { label: 'No', value: false },
          ],
        },
      },
      defaultProps: {
        items: [
          {
            id: '',
            title: 'First Question',
            content: '<p>Answer to the first question.</p>',
          },
          {
            id: '',
            title: 'Second Question',
            content: '<p>Answer to the second question.</p>',
          },
        ],
        allowMultiple: false,
      },
      resolveData: async ({ props }) => {
        // Ensure every item has a unique ID
        const items = props.items?.map((item: AccordionItem) => ({
          ...item,
          id: item.id || crypto.randomUUID(),
        }));
        return { props: { ...props, items } };
      },
      render: AccordionComponent as any,
    },

    Tabs: {
      fields: {
        items: {
          type: 'array',
          label: 'Tab Items',
          arrayFields: {
            title: {
              type: 'text',
              label: 'Tab Title',
            },
            content: {
              type: 'custom',
              label: 'Content',
              render: ({ value, onChange }) => (
                <LexicalField value={value || ''} onChange={onChange} enableMediaLibrary />
              ),
            },
          },
          defaultItemProps: {
            title: '',
            content: '',
          },
          getItemSummary: (item: TabItem) => item.title || 'Untitled Tab',
        },
      },
      defaultProps: {
        items: [
          {
            id: '',
            title: 'Tab 1',
            content: '<p>Content for tab 1.</p>',
          },
          {
            id: '',
            title: 'Tab 2',
            content: '<p>Content for tab 2.</p>',
          },
        ],
      },
      resolveData: async ({ props }) => {
        // Ensure every item has a unique ID
        const items = props.items?.map((item: TabItem) => ({
          ...item,
          id: item.id || crypto.randomUUID(),
        }));
        return { props: { ...props, items } };
      },
      render: TabsComponent as any,
    },

    Spacer: {
      fields: {
        size: {
          type: 'select',
          label: 'Size',
          options: [
            { label: 'Small (16px)', value: 'small' },
            { label: 'Medium (32px)', value: 'medium' },
            { label: 'Large (64px)', value: 'large' },
          ],
        },
      },
      defaultProps: {
        size: 'medium',
      },
      render: SpacerComponent as any,
    },

    Divider: {
      fields: {
        style: {
          type: 'select',
          label: 'Line Style',
          options: [
            { label: 'Solid', value: 'solid' },
            { label: 'Dashed', value: 'dashed' },
            { label: 'Dotted', value: 'dotted' },
          ],
        },
      },
      defaultProps: {
        style: 'solid',
      },
      render: DividerComponent as any,
    },

    Image: {
      fields: {
        src: {
          type: 'custom',
          label: 'Image',
          render: ({ value, onChange }) => (
            <ImagePickerField value={value || ''} onChange={onChange} />
          ),
        },
        alt: {
          type: 'text',
          label: 'Alt Text',
        },
        width: {
          type: 'select',
          label: 'Width',
          options: [
            { label: 'Auto', value: 'auto' },
            { label: 'Full Width', value: 'full' },
            { label: 'Half Width', value: 'half' },
          ],
        },
        alignment: {
          type: 'select',
          label: 'Alignment',
          options: [
            { label: 'Left', value: 'left' },
            { label: 'Center', value: 'center' },
            { label: 'Right', value: 'right' },
          ],
        },
        caption: {
          type: 'text',
          label: 'Caption (optional)',
        },
        linkBehavior: {
          type: 'select',
          label: 'Click Behavior',
          options: [
            { label: 'None', value: 'none' },
            { label: 'Navigate to URL', value: 'navigate' },
            { label: 'Open in Lightbox', value: 'lightbox' },
          ],
        },
        linkUrl: {
          type: 'text',
          label: 'Link URL',
        },
        openInNewTab: {
          type: 'radio',
          label: 'Open in New Tab',
          options: [
            { label: 'Yes', value: true },
            { label: 'No', value: false },
          ],
        },
      },
      defaultProps: {
        src: '',
        alt: 'Image',
        width: 'auto',
        alignment: 'center',
        caption: '',
        linkBehavior: 'none',
        linkUrl: '',
        openInNewTab: false,
      },
      // Conditionally show link fields only when "Navigate to URL" is selected
      resolveFields: (data) => {
        const baseFields = {
          src: {
            type: 'custom' as const,
            label: 'Image',
            render: ({ value, onChange }: { value: string; onChange: (value: string) => void }) => (
              <ImagePickerField value={value || ''} onChange={onChange} />
            ),
          },
          alt: {
            type: 'text' as const,
            label: 'Alt Text',
          },
          width: {
            type: 'select' as const,
            label: 'Width',
            options: [
              { label: 'Auto', value: 'auto' },
              { label: 'Full Width', value: 'full' },
              { label: 'Half Width', value: 'half' },
            ],
          },
          alignment: {
            type: 'select' as const,
            label: 'Alignment',
            options: [
              { label: 'Left', value: 'left' },
              { label: 'Center', value: 'center' },
              { label: 'Right', value: 'right' },
            ],
          },
          caption: {
            type: 'text' as const,
            label: 'Caption (optional)',
          },
          linkBehavior: {
            type: 'select' as const,
            label: 'Click Behavior',
            options: [
              { label: 'None', value: 'none' },
              { label: 'Navigate to URL', value: 'navigate' },
              { label: 'Open in Lightbox', value: 'lightbox' },
            ],
          },
        };

        // Only show linkUrl and openInNewTab when "Navigate to URL" is selected
        if (data.props.linkBehavior === 'navigate') {
          return {
            ...baseFields,
            linkUrl: {
              type: 'text' as const,
              label: 'Link URL',
            },
            openInNewTab: {
              type: 'radio' as const,
              label: 'Open in New Tab',
              options: [
                { label: 'Yes', value: true },
                { label: 'No', value: false },
              ],
            },
          };
        }

        return baseFields;
      },
      render: ImageComponent as any,
    },

    TwoColumn: {
      label: 'Two Column',
      fields: {
        columnRatio: {
          type: 'select',
          label: 'Column Ratio',
          options: [
            { label: 'Equal (50/50)', value: '50-50' },
            { label: 'Narrow/Wide (33/67)', value: '33-67' },
            { label: 'Wide/Narrow (67/33)', value: '67-33' },
          ],
        },
        gap: {
          type: 'select',
          label: 'Gap',
          options: [
            { label: 'Small', value: 'small' },
            { label: 'Medium', value: 'medium' },
            { label: 'Large', value: 'large' },
          ],
        },
        leftColumn: {
          type: 'slot',
        },
        rightColumn: {
          type: 'slot',
        },
      },
      defaultProps: {
        columnRatio: '50-50',
        gap: 'medium',
        leftColumn: [],
        rightColumn: [],
      },
      render: TwoColumnComponent as any,
    },

    Video: {
      label: 'Video',
      fields: {
        embedType: {
          type: 'select',
          label: 'Video Source',
          options: [
            { label: 'YouTube', value: 'youtube' },
            { label: 'Vimeo', value: 'vimeo' },
            { label: 'Direct URL (MP4/WebM)', value: 'url' },
            { label: 'Custom Embed Code', value: 'embed' },
          ],
        },
        videoId: {
          type: 'text',
          label: 'Video ID or URL',
        },
        videoUrl: {
          type: 'text',
          label: 'Video URL',
        },
        embedCode: {
          type: 'textarea',
          label: 'Embed Code',
        },
        aspectRatio: {
          type: 'select',
          label: 'Aspect Ratio',
          options: [
            { label: '16:9 (Widescreen)', value: '16:9' },
            { label: '4:3 (Standard)', value: '4:3' },
            { label: '1:1 (Square)', value: '1:1' },
            { label: '9:16 (Vertical)', value: '9:16' },
          ],
        },
        autoplay: {
          type: 'radio',
          label: 'Autoplay (muted)',
          options: [
            { label: 'Yes', value: true },
            { label: 'No', value: false },
          ],
        },
        loop: {
          type: 'radio',
          label: 'Loop',
          options: [
            { label: 'Yes', value: true },
            { label: 'No', value: false },
          ],
        },
        showControls: {
          type: 'radio',
          label: 'Show Controls',
          options: [
            { label: 'Yes', value: true },
            { label: 'No', value: false },
          ],
        },
      },
      defaultProps: {
        embedType: 'youtube',
        videoId: '',
        videoUrl: '',
        embedCode: '',
        aspectRatio: '16:9',
        autoplay: false,
        loop: false,
        showControls: true,
      },
      // Conditionally show fields based on embedType selection
      resolveFields: (data) => {
        const baseFields = {
          embedType: {
            type: 'select' as const,
            label: 'Video Source',
            options: [
              { label: 'YouTube', value: 'youtube' },
              { label: 'Vimeo', value: 'vimeo' },
              { label: 'Direct URL (MP4/WebM)', value: 'url' },
              { label: 'Custom Embed Code', value: 'embed' },
            ],
          },
          aspectRatio: {
            type: 'select' as const,
            label: 'Aspect Ratio',
            options: [
              { label: '16:9 (Widescreen)', value: '16:9' },
              { label: '4:3 (Standard)', value: '4:3' },
              { label: '1:1 (Square)', value: '1:1' },
              { label: '9:16 (Vertical)', value: '9:16' },
            ],
          },
          autoplay: {
            type: 'radio' as const,
            label: 'Autoplay (muted)',
            options: [
              { label: 'Yes', value: true },
              { label: 'No', value: false },
            ],
          },
          loop: {
            type: 'radio' as const,
            label: 'Loop',
            options: [
              { label: 'Yes', value: true },
              { label: 'No', value: false },
            ],
          },
          showControls: {
            type: 'radio' as const,
            label: 'Show Controls',
            options: [
              { label: 'Yes', value: true },
              { label: 'No', value: false },
            ],
          },
        };

        // Show different input field based on selected video source
        if (data.props.embedType === 'youtube' || data.props.embedType === 'vimeo') {
          return {
            ...baseFields,
            videoId: {
              type: 'text' as const,
              label:
                data.props.embedType === 'youtube'
                  ? 'YouTube Video ID or URL'
                  : 'Vimeo Video ID or URL',
            },
          };
        } else if (data.props.embedType === 'url') {
          return {
            ...baseFields,
            videoUrl: {
              type: 'text' as const,
              label: 'Video URL (MP4, WebM, etc.)',
            },
          };
        } else if (data.props.embedType === 'embed') {
          return {
            ...baseFields,
            embedCode: {
              type: 'textarea' as const,
              label: 'Paste Embed Code (iframe from YouTube, Vimeo, etc.)',
            },
          };
        }

        return baseFields;
      },
      render: VideoComponent as any,
    },

    HtmlEmbed: {
      label: 'HTML Embed',
      fields: {
        code: {
          type: 'textarea',
          label: 'HTML Code',
        },
      },
      defaultProps: {
        code: '',
      },
      render: HtmlEmbedComponent as any,
    },

    Grid: {
      label: 'Grid Layout',
      fields: {
        columns: {
          type: 'select',
          label: 'Number of Columns',
          options: [
            { label: '2 Columns', value: 2 },
            { label: '3 Columns', value: 3 },
            { label: '4 Columns', value: 4 },
          ],
        },
        gap: {
          type: 'select',
          label: 'Gap',
          options: [
            { label: 'None', value: 'none' },
            { label: 'Small', value: 'small' },
            { label: 'Medium', value: 'medium' },
            { label: 'Large', value: 'large' },
          ],
        },
        verticalAlign: {
          type: 'select',
          label: 'Vertical Alignment',
          options: [
            { label: 'Top', value: 'top' },
            { label: 'Center', value: 'center' },
            { label: 'Bottom', value: 'bottom' },
          ],
        },
        column1: {
          type: 'slot',
        },
        column2: {
          type: 'slot',
        },
        column3: {
          type: 'slot',
        },
        column4: {
          type: 'slot',
        },
      },
      defaultProps: {
        columns: 2,
        gap: 'medium',
        verticalAlign: 'top',
        column1: [],
        column2: [],
        column3: [],
        column4: [],
      },
      render: GridComponent as any,
    },

    // Hero temporarily disabled - padding/margin issues with dropzone
    // Hero: {
    //   fields: {
    //     headline: {
    //       type: 'text',
    //       label: 'Headline',
    //     },
    //     subheadline: {
    //       type: 'text',
    //       label: 'Subheadline',
    //     },
    //     backgroundImage: {
    //       type: 'text',
    //       label: 'Background Image URL',
    //     },
    //     buttonText: {
    //       type: 'text',
    //       label: 'Button Text',
    //     },
    //     buttonUrl: {
    //       type: 'text',
    //       label: 'Button URL',
    //     },
    //   },
    //   defaultProps: {
    //     headline: 'Welcome to Our Site',
    //     subheadline: 'Your trusted AMSOIL dealer',
    //     buttonText: 'Shop Now',
    //     buttonUrl: '#',
    //   },
    //   render: HeroComponent as any,
    // },
  },
  categories: {
    content: {
      title: 'Content',
      components: ['Heading', 'RichText', 'Image', 'Video', 'HtmlEmbed'],
    },
    interactive: {
      title: 'Interactive',
      components: ['Accordion', 'Tabs'],
    },
    layout: {
      title: 'Layout',
      components: ['Grid', 'TwoColumn', 'Spacer', 'Divider'],
    },
  },
};

// Export types for external use
export type PuckData = Data;
export type { Config };
