import React, { CSSProperties, useCallback, useRef, useState } from 'react';
import { useNode, Element, UserComponent } from '@craftjs/core';
import { Container } from '../layout/Container';
import { cssPropsToString } from '../../utils/style-helpers';

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

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

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

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

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

  // YouTube
  const ytMatch = url.match(
    /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]+)/
  );
  if (ytMatch) return { type: 'youtube', embedUrl: `https://www.youtube.com/embed/${ytMatch[1]}?rel=0` };

  // Vimeo
  const vmMatch = url.match(/vimeo\.com\/(\d+)/);
  if (vmMatch) return { type: 'vimeo', embedUrl: `https://player.vimeo.com/video/${vmMatch[1]}` };

  // 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();
}

/* ---------- Upload helper ---------- */

async function uploadToWhp(file: File): Promise<string | null> {
  const cfg = (window as any).WHP_CONFIG;
  if (!cfg) return URL.createObjectURL(file);

  const formData = new FormData();
  formData.append('file', file);
  try {
    const resp = await fetch(`${cfg.apiUrl}?action=upload_asset&site_id=${cfg.siteId}`, {
      method: 'POST',
      headers: { 'X-CSRF-Token': cfg.csrfToken },
      body: formData,
    });
    const data = await resp.json();
    if (data.success && data.url) return data.url;
    return null;
  } catch {
    return null;
  }
}

/* ---------- 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,
  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',
            paddingBottom: '56.25%',
            height: 0,
            overflow: 'hidden',
            borderRadius: (style as any)?.borderRadius || undefined,
          }}
        >
          <iframe
            src={buildEmbedParams(embedUrl, { autoplay, muted, loop, controls })}
            style={{
              position: 'absolute',
              top: 0,
              left: 0,
              width: '100%',
              height: '100%',
              border: 'none',
            }}
            allow="autoplay; encrypted-media; picture-in-picture"
            allowFullScreen
          />
        </div>
      )}

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

/* ========================================================================
   Settings Panel
   ======================================================================== */

