import React from 'react';
import { Img, Video } from '../../engine/components';
import { TimelineElement, DesignMD } from '../../types';
import { ChromaKeyImage } from './ChromaKeyImage';
import { ChromaKeyVideo } from './ChromaKeyVideo';
import { useVideoConfig } from '../../engine/player';

interface ElementRendererProps {
  element: TimelineElement;
  designMD: DesignMD;
  displayContent: string;
  filterStr: string;
  opacity?: number;
  hasContainBg: boolean;
  containBgStyle?: React.CSSProperties;
  ckColor: string;
  ckTolerance: number;
  ckSoftness: number;
}

export const ElementRenderer: React.FC<ElementRendererProps> = ({
  element: el,
  designMD,
  displayContent,
  filterStr,
  hasContainBg,
  containBgStyle,
  ckColor,
  ckTolerance,
  ckSoftness,
}) => {
  const { width } = useVideoConfig();
  const scaleFactor = width / 1080;

  if (el.type === 'text') {
    const fontSize = (el.fontSize ?? 56) * scaleFactor;
    const shadowOffset = (el.shadowOffset ?? 3) * scaleFactor;
    const shadowBlur = (el.shadowBlur ?? 6) * scaleFactor;
    const letterSpacing = el.letterSpacing ? el.letterSpacing * scaleFactor : undefined;
    const strokeWidth = el.textStrokeWidth ? el.textStrokeWidth * scaleFactor : undefined;
    const bgPadding = (el.textBackgroundPadding ?? 8) * scaleFactor;
    const bgRadius = (el.textBackgroundRadius ?? 4) * scaleFactor;

    return (
      <div
        style={{
          fontFamily: el.fontFamily ?? designMD.baseFont,
          color: el.color ?? designMD.textColor,
          fontSize: `${fontSize}px`,
          fontWeight: el.fontWeight ?? 'bold',
          fontStyle: el.fontStyle ?? 'normal',
          textDecoration: el.textDecoration && el.textDecoration !== 'none' ? el.textDecoration : undefined,
          textShadow: `${shadowOffset}px ${shadowOffset}px ${shadowBlur}px ${el.shadowColor ?? 'rgba(0,0,0,0.8)'}`,
          textAlign: el.textAlign ?? 'center',
          lineHeight: el.lineHeight ?? 1.2,
          letterSpacing: letterSpacing ? `${letterSpacing}px` : undefined,
          textTransform: el.textTransform ?? 'none',
          WebkitTextStroke: strokeWidth
            ? `${strokeWidth}px ${el.textStrokeColor ?? '#000000'}`
            : undefined,
          ...(el.textGradient ? {
            background: el.textGradient,
            WebkitBackgroundClip: 'text',
            WebkitTextFillColor: 'transparent',
            backgroundClip: 'text',
          } : el.textBackground ? {
            background: el.textBackground,
            padding: `${bgPadding}px ${bgPadding * 2}px`,
            borderRadius: `${bgRadius}px`,
            display: 'inline-block',
          } : {}),
          whiteSpace: 'pre-wrap',
          userSelect: 'none',
          pointerEvents: 'none',
        }}
      >
        {displayContent}
      </div>
    );
  }

  if (el.type === 'video') {
    const videoContent = el.chromaKeyEnabled ? (
      <ChromaKeyVideo
        src={el.content}
        chromaKeyColor={ckColor}
        chromaKeyTolerance={ckTolerance}
        chromaKeySoftness={ckSoftness}
        playbackRate={el.playbackRate}
        style={{
          width: '100%',
          height: el.height ? '100%' : 'auto',
          objectFit: el.objectFit ?? 'contain',
          objectPosition: el.objectPosition ?? 'center center',
          pointerEvents: 'none',
          userSelect: 'none',
          filter: filterStr,
        }}
      />
    ) : (
      <Video 
        src={el.content}
        volume={el.volume ?? 1}
        playbackRate={el.playbackRate ?? 1}
        startFrom={el.trimStartSec ? Math.round(el.trimStartSec * 30) : undefined}
        endAt={el.trimEndSec ? Math.round(el.trimEndSec * 30) : undefined}
        style={{ 
          width: '100%', 
          height: el.height ? '100%' : 'auto',
          objectFit: el.objectFit ?? 'contain',
          objectPosition: el.objectPosition ?? 'center center', 
          pointerEvents: 'none', 
          userSelect: 'none',
          filter: filterStr,
        }}
      />
    );
    return hasContainBg ? <div style={containBgStyle}>{videoContent}</div> : videoContent;
  }

  if (el.type === 'shape') {
    const sw = el.width ?? 25;
    const fill = el.shapeFill ?? '#ffffff';
    const stroke = el.shapeStroke ?? 'none';
    const strokeW = el.shapeStrokeWidth ?? 0;
    const cr = el.shapeCornerRadius ?? 0;
    const svgStyle: React.CSSProperties = {
      width: '100%',
      pointerEvents: 'none',
      userSelect: 'none',
      filter: filterStr,
    };
    switch (el.shapeType) {
      case 'circle':
        return (
          <svg viewBox="0 0 100 100" style={svgStyle}>
            <circle cx="50" cy="50" r={48 - strokeW / 2} fill={fill} stroke={stroke} strokeWidth={strokeW} />
          </svg>
        );
      case 'triangle':
        return (
          <svg viewBox="0 0 100 100" style={svgStyle}>
            <polygon points="50,2 98,98 2,98" fill={fill} stroke={stroke} strokeWidth={strokeW} strokeLinejoin="round" />
          </svg>
        );
      case 'line':
        return (
          <svg viewBox="0 0 100 10" style={svgStyle} preserveAspectRatio="none">
            <line x1="0" y1="5" x2="100" y2="5" stroke={stroke || fill} strokeWidth={strokeW || 3} strokeLinecap="round" />
          </svg>
        );
      case 'arrow':
        return (
          <svg viewBox="0 0 100 40" style={svgStyle} preserveAspectRatio="none">
            <line x1="0" y1="20" x2="80" y2="20" stroke={stroke || fill} strokeWidth={strokeW || 3} strokeLinecap="round" />
            <polygon points="75,5 100,20 75,35" fill={stroke || fill} />
          </svg>
        );
      case 'star':
        return (
          <svg viewBox="0 0 100 100" style={svgStyle}>
            <polygon points="50,0 61,35 98,35 68,57 79,91 50,70 21,91 32,57 2,35 39,35" fill={fill} stroke={stroke} strokeWidth={strokeW} strokeLinejoin="round" />
          </svg>
        );
      case 'rectangle':
      default:
        return (
          <svg viewBox="0 0 100 100" style={svgStyle}>
            <rect x={strokeW / 2} y={strokeW / 2} width={100 - strokeW} height={100 - strokeW} rx={cr} ry={cr} fill={fill} stroke={stroke} strokeWidth={strokeW} />
          </svg>
        );
    }
  }

  if (el.isPlaceholder) {
    return (
      <div
        style={{
          width: '100%',
          height: el.height ? `${el.height}%` : '100%',
          aspectRatio: el.height ? undefined : '16/9',
          border: '2px dashed rgba(255,255,255,0.2)',
          borderRadius: 8,
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          justifyContent: 'center',
          gap: 6,
          background: 'rgba(255,255,255,0.03)',
          pointerEvents: 'none',
          userSelect: 'none',
        }}
      >
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="rgba(255,255,255,0.25)" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
          <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>
        {el.placeholderLabel && (
          <span style={{ fontSize: 11, color: 'rgba(255,255,255,0.25)', fontFamily: 'system-ui, sans-serif', textAlign: 'center' }}>
            {el.placeholderLabel}
          </span>
        )}
      </div>
    );
  }

  // Fallback to Image
  const imgContent = el.chromaKeyEnabled ? (
    <ChromaKeyImage
      src={el.content}
      chromaKeyColor={ckColor}
      chromaKeyTolerance={ckTolerance}
      chromaKeySoftness={ckSoftness}
      style={{
        width: '100%',
        height: el.height ? '100%' : 'auto',
        objectFit: el.objectFit ?? 'contain',
        objectPosition: el.objectPosition ?? 'center center',
        pointerEvents: 'none',
        userSelect: 'none',
        filter: filterStr,
      }}
      draggable={false}
    />
  ) : (
    <Img 
      src={el.content} 
      style={{ 
        width: '100%', 
        height: el.height ? '100%' : 'auto',
        objectFit: el.objectFit ?? 'contain',
        objectPosition: el.objectPosition ?? 'center center', 
        pointerEvents: 'none', 
        userSelect: 'none',
        filter: filterStr,
      }} 
      draggable={false} 
    />
  );
  return hasContainBg ? <div style={containBgStyle}>{imgContent}</div> : imgContent;
};
