'use client';

/**
 * MediaPicker — composant réutilisable par les modules consommateurs (Posts,
 * Pages, modules externes) pour choisir un média existant ou en uploader un.
 *
 * @example
 *   <MediaPicker
 *     isOpen={open}
 *     onClose={() => setOpen(false)}
 *     accept="image/*"
 *     visibility="public"
 *     onSelect={(media) => setFeaturedImage(media)}
 *   />
 */

import { useState, useEffect, useCallback, useRef } from 'react';
import { Modal, Button } from '@zen/core/shared/components';
import { useToast } from '@zen/core/toast';
import { CloudUploadIcon } from '@zen/core/shared/icons';
import MediaGrid from './MediaGrid.client.js';
import MediaFilters from './MediaFilters.client.js';

const MEDIA_API = '/zen/api/media';

function deriveKindFromAccept(accept) {
  if (!accept) return undefined;
  if (accept.startsWith('image/')) return 'image';
  if (accept.startsWith('video/')) return 'video';
  if (accept.startsWith('audio/')) return 'audio';
  if (accept === 'application/pdf') return 'document';
  return undefined;
}

export default function MediaPicker({
  isOpen,
  onClose,
  onSelect,
  accept,
  visibility,
  multiple = false,
  title = 'Sélectionner un média',
  uploadVisibility = 'public',
}) {
  const toast = useToast();
  const fileInputRef = useRef(null);
  const [items, setItems] = useState([]);
  const [loading, setLoading] = useState(true);
  const [uploading, setUploading] = useState(false);
  const [filters, setFilters] = useState({
    search: '',
    kind: deriveKindFromAccept(accept) ?? '',
    visibility: visibility && visibility !== 'any' ? visibility : '',
  });
  const [selectedIds, setSelectedIds] = useState(new Set());

  const fetchItems = useCallback(async () => {
    setLoading(true);
    try {
      const params = new URLSearchParams({ limit: '60' });
      if (filters.search)     params.set('search', filters.search);
      if (filters.kind)       params.set('kind', filters.kind);
      if (filters.visibility) params.set('visibility', filters.visibility);

      const response = await fetch(`${MEDIA_API}?${params}`, { credentials: 'include' });
      if (!response.ok) throw new Error('Échec du chargement');
      const data = await response.json();
      setItems(data.media || []);
    } catch (err) {
      toast.error(err.message || 'Échec du chargement des médias');
    } finally {
      setLoading(false);
    }
  }, [filters, toast]);

  useEffect(() => {
    if (!isOpen) return;
    fetchItems();
  }, [isOpen, fetchItems]);

  useEffect(() => {
    if (!isOpen) {
      setSelectedIds(new Set());
    }
  }, [isOpen]);

  const handleSelect = (media) => {
    if (multiple) {
      setSelectedIds(prev => {
        const next = new Set(prev);
        if (next.has(media.id)) next.delete(media.id);
        else next.add(media.id);
        return next;
      });
    } else {
      onSelect?.(media);
      onClose?.();
    }
  };

  const handleConfirmMultiple = () => {
    const selected = items.filter(m => selectedIds.has(m.id));
    onSelect?.(selected);
    onClose?.();
  };

  const handleUpload = async (event) => {
    const file = event.target.files?.[0];
    if (!file) return;

    setUploading(true);
    try {
      const formData = new FormData();
      formData.append('file', file);
      formData.append('visibility', uploadVisibility);

      const response = await fetch(MEDIA_API, {
        method: 'POST',
        credentials: 'include',
        body: formData,
      });
      const data = await response.json();
      if (!response.ok) throw new Error(data.message || 'Échec du téléversement');

      toast.success('Média téléversé');
      await fetchItems();

      if (!multiple && data.media) {
        onSelect?.(data.media);
        onClose?.();
      }
    } catch (err) {
      toast.error(err.message);
    } finally {
      setUploading(false);
      if (fileInputRef.current) fileInputRef.current.value = '';
    }
  };

  return (
    <Modal
      isOpen={isOpen}
      onClose={onClose}
      title={title}
      size="xl"
      footer={multiple ? (
        <div className="flex items-center justify-between">
          <span className="text-xs text-neutral-500">{selectedIds.size} sélectionné(s)</span>
          <div className="flex gap-2">
            <Button variant="ghost" onClick={onClose}>Annuler</Button>
            <Button variant="primary" onClick={handleConfirmMultiple} disabled={selectedIds.size === 0}>
              Sélectionner
            </Button>
          </div>
        </div>
      ) : (
        <div className="flex justify-end">
          <Button variant="ghost" onClick={onClose}>Fermer</Button>
        </div>
      )}
    >
      <div className="space-y-4">
        <div className="flex flex-col sm:flex-row gap-2 sm:items-center sm:justify-between">
          <div className="flex-1">
            <MediaFilters filters={filters} onChange={setFilters} />
          </div>
          <div>
            <input
              ref={fileInputRef}
              type="file"
              accept={accept}
              onChange={handleUpload}
              className="hidden"
            />
            <Button
              variant="secondary"
              icon={CloudUploadIcon}
              onClick={() => fileInputRef.current?.click()}
              loading={uploading}
            >
              Téléverser
            </Button>
          </div>
        </div>

        <MediaGrid
          items={items}
          loading={loading}
          onSelect={handleSelect}
          selectedIds={selectedIds}
          emptyMessage="Aucun média ne correspond aux filtres"
        />
      </div>
    </Modal>
  );
}
