import React, { CSSProperties } from 'react';
import { useNode, Element, UserComponent } from '@craftjs/core';
import { Container } from '../layout/Container';
import { cssPropsToString } from '../../utils/style-helpers';
import { escapeAttr, safeUrl, safeImageUrl } from '../../utils/escape';

/* ---------- Types ---------- */

type VideoType = 'youtube' | 'vimeo' | 'file' | 'none';

interface VideoBlockProps {
  videoUrl?: string;
  videoType?: VideoType;
  embedUrl?: string;
  poster?: string;
  autoplay?: boolean;
  muted?: boolean;
  loop?: boolean;
  controls?: boolean;
  isBackground?: boolean;
  overlayColor?: string;
  overlayOpacity?: number;
  innerMaxWidth?: string;
  style?: CSSProperties;
  children?: React.ReactNode;
  animation?: string;
  animationDelay?: string;
  hideOnDesktop?: boolean;
  hideOnTablet?: boolean;
  hideOnMobile?: boolean;
}

/* ---------- URL detection ---------- */

/**
 * Extract a YouTube video ID from any of the URL shapes WHP users paste:
 * youtu.be/ID, youtube.com/embed/ID, youtube.com/shorts/ID,
 * youtube.com/live/ID (path-based), and youtube.com/watch?...v=ID where `v`
 * may appear anywhere in the query string (not just as the first param).
 */
