import React, { useState, useCallback, useRef, useEffect, CSSProperties } from 'react';
import { uploadAsset, listAssets, Asset } from '../utils/assets';
import { clickableProps } from '../utils/a11y';

export interface AssetPickerProps {
  value: string;
  onChange: (url: string) => void;
  /** Drives the file `<input accept>` and the `listAssets` grid filter. Default 'image'. */
  mediaType?: 'image' | 'video' | 'any';
  /** 'full' mirrors ImageStylePanel's source UI; 'compact' is a single tight row for array-editor cards. */
  variant?: 'full' | 'compact';
  placeholder?: string;
}

/* ---------- Pure helpers (exported for unit testing) ---------- */

/** File `<input accept>` value for a given mediaType; `undefined` (any file) for 'any'. */
export function acceptFor(mediaType: 'image' | 'video' | 'any'): string | undefined {
  if (mediaType === 'image') return 'image/*';
  if (mediaType === 'video') return 'video/*';
  return undefined;
}

/** Whether a dropped/selected file's MIME type is acceptable for the given mediaType. */
export function matchesMediaType(fileType: string, mediaType: 'image' | 'video' | 'any'): boolean {
  if (mediaType === 'any') return true;
  return fileType.startsWith(mediaType);
}

/** True when running outside WHP (no `window.WHP_CONFIG`) -- Browse should be hidden. */
export function isStandalone(): boolean {
  return typeof window === 'undefined' || !(window as any).WHP_CONFIG;
}

const previewBoxStyle: CSSProperties = {
  marginBottom: 8,
  borderRadius: 6,
  overflow: 'hidden',
  border: '1px solid #3f3f46',
  position: 'relative',
};

const removeBtnStyle: CSSProperties = {
  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',
};

const dropZoneStyle = (active: boolean): CSSProperties => ({
  padding: '20px 12px',
  border: `2px dashed ${active ? '#3b82f6' : '#3f3f46'}`,
  borderRadius: 6,
  textAlign: 'center',
  color: '#71717a',
  fontSize: 12,
  cursor: 'pointer',
  marginBottom: 8,
  transition: 'border-color 0.15s',
});

const uploadBtnStyle: CSSProperties = {
  flex: 1,
  padding: '8px 10px',
  fontSize: 12,
  borderRadius: 4,
  cursor: 'pointer',
  border: '1px solid #3f3f46',
  background: '#3b82f6',
  color: '#fff',
  fontWeight: 500,
};

const browseBtnStyle = (active: boolean): CSSProperties => ({
  flex: 1,
  padding: '8px 10px',
  fontSize: 12,
  borderRadius: 4,
  cursor: 'pointer',
  border: '1px solid #3f3f46',
  background: active ? '#3b82f6' : '#27272a',
  color: active ? '#fff' : '#e4e4e7',
});

const gridStyle: CSSProperties = {
  maxHeight: 200,
  overflowY: 'auto',
  display: 'grid',
  gridTemplateColumns: 'repeat(3, 1fr)',
  gap: 4,
  marginTop: 8,
  background: '#18181b',
  borderRadius: 6,
  padding: 4,
};