const VideoBlockSettings: React.FC = () => {
  const {
    actions: { setProp },
    props,
  } = useNode((node) => ({
    props: node.data.props as VideoBlockProps,
  }));

  const [urlInput, setUrlInput] = useState(props.videoUrl || '');
  const fileInputRef = useRef<HTMLInputElement>(null);

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

  const applyUrl = useCallback(
    (url: string) => {
      const info = detectVideoType(url);
      setProp((p: VideoBlockProps) => {
        p.videoUrl = url;
        p.videoType = info.type;
        p.embedUrl = info.embedUrl;
      });
    },
    [setProp]
  );

  const handleUpload = useCallback(
    async (file: File) => {
      const url = await uploadToWhp(file);
      if (url) {
        setUrlInput(url);
        applyUrl(url);
      }
    },
    [applyUrl]
  );

  const handleBrowse = useCallback(async () => {
    const cfg = (window as any).WHP_CONFIG;
    if (!cfg) return;
    try {
      const resp = await fetch(`${cfg.apiUrl}?action=list_assets&site_id=${cfg.siteId}`);
      const data = await resp.json();
      if (data.success && Array.isArray(data.assets)) {
        const videos = data.assets.filter(
          (a: any) => (a.type || '').startsWith('video') || (a.name || '').match(/\.(mp4|webm|ogg|mov)$/i)
        );
        if (videos.length === 0) {
          alert('No video assets uploaded yet. Use the Upload button to add one.');
          return;
        }
        const names = videos.map((a: any, i: number) => `${i + 1}. ${a.name}`).join('\n');
        const choice = prompt(`Select a video (enter number):\n\n${names}`);
        if (choice) {
          const idx = parseInt(choice, 10) - 1;
          if (videos[idx]) {
            setUrlInput(videos[idx].url);
            applyUrl(videos[idx].url);
          }
        }
      }
    } catch (e) {
      console.error('Browse failed:', e);
    }
  }, [applyUrl]);

  const typeBadge = (label: string, color: string) => (
    <span
      style={{
        display: 'inline-block',
        padding: '2px 8px',
        borderRadius: 4,
        background: color,
        color: '#fff',
        fontSize: 10,
        fontWeight: 600,
        textTransform: 'uppercase',
        letterSpacing: '0.05em',
      }}
    >
      {label}
    </span>
  );

  const overlayPresets = ['#000000', '#1e293b', '#0f172a', '#312e81', '#064e3b', '#7f1d1d'];

  const labelStyle: CSSProperties = { fontSize: 11, color: '#a1a1aa', display: 'block', marginBottom: 4 };
  const inputStyle: CSSProperties = {
    width: '100%',
    padding: '4px 8px',
    background: '#27272a',
    color: '#e4e4e7',
    border: '1px solid #3f3f46',
    borderRadius: 4,
    fontSize: 12,
  };
  const checkboxRowStyle: CSSProperties = {
    display: 'flex',
    alignItems: 'center',
    gap: 6,
    fontSize: 12,
    color: '#e4e4e7',
    cursor: 'pointer',
  };

  return (
    <div style={{ padding: 12, display: 'flex', flexDirection: 'column', gap: 14 }}>
      {/* Video URL */}
      <div>
        <label style={labelStyle}>Video URL</label>
        <div style={{ display: 'flex', gap: 4 }}>
          <input
            type="text"
            value={urlInput}
            onChange={(e) => setUrlInput(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === 'Enter') applyUrl(urlInput);
            }}
            placeholder="YouTube, Vimeo, or direct video URL..."
            style={{ ...inputStyle, flex: 1 }}
          />
          <button
            onClick={() => applyUrl(urlInput)}
            style={{
              padding: '4px 12px',
              fontSize: 11,
              borderRadius: 4,
              cursor: 'pointer',
              border: '1px solid #3f3f46',
              background: '#3b82f6',
              color: '#fff',
              fontWeight: 600,
              whiteSpace: 'nowrap',
            }}
          >
            Apply
          </button>
        </div>

        {/* Detected type badge */}
        {detected.type !== 'none' && (
          <div style={{ marginTop: 6 }}>
            {detected.type === 'youtube' && typeBadge('YouTube', '#dc2626')}
            {detected.type === 'vimeo' && typeBadge('Vimeo', '#1ab7ea')}
            {detected.type === 'file' && typeBadge('Video File', '#16a34a')}
          </div>
        )}
      </div>

      {/* Upload / Browse */}
      <div>
        <div style={{ display: 'flex', gap: 4 }}>
          <button
            onClick={() => fileInputRef.current?.click()}
            style={{
              flex: 1,
              padding: '8px 10px',
              fontSize: 12,
              borderRadius: 4,
              cursor: 'pointer',
              border: '1px solid #3f3f46',
              background: '#3b82f6',
              color: '#fff',
              fontWeight: 500,
            }}
          >
            <i className="fa fa-upload" style={{ marginRight: 4 }} /> Upload
          </button>
          <button
            onClick={handleBrowse}
            style={{
              flex: 1,
              padding: '8px 10px',
              fontSize: 12,
              borderRadius: 4,
              cursor: 'pointer',
              border: '1px solid #3f3f46',
              background: '#27272a',
              color: '#e4e4e7',
            }}
          >
            <i className="fa fa-folder-open" style={{ marginRight: 4 }} /> Browse
          </button>
        </div>
        <input
          ref={fileInputRef}
          type="file"
          accept="video/*"
          style={{ display: 'none' }}
          onChange={(e) => {
            const file = e.target.files?.[0];
            if (file) handleUpload(file);
            e.target.value = '';
          }}
        />
      </div>

      {/* Playback options */}
      <div>
        <label style={labelStyle}>Playback</label>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
          <label style={checkboxRowStyle}>
            <input
              type="checkbox"
              checked={props.autoplay ?? false}
              onChange={(e) => setProp((p: VideoBlockProps) => { p.autoplay = e.target.checked; })}
            />
            Autoplay
          </label>
          <label style={checkboxRowStyle}>
            <input
              type="checkbox"
              checked={props.muted ?? true}
              onChange={(e) => setProp((p: VideoBlockProps) => { p.muted = e.target.checked; })}
            />
            Muted
          </label>
          <label style={checkboxRowStyle}>
            <input
              type="checkbox"
              checked={props.loop ?? false}
              onChange={(e) => setProp((p: VideoBlockProps) => { p.loop = e.target.checked; })}
            />
            Loop
          </label>
          <label style={checkboxRowStyle}>
            <input
              type="checkbox"
              checked={props.controls ?? true}
              onChange={(e) => setProp((p: VideoBlockProps) => { p.controls = e.target.checked; })}
            />
            Show Controls
          </label>
        </div>
      </div>

      {/* Mode toggle */}
      <div>
        <label style={labelStyle}>Display Mode</label>
        <div style={{ display: 'flex', gap: 4 }}>
          <button
            onClick={() => setProp((p: VideoBlockProps) => { p.isBackground = false; })}
            style={{
              flex: 1,
              padding: '6px 10px',
              fontSize: 11,
              borderRadius: 4,
              cursor: 'pointer',
              border: '1px solid #3f3f46',
              background: !props.isBackground ? '#3b82f6' : '#27272a',
              color: !props.isBackground ? '#fff' : '#a1a1aa',
              fontWeight: 500,
            }}
          >
            Normal
          </button>
          <button
            onClick={() => setProp((p: VideoBlockProps) => { p.isBackground = true; })}
            style={{
              flex: 1,
              padding: '6px 10px',
              fontSize: 11,
              borderRadius: 4,
              cursor: 'pointer',
              border: '1px solid #3f3f46',
              background: props.isBackground ? '#3b82f6' : '#27272a',
              color: props.isBackground ? '#fff' : '#a1a1aa',
              fontWeight: 500,
            }}
          >
            Background
          </button>
        </div>
      </div>

      {/* Background mode options */}
      {props.isBackground && (
        <>
          <div>
            <label style={labelStyle}>Overlay Color</label>
            <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap' }}>
              {overlayPresets.map((c) => (
                <button
                  key={c}
                  onClick={() => setProp((p: VideoBlockProps) => { p.overlayColor = c; })}
                  style={{
                    width: 24,
                    height: 24,
                    borderRadius: 4,
                    border: '1px solid #3f3f46',
                    backgroundColor: c,
                    cursor: 'pointer',
                    outline: props.overlayColor === c ? '2px solid #3b82f6' : 'none',
                    outlineOffset: 1,
                  }}
                />
              ))}
            </div>
          </div>

          <div>
            <label style={labelStyle}>
              Overlay Opacity: {props.overlayOpacity ?? 50}%
            </label>
            <input
              type="range"
              min={0}
              max={100}
              value={props.overlayOpacity ?? 50}
              onChange={(e) =>
                setProp((p: VideoBlockProps) => {
                  p.overlayOpacity = parseInt(e.target.value, 10);
                })
              }
              style={{ width: '100%' }}
            />
          </div>

          <div>
            <label style={labelStyle}>Inner Max Width</label>
            <input
              type="text"
              value={props.innerMaxWidth || '1200px'}
              onChange={(e) => setProp((p: VideoBlockProps) => { p.innerMaxWidth = e.target.value; })}
              style={inputStyle}
            />
          </div>
        </>
      )}
    </div>
  );
};

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

