/**
 * Custom Puck field for picking images from the Media Gallery
 */
import React, { useState, useEffect, useCallback } from 'react';
import { Image as ImageIcon, X, Upload, FolderOpen, Loader2 } from 'lucide-react';
import {
  listAlbums,
  listMediaFiles,
  uploadMediaFile,
  Album,
  MediaFile,
  formatFileSize,
  isAllowedFileType,
  isFileSizeAllowed,
  getStorageUsage,
  StorageUsage,
} from '../../api/media';

interface ImagePickerFieldProps {
  value: string;
  onChange: (value: string) => void;
  readOnly?: boolean;
}

/**
 * Image Picker Field Component
 * Shows a preview of the selected image and opens a modal to browse/select from gallery
 */
export const ImagePickerField: React.FC<ImagePickerFieldProps> = ({
  value,
  onChange,
  readOnly,
}) => {
  const [isOpen, setIsOpen] = useState(false);

  const handleSelect = (url: string) => {
    onChange(url);
    setIsOpen(false);
  };

  const handleClear = () => {
    onChange('');
  };

  return (
    <div className="space-y-2">
      {/* Preview */}
      {value ? (
        <div className="relative group">
          <img
            src={value}
            alt="Selected"
            className="w-full h-32 object-cover rounded-lg border border-gray-200"
          />
          {!readOnly && (
            <div className="absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity rounded-lg flex items-center justify-center gap-2">
              <button
                type="button"
                onClick={() => setIsOpen(true)}
                className="px-3 py-1.5 bg-white text-gray-800 rounded text-sm font-medium hover:bg-gray-100"
              >
                Change
              </button>
              <button
                type="button"
                onClick={handleClear}
                className="p-1.5 bg-red-500 text-white rounded hover:bg-red-600"
              >
                <X size={16} />
              </button>
            </div>
          )}
        </div>
      ) : (
        <button
          type="button"
          onClick={() => setIsOpen(true)}
          disabled={readOnly}
          className="w-full h-32 border-2 border-dashed border-gray-300 rounded-lg flex flex-col items-center justify-center gap-2 text-gray-500 hover:border-indigo-400 hover:text-indigo-500 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
        >
          <ImageIcon size={24} />
          <span className="text-sm">Select Image</span>
        </button>
      )}

      {/* URL input for manual entry */}
      <input
        type="text"
        value={value}
        onChange={(e) => onChange(e.target.value)}
        placeholder="Or paste image URL..."
        disabled={readOnly}
        className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 disabled:opacity-50"
      />

      {/* Gallery Modal */}
      {isOpen && (
        <ImagePickerModal
          onSelect={handleSelect}
          onClose={() => setIsOpen(false)}
          currentValue={value}
        />
      )}
    </div>
  );
};

/**
 * Modal for browsing and selecting images from the gallery
 */
interface ImagePickerModalProps {
  onSelect: (url: string) => void;
  onClose: () => void;
  currentValue?: string;
}

