import React, { RefObject, useEffect } from 'react';
import { Sequence, AbsoluteFill, Img, Video, Audio } from '../../engine/components';
import { useVideoConfig } from '../../engine/player';
import { interpolate } from '../../engine/animation';
import { TimelineElement, TimelineLayer, DesignMD } from '../../types';
import { calculateElementTransitions } from './useTransitions';
import { resolveKeyframes } from './keyframeEngine';
import { ChromaKeyImage } from './ChromaKeyImage';
import { ChromaKeyVideo } from './ChromaKeyVideo';
import type { CanvasActionMode } from './ElementActionToolbar';
import { loadGoogleFont } from '../../utils/googleFontsApi';
import { ElementRenderer } from './ElementRenderer';
import { ElementHandles } from './ElementHandles';

interface CompositionElementProps {
  element: TimelineElement;
  layer: TimelineLayer | undefined;
  designMD: DesignMD;
  frame: number;
  selectedElementId: string | null;
  activeLayerId: string | null;
  activeAction: CanvasActionMode;
  isImageMode?: boolean;
  onElementClick?: (id: string) => void;
  onElementDoubleClick?: (id: string) => void;
  onElementContextMenu?: (id: string, e: React.MouseEvent) => void;
  onDragStart?: (e: React.PointerEvent, id: string, origPos: { x: number; y: number; w: number; h: number; rotation?: number }) => void;
  startResize?: (e: React.PointerEvent, id: string, origPos: { x: number; y: number; w: number; h: number; rotation?: number }) => void;
  startRotate?: (e: React.PointerEvent, id: string, origPos: { x: number; y: number; w: number; h: number; rotation?: number }) => void;
  onElementDuplicate?: (id: string) => void;
  onElementDelete?: (id: string) => void;
  onElementLock?: (id: string) => void;
}