VideoBlock.craft = {
  displayName: 'Video',
  props: {
    videoUrl: '',
    videoType: 'none',
    embedUrl: '',
    autoplay: false,
    muted: true,
    loop: false,
    controls: true,
    isBackground: false,
    overlayColor: '#000000',
    overlayOpacity: 50,
    innerMaxWidth: '1200px',
    style: {},
  },
  rules: {
    canDrag: () => true,
    canMoveIn: () => true,
    canMoveOut: () => true,
  },
  related: {
    settings: VideoBlockSettings,
  },
};

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

(VideoBlock as any).toHtml = (props: VideoBlockProps, childrenHtml: string) => {
  const {
    videoUrl = '',
    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="${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="${iframeSrc}" 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',
      paddingBottom: '56.25%',
      height: '0',
      overflow: 'hidden',
      borderRadius: (style as any)?.borderRadius || undefined,
    });
    const iframeStyle = cssPropsToString({
      position: 'absolute',
      top: '0',
      left: '0',
      width: '100%',
      height: '100%',
      border: 'none',
    });
    return {
      html: `<div${wrapperStyle ? ` style="${wrapperStyle}"` : ''}><div${containerStyle ? ` style="${containerStyle}"` : ''}><iframe src="${iframeSrc}" 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 vidStyle = cssPropsToString({
    display: 'block',
    width: '100%',
    borderRadius: (style as any)?.borderRadius || undefined,
  });

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