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

const PLACEHOLDER_SRC = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='300'%3E%3Cdefs%3E%3ClinearGradient id='bg' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0%25' stop-color='%23f1f5f9'/%3E%3Cstop offset='100%25' stop-color='%23e2e8f0'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect fill='url(%23bg)' width='400' height='300' rx='12'/%3E%3Crect x='2' y='2' width='396' height='296' rx='10' fill='none' stroke='%23cbd5e1' stroke-width='2' stroke-dasharray='8 4'/%3E%3Cg transform='translate(200,110)'%3E%3Crect x='-28' y='-28' width='56' height='56' rx='12' fill='%23cbd5e1' opacity='0.5'/%3E%3Cpath d='M-12 8 L-4 -2 L2 4 L8 -6 L16 8Z' fill='%2394a3b8'/%3E%3Ccircle cx='-6' cy='-10' r='5' fill='%2394a3b8'/%3E%3C/g%3E%3Ctext x='200' y='160' text-anchor='middle' fill='%2364748b' font-family='Inter,sans-serif' font-size='15' font-weight='500'%3EDrop image here%3C/text%3E%3Ctext x='200' y='182' text-anchor='middle' fill='%2394a3b8' font-family='Inter,sans-serif' font-size='12'%3Eor click to upload%3C/text%3E%3C/svg%3E";

interface ImageBlockProps {
  src?: string;
  alt?: string;
  style?: CSSProperties;
}

// Helper: upload a file to the WHP API and return the proxy URL
async function uploadToWhp(file: File): Promise<string | null> {
  const cfg = (window as any).WHP_CONFIG;
  if (!cfg) return URL.createObjectURL(file); // Standalone fallback

  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; }
}

export const ImageBlock: UserComponent<ImageBlockProps> = ({
  src = PLACEHOLDER_SRC,
  alt = '',
  style = {},
}) => {
  const {
    connectors: { connect, drag },
    selected,
    actions: { setProp },
  } = useNode((node) => ({ selected: node.events.selected }));

  const imgRef = useRef<HTMLImageElement | null>(null);
  const isPlaceholder = !src || src === PLACEHOLDER_SRC || src.startsWith('data:image/svg');

  // Handle drag-and-drop of files directly onto the image
  const handleDrop = useCallback(async (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    const file = e.dataTransfer.files?.[0];
    if (file && file.type.startsWith('image/')) {
      const url = await uploadToWhp(file);
      if (url) setProp((p: ImageBlockProps) => { p.src = url; });
    }
  }, [setProp]);

  const handleDragOver = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    e.dataTransfer.dropEffect = 'copy';
  }, []);

  return (
    <img
      ref={(ref: HTMLImageElement | null) => {
        imgRef.current = ref;
        if (ref) connect(drag(ref));
      }}
      src={src}
      alt={alt || 'Image'}
      onDrop={handleDrop}
      onDragOver={handleDragOver}
      style={{
        display: 'block',
        maxWidth: '100%',
        outline: 'none',
        cursor: selected ? 'move' : 'pointer',
        ...style,
      }}
    />
  );
};

/* ---------- Helpers for parsing CSS unit values ---------- */

type SizeUnit = 'px' | '%' | 'auto';

function parseSizeValue(value: string | number | undefined): { num: string; unit: SizeUnit } {
  if (!value || value === 'auto') return { num: '', unit: 'auto' };
  const str = String(value);
  if (str === 'auto') return { num: '', unit: 'auto' };
  const match = str.match(/^(\d+(?:\.\d+)?)\s*(px|%)$/);
  if (match) return { num: match[1], unit: match[2] as SizeUnit };
  // Pure number = px
  if (/^\d+(?:\.\d+)?$/.test(str)) return { num: str, unit: 'px' };
  return { num: '', unit: 'px' };
}

function buildSizeString(num: string, unit: SizeUnit): string | undefined {
  if (unit === 'auto') return 'auto';
  if (!num) return undefined;
  return `${num}${unit}`;
}

type Alignment = 'left' | 'center' | 'right';

function detectAlignment(style: CSSProperties | undefined): Alignment {
  if (!style) return 'left';
  const ml = style.marginLeft;
  const mr = style.marginRight;
  if (ml === 'auto' && mr === 'auto') return 'center';
  if (ml === 'auto' && mr !== 'auto') return 'right';
  return 'left';
}