export const AssetPicker: React.FC<AssetPickerProps> = ({
  value,
  onChange,
  mediaType = 'image',
  variant = 'full',
  placeholder = 'Or paste URL...',
}) => {
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [showBrowser, setShowBrowser] = useState(false);
  const [browserAssets, setBrowserAssets] = useState<Asset[]>([]);
  const [browserLoading, setBrowserLoading] = useState(false);
  const [urlValue, setUrlValue] = useState(value || '');
  const [dragOver, setDragOver] = useState(false);
  const standalone = isStandalone();

  useEffect(() => {
    setUrlValue(value || '');
  }, [value]);

  const handleUpload = useCallback(async (file: File) => {
    const url = await uploadAsset(file);
    if (url) {
      onChange(url);
      setUrlValue(url);
    }
  }, [onChange]);

  const handleBrowseToggle = useCallback(async () => {
    if (showBrowser) {
      setShowBrowser(false);
      return;
    }
    setBrowserLoading(true);
    try {
      const assets = await listAssets(mediaType);
      setBrowserAssets(assets);
      setShowBrowser(true);
    } finally {
      setBrowserLoading(false);
    }
  }, [showBrowser, mediaType]);

  const handleSelectAsset = useCallback((asset: Asset) => {
    onChange(asset.url);
    setUrlValue(asset.url);
    setShowBrowser(false);
  }, [onChange]);

  const handleApplyUrl = useCallback(() => {
    onChange(urlValue);
  }, [urlValue, onChange]);

  const handleRemove = useCallback(() => {
    onChange('');
    setUrlValue('');
  }, [onChange]);

  const handleDrop = useCallback(async (e: React.DragEvent) => {
    e.preventDefault();
    setDragOver(false);
    const file = e.dataTransfer.files?.[0];
    if (file && matchesMediaType(file.type, mediaType)) {
      await handleUpload(file);
    }
  }, [handleUpload, mediaType]);

  const accept = acceptFor(mediaType);
  const hasValue = !!value;

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

  const grid = showBrowser && (
    <div style={gridStyle} data-testid="asset-picker-grid">
      {browserAssets.map((asset) => (
        <div
          key={asset.name}
          {...clickableProps(() => handleSelectAsset(asset))}
          data-testid={`asset-picker-thumb-${asset.name}`}
          style={{ cursor: 'pointer', borderRadius: 4, overflow: 'hidden', border: '2px solid transparent', aspectRatio: '1' }}
        >
          <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 assets uploaded yet. Use Upload above.
        </p>
      )}
    </div>
  );

  const browseButton = !standalone && (
    <button
      type="button"
      onClick={handleBrowseToggle}
      data-testid="asset-picker-browse"
      style={variant === 'full' ? browseBtnStyle(showBrowser) : { ...browseBtnStyle(showBrowser), flex: 'none', padding: '6px 8px' }}
    >
      <i className={`fa ${browserLoading ? 'fa-spinner fa-spin' : 'fa-folder-open'}`} style={{ marginRight: variant === 'full' ? 4 : 0 }} />
      {variant === 'full' && 'Browse'}
    </button>
  );

  if (variant === 'compact') {
    return (
      <div data-testid="asset-picker-compact">
        <div style={{ display: 'flex', gap: 4, alignItems: 'center' }}>
          {hasValue && (
            <div style={{ width: 28, height: 28, borderRadius: 4, overflow: 'hidden', border: '1px solid #3f3f46', flex: 'none', position: 'relative' }}>
              <img src={value} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
              <button
                type="button"
                onClick={handleRemove}
                title="Remove"
                data-testid="asset-picker-remove"
                style={{ position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.5)', border: 'none', color: '#fff', fontSize: 9, cursor: 'pointer', opacity: 0 }}
                onMouseEnter={(e) => { e.currentTarget.style.opacity = '1'; }}
                onMouseLeave={(e) => { e.currentTarget.style.opacity = '0'; }}
              >
                <i className="fa fa-times" />
              </button>
            </div>
          )}
          <button
            type="button"
            onClick={() => fileInputRef.current?.click()}
            data-testid="asset-picker-upload"
            style={{ flex: 'none', padding: '6px 8px', fontSize: 11, borderRadius: 4, cursor: 'pointer', border: '1px solid #3f3f46', background: '#3b82f6', color: '#fff' }}
            title="Upload"
          >
            <i className="fa fa-upload" />
          </button>
          {browseButton}
          <input
            type="text"
            className="guided-input"
            value={urlValue}
            placeholder={placeholder}
            onChange={(e) => { setUrlValue(e.target.value); }}
            onBlur={handleApplyUrl}
            onKeyDown={(e) => { if (e.key === 'Enter') handleApplyUrl(); }}
            data-testid="asset-picker-url-input"
            style={{ flex: 1, fontSize: 11, minWidth: 0 }}
          />
        </div>
        {grid}
        {fileInput}
      </div>
    );
  }

  return (
    <div data-testid="asset-picker-full">
      {hasValue ? (
        <div style={previewBoxStyle}>
          <img src={value} alt="" style={{ width: '100%', height: 'auto', display: 'block', maxHeight: 150, objectFit: 'cover' }} data-testid="asset-picker-preview" />
          <button
            type="button"
            onClick={handleRemove}
            title="Remove"
            data-testid="asset-picker-remove"
            style={removeBtnStyle}
          >
            <i className="fa fa-times" />
          </button>
        </div>
      ) : (
        <div
          style={dropZoneStyle(dragOver)}
          onDragOver={(e) => { e.preventDefault(); setDragOver(true); }}
          onDragLeave={() => setDragOver(false)}
          onDrop={handleDrop}
          onClick={() => fileInputRef.current?.click()}
          data-testid="asset-picker-dropzone"
        >
          <i className="fa fa-cloud-upload" style={{ fontSize: 24, display: 'block', marginBottom: 6, color: '#3b82f6' }} />
          Drop {mediaType === 'video' ? 'video' : mediaType === 'any' ? 'file' : 'image'} here or click to upload
        </div>
      )}

      <div style={{ display: 'flex', gap: 4 }}>
        <button
          type="button"
          onClick={() => fileInputRef.current?.click()}
          data-testid="asset-picker-upload"
          style={uploadBtnStyle}
        >
          <i className="fa fa-upload" style={{ marginRight: 4 }} /> Upload
        </button>
        {browseButton}
      </div>

      {grid}
      {fileInput}

      <div style={{ marginTop: 6 }}>
        <div className="guided-input-row">
          <input
            type="text"
            className="guided-input"
            value={urlValue}
            placeholder={placeholder}
            onChange={(e) => setUrlValue(e.target.value)}
            data-testid="asset-picker-url-input"
            style={{ fontSize: 11 }}
          />
          <button
            type="button"
            className="preset-btn apply-btn"
            onClick={handleApplyUrl}
            data-testid="asset-picker-apply"
          >
            Apply
          </button>
        </div>
      </div>
    </div>
  );
};