export const CompositionElement: React.FC<CompositionElementProps> = ({
  element: el,
  layer,
  designMD,
  frame,
  selectedElementId,
  activeLayerId,
  activeAction,
  isImageMode = false,
  onElementClick,
  onElementDoubleClick,
  onElementContextMenu,
  onDragStart,
  startResize,
  startRotate,
  onElementDuplicate,
  onElementDelete,
  onElementLock,
}) => {
  // ─── Dynamic font loading for text elements ───
  const fontFamily = el.type === 'text' ? (el.fontFamily ?? designMD.baseFont) : null;
  useEffect(() => {
    if (fontFamily) loadGoogleFont(fontFamily);
  }, [fontFamily]);

  const { width } = useVideoConfig();
  const scaleFactor = width / 1080;

  // In image mode: all non-locked elements are interactive (Photoshop model)
  // In video mode: only elements on the active layer are interactive
  const isInteractive = isImageMode
    ? !el.isLocked
    : (!!activeLayerId && el.layerId === activeLayerId) && !el.isLocked;

  // Skip hidden elements (after all hooks to satisfy Rules of Hooks)
  if (el.isHidden) return null;
  if (el.type === 'text') {
    console.log('[DEBUG TEXT]', {
      id: el.id,
      content: el.content,
      x: el.x, y: el.y,
      opacity: el.opacity,
      layerOpacity: layer?.opacity,
      color: el.color,
      fontSize: el.fontSize,
      fontFamily: fontFamily,
      startFrame: el.startFrame,
      endFrame: el.endFrame,
      currentFrame: frame
    });
  }
  const isSelected = selectedElementId === el.id;
  const layerOpacity = layer?.opacity ?? 1;
  const baseOpacity = ((el.opacity ?? 100) / 100) * layerOpacity;
  
  const currentScale = el.scale ?? 1;
  const currentRot = el.rotation ?? 0;

  const { opacity, transformStr, displayContent } = calculateElementTransitions(
    el, frame, baseOpacity, currentScale, currentRot, undefined, undefined
  );

  // Resolve position — multi-keyframes take priority over legacy animEnd*
  let currentX = el.x;
  let currentY = el.y;

  if (el.keyframes && el.keyframes.length >= 2) {
    // Multi-keyframe: resolve x/y from keyframe engine
    const resolved = resolveKeyframes(el.keyframes, frame, {
      x: el.x, y: el.y,
      scale: currentScale, opacity: baseOpacity, rotation: currentRot,
    });
    currentX = resolved.x;
    currentY = resolved.y;
  } else if (!el.keyframes) {
    // Legacy 2-point keyframes
    if (el.animEndX !== undefined) {
      currentX = interpolate(frame, [el.startFrame, el.endFrame], [el.x, el.animEndX], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' });
    }
    if (el.animEndY !== undefined) {
      currentY = interpolate(frame, [el.startFrame, el.endFrame], [el.y, el.animEndY], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' });
    }
  }

  const isFullscreenBrand = el.isBrandElement && (el.brandDisplayMode ?? 'fullscreen') === 'fullscreen' && el.type === 'video';

  const resolvedBlendMode = (() => {
    // When chroma key is active, transparency is handled by the canvas — no CSS blend needed
    if (el.chromaKeyEnabled) return 'normal';
    if (!el.isBrandElement) return el.blendMode || 'normal';
    if (el.content === designMD.introVideoUrl) return designMD.introBlendMode || el.blendMode || 'normal';
    if (el.content === designMD.outroVideoUrl) return designMD.outroBlendMode || el.blendMode || 'normal';
    return el.blendMode || 'normal';
  })();

  // Chroma key defaults
  const ckColor = el.chromaKeyColor || '#ffffff';
  const ckTolerance = el.chromaKeyTolerance ?? 30;
  const ckSoftness = el.chromaKeySoftness ?? 10;

  const scaledBlurAmount = (el.blurAmount ?? 0) * scaleFactor;
  const filterStr = `brightness(${el.brightness ?? 100}%) contrast(${el.contrast ?? 100}%) saturate(${el.saturation ?? 100}%)${el.hueRotate ? ` hue-rotate(${el.hueRotate}deg)` : ''}${el.sepia ? ` sepia(${el.sepia}%)` : ''}${scaledBlurAmount ? ` blur(${scaledBlurAmount}px)` : ''}`;

  // Contain background: wrap media in a colored container when objectFit='contain' and color is set
  const hasContainBg = (el.objectFit === 'contain' || !el.objectFit) && !!el.containBgColor;
  const containBgStyle: React.CSSProperties | undefined = hasContainBg ? {
    width: '100%',
    height: el.height ? '100%' : 'auto',
    backgroundColor: el.containBgColor!,
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    overflow: 'hidden',
  } : undefined;


  // Adapters for the drag hooks
  const getOrigPos = () => ({
    x: currentX,
    y: currentY,
    w: el.width ?? (el.type === 'text' ? undefined : 25) ?? 25,
    h: el.height ?? 25,
    rotation: currentRot,
  });

  const handleStartDrag = (e: React.PointerEvent) => {
    if (!isInteractive) return;
    e.stopPropagation();
    if (e.button === 2) return;
    if (onElementClick) onElementClick(el.id);

    if (activeAction === 'move' && onDragStart) {
      onDragStart(e, el.id, getOrigPos());
    } else if (activeAction === 'scale' && startResize) {
      startResize(e, el.id, getOrigPos());
    } else if (activeAction === 'rotate' && startRotate) {
      startRotate(e, el.id, getOrigPos());
    }
  };

  const handleScaleDrag = (e: React.PointerEvent) => {
    if (!isInteractive || !startResize) return;
    e.stopPropagation();
    startResize(e, el.id, getOrigPos());
  };

  const handleRotateDrag = (e: React.PointerEvent) => {
    if (!isInteractive || !startRotate) return;
    e.stopPropagation();
    startRotate(e, el.id, getOrigPos());
  };

  // ── Selection outline color ──
  const outlineColor = el.isLocked ? '#d97706' : '#8b5cf6';

  return (
    <Sequence from={el.startFrame} durationInFrames={Math.max(1, el.endFrame - el.startFrame)}>
      {el.type === 'audio' ? ((() => {
          const layerVol = (layer?.volume ?? 100) / 100;
          const elVol = el.volume ?? 1;
          const isMuted = layer?.isMuted === true;

          // Build volume callback for Remotion <Audio>
          const volumeCallback = (f: number) => {
            if (isMuted) return 0;

            let vol = layerVol * elVol;

            // Fade in
            const fadeIn = el.fadeInFrames ?? 0;
            if (fadeIn > 0 && f < fadeIn) {
              vol *= interpolate(f, [0, fadeIn], [0, 1], {
                extrapolateLeft: 'clamp',
                extrapolateRight: 'clamp',
              });
            }

            // Fade out
            const fadeOut = el.fadeOutFrames ?? 0;
            const clipDuration = el.endFrame - el.startFrame;
            if (fadeOut > 0 && f > clipDuration - fadeOut) {
              vol *= interpolate(f, [clipDuration - fadeOut, clipDuration], [1, 0], {
                extrapolateLeft: 'clamp',
                extrapolateRight: 'clamp',
              });
            }

            // Volume keyframes
            const vkfs = el.volumeKeyframes;
            if (vkfs && vkfs.length > 0) {
              const sorted = [...vkfs].sort((a, b) => a.frame - b.frame);
              let before = sorted[0];
              let after = sorted[sorted.length - 1];
              for (let i = 0; i < sorted.length - 1; i++) {
                if (f >= sorted[i].frame && f <= sorted[i + 1].frame) {
                  before = sorted[i];
                  after = sorted[i + 1];
                  break;
                }
              }
              if (f <= before.frame) {
                vol *= before.volume;
              } else if (f >= after.frame) {
                vol *= after.volume;
              } else {
                const kfVol = interpolate(f, [before.frame, after.frame], [before.volume, after.volume], {
                  extrapolateLeft: 'clamp',
                  extrapolateRight: 'clamp',
                });
                vol *= kfVol;
              }
            }

            return Math.max(0, Math.min(1, vol));
          };

          return <Audio src={el.content} volume={volumeCallback} />;
        })()) : isFullscreenBrand ? (
        /* ═══ Fullscreen Brand Video ═══ */
        <AbsoluteFill
          style={{ 
            cursor: isInteractive ? 'pointer' : 'default', 
            pointerEvents: isInteractive ? 'auto' : 'none',
            mixBlendMode: resolvedBlendMode !== 'normal' ? resolvedBlendMode as React.CSSProperties['mixBlendMode'] : undefined,
          }}
          onClick={(e) => {
            e.stopPropagation();
            if (isInteractive && onElementClick) onElementClick(el.id);
          }}
        >
          {/* Positioned container — matches branding preview (PreviewRemotion) */}
          <div style={{
            position: 'absolute',
            left: `${el.x ?? 0}%`,
            top: `${el.y ?? 0}%`,
            width: `${el.w ?? 100}%`,
            height: `${el.h ?? 100}%`,
            overflow: 'hidden',
            borderRadius: (el.w ?? 100) < 100 || (el.h ?? 100) < 100 ? 8 : 0,
            backgroundColor: el.containBgColor || undefined,
          }}>
            {el.chromaKeyEnabled ? (
              <ChromaKeyVideo
                src={el.content}
                chromaKeyColor={ckColor}
                chromaKeyTolerance={ckTolerance}
                chromaKeySoftness={ckSoftness}
                style={{
                  width: '100%',
                  height: '100%',
                  objectFit: (el.objectFit || (() => {
                    if (el.content === designMD.introVideoUrl) return designMD.introVideoFit || 'cover';
                    if (el.content === designMD.outroVideoUrl) return designMD.outroVideoFit || 'cover';
                    return 'cover';
                  })()) as React.CSSProperties['objectFit'],
                  opacity: opacity,
                  filter: filterStr,
                }}
              />
            ) : (
              <Video 
                src={el.content}
                volume={el.volume ?? 1}
                style={{ 
                  width: '100%',
                  height: '100%',
                  objectFit: (el.objectFit || (() => {
                    if (el.content === designMD.introVideoUrl) return designMD.introVideoFit || 'cover';
                    if (el.content === designMD.outroVideoUrl) return designMD.outroVideoFit || 'cover';
                    return 'cover';
                  })()) as React.CSSProperties['objectFit'],
                  opacity: opacity,
                  pointerEvents: 'none',
                  filter: filterStr,
                }}
              />
            )}
          </div>
          {isSelected && (
            <div style={{
              position: 'absolute',
              left: `${el.x ?? 0}%`,
              top: `${el.y ?? 0}%`,
              width: `${el.w ?? 100}%`,
              height: `${el.h ?? 100}%`,
              border: '3px solid #d97706',
              pointerEvents: 'none',
              borderRadius: (el.w ?? 100) < 100 || (el.h ?? 100) < 100 ? 8 : 0,
            }} />
          )}
        </AbsoluteFill>
      ) : (
      /* ═══ Normal Positioned Element ═══ */
      <AbsoluteFill style={{ pointerEvents: 'none' }}>
          <div
            style={{
              position: 'absolute',
              left: `${currentX}%`,
              top: `${currentY}%`,
              width: el.type === 'text' ? (el.width ? `${el.width}%` : undefined) : `${el.width ?? 25}%`,
              height: el.height ? `${el.height}%` : undefined,
              transform: `${transformStr}${el.flipH ? ' scaleX(-1)' : ''}${el.flipV ? ' scaleY(-1)' : ''}`,
              opacity: opacity,
              cursor: isInteractive
                ? (activeAction === 'move'
                    ? 'grab'
                    : activeAction === 'scale' ? 'nwse-resize'
                    : activeAction === 'rotate' ? 'alias'
                    : 'grab')
                : (el.isLocked ? 'not-allowed' : 'default'),
              outline: isSelected ? `${Math.max(1, 3 / currentScale)}px dashed ${outlineColor}` : 'none',
              outlineOffset: `${6 / currentScale}px`,
              pointerEvents: isInteractive || isSelected ? 'auto' : 'none',
              mixBlendMode: resolvedBlendMode !== 'normal' ? resolvedBlendMode as React.CSSProperties['mixBlendMode'] : undefined,
              border: el.borderWidth ? `${el.borderWidth * scaleFactor}px ${el.borderStyle ?? 'solid'} ${el.borderColor ?? '#ffffff'}` : undefined,
              borderRadius: el.borderRadius ? `${el.borderRadius * scaleFactor}px` : undefined,
              overflow: (el.height || el.borderRadius) ? 'hidden' : undefined,
              boxShadow: el.boxShadowBlur || el.boxShadowX || el.boxShadowY
                ? `${(el.boxShadowX ?? 0) * scaleFactor}px ${(el.boxShadowY ?? 4) * scaleFactor}px ${(el.boxShadowBlur ?? 10) * scaleFactor}px ${el.boxShadowColor ?? 'rgba(0,0,0,0.5)'}` 
                : undefined,
            }}
            onClick={(e) => { e.stopPropagation(); }}
            onDoubleClick={(e) => {
              e.stopPropagation();
              if (isInteractive && onElementDoubleClick) onElementDoubleClick(el.id);
            }}
            onContextMenu={(e) => {
              e.preventDefault();
              e.stopPropagation();
              if (isInteractive && onElementContextMenu) onElementContextMenu(el.id, e as unknown as React.MouseEvent);
            }}
            onPointerDown={handleStartDrag}
          >
          {/* ── Visual Content ── */}
          <ElementRenderer 
            element={el}
            designMD={designMD}
            displayContent={displayContent}
            filterStr={filterStr}
            hasContainBg={hasContainBg}
            containBgStyle={containBgStyle}
            ckColor={ckColor}
            ckTolerance={ckTolerance}
            ckSoftness={ckSoftness}
          />

          {/* ── Editor Handles ── */}
          <ElementHandles 
            isSelected={isSelected}
            activeAction={activeAction}
            currentScale={currentScale}
            onScaleDrag={handleScaleDrag}
            onRotateDrag={handleRotateDrag}
          />
        </div>
      </AbsoluteFill>
      )}
    </Sequence>
  );
};