/* ---------- Settings panel ---------- */

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

  const isPlaceholder = !props.src || props.src === PLACEHOLDER_SRC || props.src?.startsWith('data:image/svg');
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [showBrowser, setShowBrowser] = useState(false);
  const [browserAssets, setBrowserAssets] = useState<any[]>([]);
  const [browserLoading, setBrowserLoading] = useState(false);

  // Sizing unit state
  const widthParsed = parseSizeValue(props.style?.width);
  const [widthUnit, setWidthUnit] = useState<SizeUnit>(widthParsed.unit === 'auto' ? 'px' : widthParsed.unit);
  const heightParsed = parseSizeValue(props.style?.height);
  const [heightUnit, setHeightUnit] = useState<SizeUnit>(heightParsed.unit === 'auto' ? 'px' : heightParsed.unit);
  const maxWidthParsed = parseSizeValue(props.style?.maxWidth);
  const [maxWidthUnit, setMaxWidthUnit] = useState<SizeUnit>(maxWidthParsed.unit === 'auto' ? '%' : maxWidthParsed.unit);

  const alignment = detectAlignment(props.style);

  const handleUpload = useCallback(async (file: File) => {
    const url = await uploadToWhp(file);
    if (url) setProp((p: ImageBlockProps) => { p.src = url; });
  }, [setProp]);

  const handleBrowse = useCallback(async () => {
    if (showBrowser) { setShowBrowser(false); return; }
    const cfg = (window as any).WHP_CONFIG;
    if (!cfg) return;
    setBrowserLoading(true);
    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 images = data.assets.filter((a: any) => (a.type || '').startsWith('image'));
        setBrowserAssets(images);
        setShowBrowser(true);
      }
    } catch (e) {
      console.error('Browse failed:', e);
    } finally {
      setBrowserLoading(false);
    }
  }, [showBrowser]);

  const radiusPresets = ['0', '8px', '16px', '32px', '50%'];

  const setPropStyle = useCallback((key: string, value: string | undefined) => {
    setProp((p: ImageBlockProps) => {
      p.style = { ...p.style, [key]: value };
    });
  }, [setProp]);

  const setAlignment = useCallback((align: Alignment) => {
    setProp((p: ImageBlockProps) => {
      const s = { ...p.style };
      if (align === 'center') {
        s.marginLeft = 'auto';
        s.marginRight = 'auto';
        s.display = 'block';
      } else if (align === 'right') {
        s.marginLeft = 'auto';
        s.marginRight = undefined;
        s.display = 'block';
      } else {
        s.marginLeft = undefined;
        s.marginRight = undefined;
        s.display = 'block';
      }
      p.style = s;
    });
  }, [setProp]);

  // Extract friendly filename from URL
  const getFriendlyName = (src: string) => {
    const match = src.match(/filename=([^&]+)/);
    if (match) return decodeURIComponent(match[1]).replace(/^\d+_[a-f0-9]+_/, '');
    return src.split('/').pop() || 'image';
  };

  const labelStyle: CSSProperties = { fontSize: 11, color: '#a1a1aa', display: 'block', marginBottom: 4 };
  const inputStyle: CSSProperties = { flex: 1, minWidth: 0, padding: '4px 6px', background: '#27272a', color: '#e4e4e7', border: '1px solid #3f3f46', borderRadius: 4, fontSize: 12 };
  const selectStyle: CSSProperties = { padding: '4px 2px', background: '#27272a', color: '#e4e4e7', border: '1px solid #3f3f46', borderRadius: 4, fontSize: 11, cursor: 'pointer' };
  const btnStyle = (active: boolean): CSSProperties => ({
    flex: 1, padding: '4px', fontSize: 11, borderRadius: 4, cursor: 'pointer',
    border: '1px solid #3f3f46',
    background: active ? '#3b82f6' : '#27272a',
    color: active ? '#fff' : '#a1a1aa',
  });

  return (
    <div style={{ padding: 12, display: 'flex', flexDirection: 'column', gap: 12 }}>
      {/* Image preview */}
      <div>
        <label style={labelStyle}>Image Source</label>

        {!isPlaceholder ? (
          <>
            {/* Current image thumbnail + filename + remove */}
            <div style={{ marginBottom: 8, borderRadius: 6, overflow: 'hidden', border: '1px solid #3f3f46', position: 'relative' }}>
              <img src={props.src} alt="" style={{ width: '100%', height: 'auto', display: 'block', maxHeight: 150, objectFit: 'cover' }} />
              <button onClick={() => setProp((p: ImageBlockProps) => { p.src = PLACEHOLDER_SRC; })}
                style={{ position: 'absolute', top: 4, right: 4, width: 24, height: 24, borderRadius: '50%', background: 'rgba(0,0,0,0.7)', border: 'none', color: '#fff', cursor: 'pointer', fontSize: 12, display: 'flex', alignItems: 'center', justifyContent: 'center' }}
                title="Remove image">
                <i className="fa fa-times" />
              </button>
            </div>
            <div style={{ fontSize: 11, color: '#a1a1aa', marginBottom: 8, display: 'flex', alignItems: 'center', gap: 4 }}>
              <i className="fa fa-check-circle" style={{ color: '#10b981' }} />
              <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{getFriendlyName(props.src || '')}</span>
            </div>
          </>
        ) : (
          /* Drop zone when no image set */
          <div
            style={{ padding: '20px 12px', border: '2px dashed #3f3f46', borderRadius: 6, textAlign: 'center', color: '#71717a', fontSize: 12, cursor: 'pointer', marginBottom: 8, transition: 'border-color 0.15s' }}
            onDragOver={(e) => { e.preventDefault(); e.currentTarget.style.borderColor = '#3b82f6'; }}
            onDragLeave={(e) => { e.currentTarget.style.borderColor = '#3f3f46'; }}
            onDrop={async (e) => {
              e.preventDefault();
              e.currentTarget.style.borderColor = '#3f3f46';
              const file = e.dataTransfer.files?.[0];
              if (file && file.type.startsWith('image/')) await handleUpload(file);
            }}
            onClick={() => fileInputRef.current?.click()}
          >
            <i className="fa fa-cloud-upload" style={{ fontSize: 24, display: 'block', marginBottom: 6, color: '#3b82f6' }} />
            Drop image here or click to upload
          </div>
        )}

        {/* Action buttons: Upload + Browse */}
        <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: showBrowser ? '#3b82f6' : '#27272a', color: showBrowser ? '#fff' : '#e4e4e7' }}
          >
            <i className={`fa ${browserLoading ? 'fa-spinner fa-spin' : 'fa-folder-open'}`} style={{ marginRight: 4 }} /> Browse
          </button>
        </div>

        {/* Inline asset browser grid */}
        {showBrowser && (
          <div style={{ maxHeight: 200, overflowY: 'auto', display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 4, marginTop: 8, background: '#18181b', borderRadius: 6, padding: 4 }}>
            {browserAssets.map(asset => (
              <div
                key={asset.name}
                onClick={() => { setProp((p: ImageBlockProps) => { p.src = asset.url; }); setShowBrowser(false); }}
                style={{ cursor: 'pointer', borderRadius: 4, overflow: 'hidden', border: '2px solid transparent', aspectRatio: '1', transition: 'border-color 0.15s' }}
                onMouseEnter={(e) => { e.currentTarget.style.borderColor = '#3b82f6'; }}
                onMouseLeave={(e) => { e.currentTarget.style.borderColor = 'transparent'; }}
              >
                <img src={asset.url} alt={asset.name} style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
              </div>
            ))}
            {browserAssets.length === 0 && (
              <p style={{ gridColumn: '1 / -1', textAlign: 'center', color: '#71717a', fontSize: 11, padding: '12px 0', margin: 0 }}>No images uploaded yet. Use Upload above.</p>
            )}
          </div>
        )}

        <input ref={fileInputRef} type="file" accept="image/*" style={{ display: 'none' }}
          onChange={(e) => { const file = e.target.files?.[0]; if (file) handleUpload(file); e.target.value = ''; }} />

        {/* URL input (collapsed, for advanced users) */}
        <div style={{ marginTop: 6 }}>
          <input type="text"
            value={isPlaceholder ? '' : (props.src || '')}
            onChange={(e) => setProp((p: ImageBlockProps) => { p.src = e.target.value || PLACEHOLDER_SRC; })}
            placeholder="Or paste image URL..."
            style={{ width: '100%', padding: '4px 8px', background: '#1e1e2a', color: '#71717a', border: '1px solid #27272a', borderRadius: 4, fontSize: 10 }}
          />
        </div>
      </div>

      {/* Alt Text */}
      <div>
        <label style={labelStyle}>Alt Text</label>
        <input
          type="text"
          value={props.alt || ''}
          onChange={(e) => setProp((p: ImageBlockProps) => { p.alt = e.target.value; })}
          placeholder="Describe the image..."
          style={{ width: '100%', padding: '4px 8px', background: '#27272a', color: '#e4e4e7', border: '1px solid #3f3f46', borderRadius: 4, fontSize: 12 }}
        />
      </div>

      {/* Width */}
      <div>
        <label style={labelStyle}>Width</label>
        <div style={{ display: 'flex', gap: 4 }}>
          <input
            type="number"
            min={0}
            value={widthParsed.num}
            disabled={props.style?.width === 'auto'}
            onChange={(e) => {
              const val = buildSizeString(e.target.value, widthUnit);
              setPropStyle('width', val || 'auto');
            }}
            placeholder="auto"
            style={inputStyle}
          />
          <select
            value={props.style?.width === 'auto' ? 'auto' : widthUnit}
            onChange={(e) => {
              const unit = e.target.value as SizeUnit;
              if (unit === 'auto') {
                setPropStyle('width', 'auto');
              } else {
                setWidthUnit(unit);
                const num = widthParsed.num || '100';
                setPropStyle('width', `${num}${unit}`);
              }
            }}
            style={selectStyle}
          >
            <option value="px">px</option>
            <option value="%">%</option>
            <option value="auto">auto</option>
          </select>
        </div>
      </div>

      {/* Max Width */}
      <div>
        <label style={labelStyle}>Max Width</label>
        <div style={{ display: 'flex', gap: 4 }}>
          <input
            type="number"
            min={0}
            value={maxWidthParsed.num}
            onChange={(e) => {
              const val = buildSizeString(e.target.value, maxWidthUnit);
              setPropStyle('maxWidth', val || '100%');
            }}
            placeholder="100%"
            style={inputStyle}
          />
          <select
            value={maxWidthUnit}
            onChange={(e) => {
              const unit = e.target.value as SizeUnit;
              setMaxWidthUnit(unit);
              const num = maxWidthParsed.num || '100';
              setPropStyle('maxWidth', `${num}${unit}`);
            }}
            style={selectStyle}
          >
            <option value="px">px</option>
            <option value="%">%</option>
          </select>
        </div>
      </div>

      {/* Height */}
      <div>
        <label style={labelStyle}>Height</label>
        <div style={{ display: 'flex', gap: 4 }}>
          <input
            type="number"
            min={0}
            value={heightParsed.num}
            disabled={props.style?.height === 'auto'}
            onChange={(e) => {
              const val = buildSizeString(e.target.value, heightUnit);
              setPropStyle('height', val || 'auto');
            }}
            placeholder="auto"
            style={inputStyle}
          />
          <select
            value={props.style?.height === 'auto' ? 'auto' : heightUnit}
            onChange={(e) => {
              const unit = e.target.value as SizeUnit;
              if (unit === 'auto') {
                setPropStyle('height', 'auto');
              } else {
                setHeightUnit(unit);
                const num = heightParsed.num || '300';
                setPropStyle('height', `${num}${unit}`);
              }
            }}
            style={selectStyle}
          >
            <option value="px">px</option>
            <option value="auto">auto</option>
          </select>
        </div>
      </div>

      {/* Object Fit (visible when both width and height are explicit values) */}
      {props.style?.width && props.style.width !== 'auto' && props.style?.height && props.style.height !== 'auto' && (
        <div>
          <label style={labelStyle}>Object Fit</label>
          <div style={{ display: 'flex', gap: 4 }}>
            {(['cover', 'contain', 'fill', 'none'] as const).map((fit) => (
              <button
                key={fit}
                onClick={() => setPropStyle('objectFit', fit)}
                style={btnStyle(props.style?.objectFit === fit)}
              >
                {fit}
              </button>
            ))}
          </div>
        </div>
      )}

      {/* Alignment */}
      <div>
        <label style={labelStyle}>Alignment</label>
        <div style={{ display: 'flex', gap: 4 }}>
          <button onClick={() => setAlignment('left')} style={btnStyle(alignment === 'left')}>
            <i className="fa fa-align-left" style={{ marginRight: 3 }} />Left
          </button>
          <button onClick={() => setAlignment('center')} style={btnStyle(alignment === 'center')}>
            <i className="fa fa-align-center" style={{ marginRight: 3 }} />Center
          </button>
          <button onClick={() => setAlignment('right')} style={btnStyle(alignment === 'right')}>
            <i className="fa fa-align-right" style={{ marginRight: 3 }} />Right
          </button>
        </div>
      </div>

      {/* Border Radius */}
      <div>
        <label style={labelStyle}>Border Radius</label>
        <div style={{ display: 'flex', gap: 4 }}>
          {radiusPresets.map((r) => (
            <button key={r} onClick={() => setPropStyle('borderRadius', r)}
              style={btnStyle(props.style?.borderRadius === r)}
            >{r}</button>
          ))}
        </div>
      </div>
    </div>
  );
};

ImageBlock.craft = {
  displayName: 'Image',
  props: { src: PLACEHOLDER_SRC, alt: '', style: { width: '100%', height: 'auto' } },
  rules: { canDrag: () => true, canMoveIn: () => false, canMoveOut: () => true },
  related: { settings: ImageBlockSettings },
};

(ImageBlock as any).toHtml = (props: ImageBlockProps, _c: string) => {
  // Skip placeholder/empty images in export
  const src = props.src || '';
  if (!src || src.startsWith('data:image/svg') || src === PLACEHOLDER_SRC) {
    return { html: '' };
  }
  const s = cssPropsToString({ display: 'block', maxWidth: '100%', ...props.style });
  const alt = props.alt ? ` alt="${props.alt.replace(/"/g, '&quot;')}"` : ' alt=""';
  return { html: `<img src="${src}"${alt}${s ? ` style="${s}"` : ''} />` };
};