function extractYouTubeId(url: string): string | null {
  const pathMatch = url.match(
    /(?:youtube\.com\/(?:embed|shorts|live)\/|youtu\.be\/)([a-zA-Z0-9_-]+)/
  );
  if (pathMatch) return pathMatch[1];

  const queryMatch = url.match(/youtube\.com\/watch\?([^\s#]+)/);
  if (queryMatch) {
    const v = new URLSearchParams(queryMatch[1]).get('v');
    if (v) return v;
  }

  return null;
}

function detectVideoType(url: string): { type: VideoType; embedUrl: string } {
  if (!url) return { type: 'none', embedUrl: '' };

  // YouTube
  const ytId = extractYouTubeId(url);
  if (ytId) return { type: 'youtube', embedUrl: `https://www.youtube.com/embed/${ytId}?rel=0` };

  // Vimeo: vimeo.com/ID, or vimeo.com/ID/HASH for unlisted/private videos
  // (the hash becomes the player's `h` query param).
  const vmMatch = url.match(/vimeo\.com\/(\d+)(?:\/([a-zA-Z0-9]+))?/);
  if (vmMatch) {
    const embedUrl = vmMatch[2]
      ? `https://player.vimeo.com/video/${vmMatch[1]}?h=${vmMatch[2]}`
      : `https://player.vimeo.com/video/${vmMatch[1]}`;
    return { type: 'vimeo', embedUrl };
  }

  // Direct file
  if (url.match(/\.(mp4|webm|ogg|mov)(\?|$)/i)) return { type: 'file', embedUrl: url };

  // Uploaded asset (proxy URL)
  if (url.includes('assets-proxy') || url.includes('serve_asset')) return { type: 'file', embedUrl: url };

  return { type: 'none', embedUrl: url };
}

/** Build embed params for YouTube/Vimeo iframes */
function buildEmbedParams(
  baseUrl: string,
  opts: { autoplay?: boolean; muted?: boolean; loop?: boolean; controls?: boolean }
): string {
  const url = new URL(baseUrl);
  if (opts.autoplay) url.searchParams.set('autoplay', '1');
  if (opts.muted) url.searchParams.set('mute', '1');
  if (opts.loop) url.searchParams.set('loop', '1');
  if (opts.controls === false) url.searchParams.set('controls', '0');
  return url.toString();
}

/* ---------- Placeholder ---------- */

const VIDEO_PLACEHOLDER = (
  <div
    style={{
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      flexDirection: 'column',
      gap: 8,
      width: '100%',
      aspectRatio: '16 / 9',
      background: '#27272a',
      borderRadius: 8,
      border: '2px dashed #3f3f46',
      color: '#71717a',
      fontFamily: 'sans-serif',
      fontSize: 14,
      textAlign: 'center' as const,
    }}
  >
    <i className="fa fa-play-circle" style={{ fontSize: 36, opacity: 0.5 }} />
    <span>Add a video URL in settings</span>
  </div>
);

/* ========================================================================
   Normal (non-background) Video Component
   ======================================================================== */

export const VideoBlock: UserComponent<VideoBlockProps> = ({
  videoUrl = '',
  videoType: _videoTypeProp,
  embedUrl: _embedUrlProp,
  poster = '',
  autoplay = false,
  muted = true,
  loop = false,
  controls = true,
  isBackground = false,
  overlayColor = '#000000',
  overlayOpacity = 50,
  innerMaxWidth = '1200px',
  style = {},
}) => {
  const {
    connectors: { connect, drag },
  } = useNode();

  // Detect type from URL
  const { type, embedUrl } = videoUrl ? detectVideoType(videoUrl) : { type: 'none' as VideoType, embedUrl: '' };

  /* ---- Background mode ---- */
  if (isBackground) {
    return (
      <section
        ref={(ref: HTMLElement | null): void => {
          if (ref) connect(drag(ref));
        }}
        style={{
          position: 'relative',
          width: '100%',
          minHeight: '300px',
          overflow: 'hidden',
          ...style,
        }}
      >
        {/* Background video layer */}
        {type === 'file' && embedUrl && (
          <video
            src={embedUrl}
            autoPlay
            muted
            loop
            playsInline
            style={{
              position: 'absolute',
              top: '50%',
              left: '50%',
              minWidth: '100%',
              minHeight: '100%',
              width: 'auto',
              height: 'auto',
              transform: 'translate(-50%, -50%)',
              objectFit: 'cover',
              zIndex: 0,
              pointerEvents: 'none',
            }}
          />
        )}
        {(type === 'youtube' || type === 'vimeo') && embedUrl && (
          <iframe
            src={buildEmbedParams(embedUrl, { autoplay: true, muted: true, loop: true, controls: false })}
            style={{
              position: 'absolute',
              top: '50%',
              left: '50%',
              width: '177.78vh', // 16:9 ratio overflow
              height: '100vh',
              minWidth: '100%',
              minHeight: '100%',
              transform: 'translate(-50%, -50%)',
              border: 'none',
              zIndex: 0,
              pointerEvents: 'none',
            }}
            allow="autoplay; encrypted-media"
            allowFullScreen
          />
        )}
        {type === 'none' && (
          <div
            style={{
              position: 'absolute',
              inset: 0,
              background: '#1e293b',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              color: '#71717a',
              fontSize: 14,
              fontFamily: 'sans-serif',
              zIndex: 0,
            }}
          >
            <i className="fa fa-film" style={{ fontSize: 48, opacity: 0.3 }} />
          </div>
        )}
        {/* Overlay */}
        <div
          style={{
            position: 'absolute',
            inset: 0,
            backgroundColor: overlayColor,
            opacity: (overlayOpacity ?? 50) / 100,
            zIndex: 1,
            pointerEvents: 'none',
          }}
        />
        {/* Content drop zone */}
        <Element
          id="video-bg-inner"
          is={Container}
          canvas
          style={{
            position: 'relative',
            zIndex: 2,
            maxWidth: innerMaxWidth,
            margin: '0 auto',
            padding: '80px 20px',
          }}
          tag="div"
        />
      </section>
    );
  }

  /* ---- Normal mode ---- */
  return (
    <div
      ref={(ref: HTMLDivElement | null): void => {
        if (ref) connect(drag(ref));
      }}
      style={{
        width: '100%',
        ...style,
      }}
    >
      {type === 'none' && VIDEO_PLACEHOLDER}

      {(type === 'youtube' || type === 'vimeo') && (
        <div
          style={{
            position: 'relative',
            aspectRatio: (style as any)?.aspectRatio || '16 / 9',
            overflow: 'hidden',
            borderRadius: (style as any)?.borderRadius || undefined,
          }}
        >
          <iframe
            src={buildEmbedParams(embedUrl, { autoplay, muted, loop, controls })}
            style={{
              position: 'absolute',
              inset: 0,
              width: '100%',
              height: '100%',
              border: 'none',
            }}
            allow="autoplay; encrypted-media; picture-in-picture"
            allowFullScreen
          />
        </div>
      )}

      {type === 'file' && (
        <video
          src={embedUrl}
          poster={poster || undefined}
          autoPlay={autoplay}
          muted={muted}
          loop={loop}
          controls={controls}
          preload="metadata"
          playsInline
          style={{
            display: 'block',
            width: '100%',
            aspectRatio: (style as any)?.aspectRatio || undefined,
            objectFit: 'cover',
            borderRadius: (style as any)?.borderRadius || undefined,
          }}
        />
      )}
    </div>
  );
};

/* ========================================================================
   Craft Config
   ======================================================================== */

VideoBlock.craft = {
  displayName: 'Video',
  props: {
    videoUrl: '',
    videoType: 'none',
    embedUrl: '',
    poster: '',
    autoplay: false,
    muted: true,
    loop: false,
    controls: true,
    isBackground: false,
    overlayColor: '#000000',
    overlayOpacity: 50,
    innerMaxWidth: '1200px',
    style: {
      width: '',
      aspectRatio: '',
      marginTop: '', marginRight: '', marginBottom: '', marginLeft: '',
      paddingTop: '', paddingRight: '', paddingBottom: '', paddingLeft: '',
      border: 'none',
      boxShadow: 'none',
      opacity: '1',
    },
    animation: '',
    animationDelay: '0',
    hideOnDesktop: false,
    hideOnTablet: false,
    hideOnMobile: false,
  },
  rules: {
    canDrag: () => true,
    canMoveIn: () => true,
    canMoveOut: () => true,
  },
};

/* ========================================================================
   HTML Export
   ======================================================================== */

(VideoBlock as any).toHtml = (props: VideoBlockProps, childrenHtml: string) => {
  const {
    videoUrl = '',
    poster = '',
    autoplay = false,
    muted = true,
    loop: doLoop = false,
    controls = true,
    isBackground = false,
    overlayColor = '#000000',
    overlayOpacity = 50,
    innerMaxWidth = '1200px',
    style = {},
  } = props;

  const { type, embedUrl } = videoUrl ? detectVideoType(videoUrl) : { type: 'none' as VideoType, embedUrl: '' };

  /* ---- Background mode export ---- */
  if (isBackground) {
    const outerStyle = cssPropsToString({
      position: 'relative',
      width: '100%',
      minHeight: '300px',
      overflow: 'hidden',
      ...style,
    });
    const overlayStyle = cssPropsToString({
      position: 'absolute',
      inset: '0',
      backgroundColor: overlayColor,
      opacity: String(overlayOpacity / 100),
      zIndex: '1',
      pointerEvents: 'none',
    });
    const innerStyle = cssPropsToString({
      position: 'relative',
      zIndex: '2',
      maxWidth: innerMaxWidth,
      margin: '0 auto',
      padding: '80px 20px',
    });

    let videoHtml = '';
    if (type === 'file' && embedUrl) {
      const vidStyle = cssPropsToString({
        position: 'absolute',
        top: '50%',
        left: '50%',
        minWidth: '100%',
        minHeight: '100%',
        width: 'auto',
        height: 'auto',
        transform: 'translate(-50%, -50%)',
        objectFit: 'cover',
        zIndex: '0',
        pointerEvents: 'none',
      });
      videoHtml = `<video src="${escapeAttr(safeUrl(embedUrl))}" autoplay muted loop playsinline${vidStyle ? ` style="${vidStyle}"` : ''}></video>`;
    } else if ((type === 'youtube' || type === 'vimeo') && embedUrl) {
      const iframeSrc = buildEmbedParams(embedUrl, { autoplay: true, muted: true, loop: true, controls: false });
      const ifrStyle = cssPropsToString({
        position: 'absolute',
        top: '50%',
        left: '50%',
        width: '177.78vh',
        height: '100vh',
        minWidth: '100%',
        minHeight: '100%',
        transform: 'translate(-50%, -50%)',
        border: 'none',
        zIndex: '0',
        pointerEvents: 'none',
      });
      videoHtml = `<iframe src="${escapeAttr(safeUrl(iframeSrc))}" title="Embedded video" allow="autoplay; encrypted-media" allowfullscreen${ifrStyle ? ` style="${ifrStyle}"` : ''}></iframe>`;
    }

    return {
      html: `<section${outerStyle ? ` style="${outerStyle}"` : ''}>${videoHtml}<div${overlayStyle ? ` style="${overlayStyle}"` : ''}></div><div${innerStyle ? ` style="${innerStyle}"` : ''}>${childrenHtml}</div></section>`,
    };
  }

  /* ---- Normal mode export ---- */
  const wrapperStyle = cssPropsToString({ width: '100%', ...style });

  if (type === 'none' || !embedUrl) {
    return { html: '' };
  }

  if (type === 'youtube' || type === 'vimeo') {
    const iframeSrc = buildEmbedParams(embedUrl, { autoplay, muted, loop: doLoop, controls });
    const containerStyle = cssPropsToString({
      position: 'relative',
      aspectRatio: (style as any)?.aspectRatio || '16 / 9',
      overflow: 'hidden',
      borderRadius: (style as any)?.borderRadius || undefined,
    });
    const iframeStyle = cssPropsToString({
      position: 'absolute',
      inset: '0',
      width: '100%',
      height: '100%',
      border: 'none',
    });
    return {
      html: `<div${wrapperStyle ? ` style="${wrapperStyle}"` : ''}><div${containerStyle ? ` style="${containerStyle}"` : ''}><iframe src="${escapeAttr(safeUrl(iframeSrc))}" title="Embedded video" allow="autoplay; encrypted-media; picture-in-picture" allowfullscreen${iframeStyle ? ` style="${iframeStyle}"` : ''}></iframe></div></div>`,
    };
  }

  // Direct file
  const vidAttrs: string[] = [];
  if (autoplay) vidAttrs.push('autoplay');
  if (muted) vidAttrs.push('muted');
  if (doLoop) vidAttrs.push('loop');
  if (controls) vidAttrs.push('controls');
  vidAttrs.push('playsinline');
  const posterAttr = poster ? ` poster="${escapeAttr(safeImageUrl(poster))}"` : '';
  const vidStyle = cssPropsToString({
    display: 'block',
    width: '100%',
    aspectRatio: (style as any)?.aspectRatio || undefined,
    objectFit: 'cover',
    borderRadius: (style as any)?.borderRadius || undefined,
  });

  return {
    html: `<div${wrapperStyle ? ` style="${wrapperStyle}"` : ''}><video src="${escapeAttr(safeUrl(embedUrl))}"${posterAttr} preload="metadata" ${vidAttrs.join(' ')}${vidStyle ? ` style="${vidStyle}"` : ''}></video></div>`,
  };
};