const ImagePickerModal: React.FC<ImagePickerModalProps> = ({
  onSelect,
  onClose,
  currentValue,
}) => {
  const [albums, setAlbums] = useState<Album[]>([]);
  const [files, setFiles] = useState<MediaFile[]>([]);
  const [selectedAlbumId, setSelectedAlbumId] = useState<number | 'all' | 'uncategorized'>('all');
  const [loading, setLoading] = useState(true);
  const [uploading, setUploading] = useState(false);
  const [storageUsage, setStorageUsage] = useState<StorageUsage | null>(null);
  const [error, setError] = useState<string | null>(null);

  // Load albums and files
  const loadData = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const [albumsData, storageData] = await Promise.all([
        listAlbums(),
        getStorageUsage(),
      ]);
      setAlbums(albumsData);
      setStorageUsage(storageData);

      // Load files based on selected album
      let filesData: MediaFile[];
      if (selectedAlbumId === 'all') {
        filesData = await listMediaFiles();
      } else if (selectedAlbumId === 'uncategorized') {
        filesData = await listMediaFiles('null');
      } else {
        filesData = await listMediaFiles(selectedAlbumId);
      }
      setFiles(filesData);
    } catch (err: any) {
      setError(err?.response?.data?.detail || 'Failed to load gallery');
    } finally {
      setLoading(false);
    }
  }, [selectedAlbumId]);

  useEffect(() => {
    loadData();
  }, [loadData]);

  // Handle file upload
  const handleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;

    if (!isAllowedFileType(file)) {
      setError('Only JPEG, PNG, GIF, and WebP images are allowed');
      return;
    }

    if (!isFileSizeAllowed(file)) {
      setError('File size must be less than 10 MB');
      return;
    }

    setUploading(true);
    setError(null);

    try {
      const albumId = typeof selectedAlbumId === 'number' ? selectedAlbumId : undefined;
      const uploaded = await uploadMediaFile(file, albumId);
      // Select the newly uploaded file
      onSelect(uploaded.url);
    } catch (err: any) {
      setError(err?.response?.data?.detail || err?.response?.data?.file?.[0] || 'Failed to upload file');
    } finally {
      setUploading(false);
      // Reset file input
      e.target.value = '';
    }
  };

  return (
    <div className="fixed inset-0 bg-black/60 flex items-center justify-center z-[9999] p-4">
      <div className="bg-white rounded-xl shadow-2xl w-full max-w-4xl max-h-[85vh] flex flex-col">
        {/* Header */}
        <div className="flex items-center justify-between px-6 py-4 border-b">
          <h2 className="text-lg font-semibold text-gray-900">Select Image</h2>
          <button
            onClick={onClose}
            className="p-1 hover:bg-gray-100 rounded-full transition-colors"
          >
            <X size={20} className="text-gray-500" />
          </button>
        </div>

        {/* Storage Usage Bar */}
        {storageUsage && (
          <div className="px-6 py-3 bg-gray-50 border-b">
            <div className="flex items-center justify-between text-sm mb-1">
              <span className="text-gray-600">Storage Used</span>
              <span className="text-gray-900 font-medium">
                {storageUsage.used_display} / {storageUsage.total_display}
              </span>
            </div>
            <div className="h-2 bg-gray-200 rounded-full overflow-hidden">
              <div
                className={`h-full rounded-full transition-all ${
                  storageUsage.percent_used > 90
                    ? 'bg-red-500'
                    : storageUsage.percent_used > 75
                    ? 'bg-amber-500'
                    : 'bg-indigo-500'
                }`}
                style={{ width: `${Math.min(storageUsage.percent_used, 100)}%` }}
              />
            </div>
          </div>
        )}

        {/* Album Filter */}
        <div className="px-6 py-3 border-b flex items-center gap-3 flex-wrap">
          <button
            onClick={() => setSelectedAlbumId('all')}
            className={`px-3 py-1.5 rounded-full text-sm font-medium transition-colors ${
              selectedAlbumId === 'all'
                ? 'bg-indigo-100 text-indigo-700'
                : 'bg-gray-100 text-gray-600 hover:bg-gray-200'
            }`}
          >
            All Files
          </button>
          <button
            onClick={() => setSelectedAlbumId('uncategorized')}
            className={`px-3 py-1.5 rounded-full text-sm font-medium transition-colors ${
              selectedAlbumId === 'uncategorized'
                ? 'bg-indigo-100 text-indigo-700'
                : 'bg-gray-100 text-gray-600 hover:bg-gray-200'
            }`}
          >
            Uncategorized
          </button>
          {albums.map((album) => (
            <button
              key={album.id}
              onClick={() => setSelectedAlbumId(album.id)}
              className={`px-3 py-1.5 rounded-full text-sm font-medium transition-colors flex items-center gap-1.5 ${
                selectedAlbumId === album.id
                  ? 'bg-indigo-100 text-indigo-700'
                  : 'bg-gray-100 text-gray-600 hover:bg-gray-200'
              }`}
            >
              <FolderOpen size={14} />
              {album.name}
              <span className="text-xs opacity-70">({album.file_count})</span>
            </button>
          ))}

          {/* Upload Button */}
          <label className="ml-auto">
            <input
              type="file"
              accept="image/jpeg,image/png,image/gif,image/webp"
              onChange={handleUpload}
              disabled={uploading}
              className="hidden"
            />
            <span className="inline-flex items-center gap-2 px-4 py-1.5 bg-indigo-600 text-white rounded-full text-sm font-medium cursor-pointer hover:bg-indigo-700 disabled:opacity-50">
              {uploading ? (
                <>
                  <Loader2 size={16} className="animate-spin" />
                  Uploading...
                </>
              ) : (
                <>
                  <Upload size={16} />
                  Upload
                </>
              )}
            </span>
          </label>
        </div>

        {/* Error Message */}
        {error && (
          <div className="px-6 py-3 bg-red-50 text-red-700 text-sm border-b">
            {error}
          </div>
        )}

        {/* Image Grid */}
        <div className="flex-1 overflow-y-auto p-6">
          {loading ? (
            <div className="flex items-center justify-center h-48">
              <Loader2 size={32} className="animate-spin text-indigo-600" />
            </div>
          ) : files.length === 0 ? (
            <div className="flex flex-col items-center justify-center h-48 text-gray-500">
              <ImageIcon size={48} className="mb-3 opacity-50" />
              <p className="text-lg font-medium">No images found</p>
              <p className="text-sm">Upload an image to get started</p>
            </div>
          ) : (
            <div className="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6 gap-3">
              {files.map((file) => (
                <button
                  key={file.id}
                  onClick={() => onSelect(file.url)}
                  className={`relative aspect-square rounded-lg overflow-hidden border-2 transition-all hover:shadow-lg ${
                    currentValue === file.url
                      ? 'border-indigo-500 ring-2 ring-indigo-200'
                      : 'border-gray-200 hover:border-indigo-300'
                  }`}
                >
                  <img
                    src={file.url}
                    alt={file.alt_text || file.filename}
                    className="w-full h-full object-cover"
                  />
                  {currentValue === file.url && (
                    <div className="absolute inset-0 bg-indigo-500/20 flex items-center justify-center">
                      <div className="w-6 h-6 bg-indigo-600 rounded-full flex items-center justify-center">
                        <svg className="w-4 h-4 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
                        </svg>
                      </div>
                    </div>
                  )}
                </button>
              ))}
            </div>
          )}
        </div>

        {/* Footer */}
        <div className="px-6 py-4 border-t flex items-center justify-end gap-3">
          <button
            onClick={onClose}
            className="px-4 py-2 text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 font-medium"
          >
            Cancel
          </button>
        </div>
      </div>
    </div>
  );
};

/**
 * Puck custom field configuration
 * Use this in component field definitions
 */
export const imagePickerField = {
  type: 'custom' as const,
  render: ({ value, onChange, readOnly }: { value: string; onChange: (val: string) => void; readOnly?: boolean }) => (
    <ImagePickerField value={value || ''} onChange={onChange} readOnly={readOnly} />
  ),
};

export default ImagePickerField;
