/* Admin galería — álbumes con portada, varias fotos, categorías y evento */

const DEFAULT_ALBUM_FORM = {
  title: '',
  category_id: '',
  linkMode: 'date',
  event_id: '',
  album_date: '',
  description: '',
  published: true,
  sort_order: 0,
  cover_storage_path: '',
  cover_focus_x: 50,
  cover_focus_y: 50,
};

const formatEventOption = (ev) => {
  if (!ev?.starts_at) return ev?.title || 'Evento';
  const d = new Date(ev.starts_at).toLocaleDateString('es-MX', { day: 'numeric', month: 'short', year: 'numeric' });
  return `${d} — ${ev.title}`;
};

const albumMetaLine = (row) => {
  const cat = row.gallery_categories?.name || '—';
  const n = row.photoCount ?? row.photos?.length ?? 0;
  const ev = row.events;
  let when = '';
  if (ev?.title) when = ev.title;
  else if (row.album_date) {
    try {
      when = new Date(row.album_date + 'T12:00:00').toLocaleDateString('es-MX', { day: 'numeric', month: 'short', year: 'numeric' });
    } catch { when = row.album_date; }
  }
  return [cat, `${n} foto${n === 1 ? '' : 's'}`, when].filter(Boolean).join(' · ');
};

const AlbumFormModal = ({ open, onClose, theme, albumId, onSaved }) => {
  const [form, setForm] = React.useState({ ...DEFAULT_ALBUM_FORM });
  const [categories, setCategories] = React.useState([]);
  const [events, setEvents] = React.useState([]);
  const [existingPhotos, setExistingPhotos] = React.useState([]);
  const [coverFile, setCoverFile] = React.useState(null);
  const [extraFiles, setExtraFiles] = React.useState([]);
  const [coverItemId, setCoverItemId] = React.useState(null);
  const [removeIds, setRemoveIds] = React.useState([]);
  const [newCatName, setNewCatName] = React.useState('');
  const [addingCat, setAddingCat] = React.useState(false);
  const [saving, setSaving] = React.useState(false);
  const [loading, setLoading] = React.useState(false);
  const [err, setErr] = React.useState('');

  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  React.useEffect(() => {
    if (!open) return;
    setCoverFile(null);
    setExtraFiles([]);
    setRemoveIds([]);
    setCoverItemId(null);
    setErr('');
    setNewCatName('');
    (async () => {
      setLoading(true);
      try {
        const [cats, evs] = await Promise.all([
          fetchGalleryCategories(),
          fetchEventsForGalleryLink(),
        ]);
        setCategories(cats);
        setEvents(evs);
        if (albumId) {
          const album = await fetchGalleryAlbumById(albumId);
          const linkMode = album.event_id ? 'event' : (album.album_date ? 'date' : 'none');
          let albumDate = album.album_date || '';
          if (albumDate && typeof albumDate === 'string' && albumDate.length >= 10) {
            albumDate = albumDate.slice(0, 10);
          }
          setForm({
            title: album.title || '',
            category_id: album.category_id || album.gallery_categories?.id || '',
            linkMode,
            event_id: album.event_id || '',
            album_date: albumDate,
            description: album.description || '',
            published: album.published !== false,
            sort_order: album.sort_order ?? 0,
            cover_storage_path: album.cover_storage_path || '',
            cover_focus_x: Number(album.cover_focus_x) || 50,
            cover_focus_y: Number(album.cover_focus_y) || 50,
          });
          const photos = (album.photos || []).map(p => ({
            ...p,
            url: getStoragePublicUrl('gallery', p.storage_path),
          }));
          setExistingPhotos(photos);
          const cov = photos.find(p => p.is_cover) || photos[0];
          if (cov) setCoverItemId(cov.id);
        } else {
          setForm({
            ...DEFAULT_ALBUM_FORM,
            category_id: cats[0]?.id || '',
          });
          setExistingPhotos([]);
        }
      } catch (e) { setErr(e.message); }
      setLoading(false);
    })();
  }, [open, albumId]);

  const addCategory = async () => {
    if (!newCatName.trim()) return;
    setAddingCat(true);
    setErr('');
    try {
      const cat = await createGalleryCategory(newCatName.trim());
      setCategories(c => [...c, cat].sort((a, b) => a.sort_order - b.sort_order));
      set('category_id', cat.id);
      setNewCatName('');
    } catch (e) { setErr(e.message); }
    setAddingCat(false);
  };

  const onEventChange = (eventId) => {
    set('event_id', eventId);
    const ev = events.find(e => e.id === eventId);
    if (ev?.starts_at) {
      set('album_date', ev.starts_at.slice(0, 10));
    }
  };

  const toggleRemovePhoto = (id) => {
    setRemoveIds(ids => ids.includes(id) ? ids.filter(x => x !== id) : [...ids, id]);
    if (coverItemId === id) setCoverItemId(null);
  };

  const coverPreview = coverFile
    ? URL.createObjectURL(coverFile)
    : (existingPhotos.find(p => p.id === coverItemId)?.url
      || (form.cover_storage_path ? getStoragePublicUrl('gallery', form.cover_storage_path) : null));

  const save = async () => {
    if (!form.title?.trim()) { setErr('El título es obligatorio.'); return; }
    if (!form.category_id) { setErr('Elige o crea una categoría.'); return; }
    const visiblePhotos = existingPhotos.filter(p => !removeIds.includes(p.id));
    if (!albumId && !coverFile && !visiblePhotos.length && !extraFiles.length) {
      setErr('Agrega al menos la foto principal del álbum.');
      return;
    }
    setSaving(true);
    setErr('');
    try {
      let albumDate = null;
      let eventId = null;
      if (form.linkMode === 'event' && form.event_id) {
        eventId = form.event_id;
        albumDate = form.album_date || null;
      } else if (form.linkMode === 'date' && form.album_date) {
        albumDate = form.album_date;
      }

      const album = await saveGalleryAlbum({
        title: form.title,
        category_id: form.category_id,
        event_id: eventId,
        album_date: albumDate,
        description: form.description,
        published: form.published !== false,
        sort_order: form.sort_order,
        cover_storage_path: form.cover_storage_path || null,
        cover_focus_x: form.cover_focus_x,
        cover_focus_y: form.cover_focus_y,
      }, albumId || null);

      for (const pid of removeIds) {
        await deleteGalleryItem(pid);
      }

      let coverPath = form.cover_storage_path || null;
      let sortBase = visiblePhotos.length;

      if (coverFile) {
        const path = await uploadGalleryAlbumPhoto(coverFile, album.id, 0);
        await upsertGalleryItem({
          title: form.title,
          storage_path: path,
          album_id: album.id,
          is_cover: true,
          sort_order: 0,
        });
        coverPath = path;
      }

      for (let i = 0; i < extraFiles.length; i++) {
        const path = await uploadGalleryAlbumPhoto(extraFiles[i], album.id, sortBase + i);
        const makeCover = !coverPath && i === 0 && !coverFile;
        await upsertGalleryItem({
          title: form.title,
          storage_path: path,
          album_id: album.id,
          is_cover: makeCover,
          sort_order: sortBase + i,
        });
        if (makeCover) coverPath = path;
      }

      if (coverItemId && !coverFile) {
        const p = visiblePhotos.find(x => x.id === coverItemId);
        if (p) {
          coverPath = p.storage_path;
          await setGalleryAlbumCover(album.id, p.storage_path, p.id);
        }
      } else if (coverPath) {
        await setGalleryAlbumCover(album.id, coverPath, null);
      }

      notifyGalleryChanged();
      onSaved?.();
      onClose();
    } catch (e) { setErr(e.message); }
    setSaving(false);
  };

  return (
    <Modal open={open} onClose={onClose} theme={theme} title={albumId ? 'Editar álbum' : 'Nuevo álbum'} width={640}>
      <div style={{ padding: '8px 24px 24px', display: 'grid', gap: 14, maxHeight: '72vh', overflowY: 'auto' }}>
        {loading ? (
          <div style={{ color: theme.textDim, fontFamily: 'Inter, sans-serif', fontSize: 13 }}>Cargando…</div>
        ) : (
          <>
            <p style={{ margin: 0, fontSize: 12, color: theme.textDim, fontFamily: 'Inter, sans-serif', lineHeight: 1.5 }}>
              Crea un álbum con portada y varias fotos. Opcionalmente vincúlalo a un evento pasado o a una fecha.
            </p>
            <Input theme={theme} label="Título del álbum *" value={form.title} onChange={e => set('title', e.target.value)} />
            <div style={{ display: 'grid', gridTemplateColumns: '1fr auto', gap: 8, alignItems: 'end' }}>
              <div>
                <label style={{ fontSize: 11, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase', fontFamily: 'Inter, sans-serif' }}>Categoría *</label>
                <select value={form.category_id} onChange={e => set('category_id', e.target.value)}
                  style={{ width: '100%', marginTop: 6, padding: 12, borderRadius: 8, border: `1px solid ${theme.border}`, background: theme.bgInput, color: theme.text, fontFamily: 'Inter, sans-serif' }}>
                  <option value="">— Elegir —</option>
                  {categories.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
                </select>
              </div>
            </div>
            <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
              <Input theme={theme} label="Nueva categoría" value={newCatName} onChange={e => setNewCatName(e.target.value)} placeholder="Ej. Viajes" style={{ flex: 1, minWidth: 160 }} />
              <Btn theme={theme} kind="soft" size="sm" onClick={addCategory} disabled={addingCat || !newCatName.trim()}>
                {addingCat ? '…' : '+ Agregar'}
              </Btn>
            </div>

            <div>
              <label style={{ fontSize: 11, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase', fontFamily: 'Inter, sans-serif' }}>Fecha / evento</label>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginTop: 8 }}>
                {[
                  { v: 'date', l: 'Solo fecha del álbum' },
                  { v: 'event', l: 'Vincular a un evento (pasado o próximo)' },
                  { v: 'none', l: 'Sin fecha ni evento' },
                ].map(o => (
                  <label key={o.v} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13, color: theme.text, fontFamily: 'Inter, sans-serif', cursor: 'pointer' }}>
                    <input type="radio" name="linkMode" checked={form.linkMode === o.v} onChange={() => set('linkMode', o.v)} />
                    {o.l}
                  </label>
                ))}
              </div>
              {form.linkMode === 'date' && (
                <Input theme={theme} label="Fecha" type="date" value={form.album_date} onChange={e => set('album_date', e.target.value)} style={{ marginTop: 8 }} />
              )}
              {form.linkMode === 'event' && (
                <div style={{ marginTop: 8 }}>
                  <label style={{ fontSize: 11, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase', fontFamily: 'Inter, sans-serif' }}>Evento</label>
                  <select value={form.event_id} onChange={e => onEventChange(e.target.value)}
                    style={{ width: '100%', marginTop: 6, padding: 12, borderRadius: 8, border: `1px solid ${theme.border}`, background: theme.bgInput, color: theme.text, fontFamily: 'Inter, sans-serif' }}>
                    <option value="">— Seleccionar evento —</option>
                    {events.map(ev => <option key={ev.id} value={ev.id}>{formatEventOption(ev)}</option>)}
                  </select>
                  {form.event_id && form.album_date && (
                    <div style={{ fontSize: 11, color: theme.primary, marginTop: 6, fontFamily: 'Inter, sans-serif' }}>
                      En el sitio se mostrará como álbum de ese evento y fecha.
                    </div>
                  )}
                </div>
              )}
            </div>

            <div>
              <label style={{ fontSize: 11, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase', fontFamily: 'Inter, sans-serif' }}>Descripción (opcional)</label>
              <textarea value={form.description} onChange={e => set('description', e.target.value)} rows={2}
                style={{ width: '100%', marginTop: 6, padding: 12, borderRadius: 8, border: `1px solid ${theme.border}`, background: theme.bgInput, color: theme.text, fontFamily: 'Inter, sans-serif', resize: 'vertical' }} />
            </div>

            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
              <Input theme={theme} label="Orden" type="number" value={form.sort_order ?? 0} onChange={e => set('sort_order', e.target.value)} />
              <div>
                <label style={{ fontSize: 11, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase', fontFamily: 'Inter, sans-serif' }}>Publicado</label>
                <select value={form.published === false ? 'false' : 'true'} onChange={e => set('published', e.target.value === 'true')}
                  style={{ width: '100%', marginTop: 6, padding: 12, borderRadius: 8, border: `1px solid ${theme.border}`, background: theme.bgInput, color: theme.text, fontFamily: 'Inter, sans-serif' }}>
                  <option value="true">Sí — visible en landing</option>
                  <option value="false">No — borrador</option>
                </select>
              </div>
            </div>

            <div style={{ borderTop: `1px solid ${theme.border}`, paddingTop: 12 }}>
              <label style={{ fontSize: 11, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase', fontFamily: 'Inter, sans-serif' }}>Foto principal (portada)</label>
              <input type="file" accept="image/jpeg,image/png,image/webp" onChange={e => setCoverFile(e.target.files?.[0] || null)}
                style={{ marginTop: 8, fontSize: 12, fontFamily: 'Inter, sans-serif', display: 'block' }} />
              {coverPreview && (
                <div style={{ marginTop: 14 }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8, flexWrap: 'wrap', gap: 8 }}>
                    <span style={{ fontSize: 11, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase', fontFamily: 'Inter, sans-serif' }}>
                      Vista previa — tarjeta landing
                    </span>
                    <button type="button" onClick={() => { set('cover_focus_x', 50); set('cover_focus_y', 50); }}
                      style={{
                        fontSize: 11, padding: '4px 10px', borderRadius: 6, cursor: 'pointer',
                        border: `1px solid ${theme.border}`, background: theme.bgInput, color: theme.textDim,
                        fontFamily: 'Inter, sans-serif',
                      }}>
                      Centrar foto
                    </button>
                  </div>
                  <p style={{ margin: '0 0 10px', fontSize: 11, color: theme.textDim, fontFamily: 'Inter, sans-serif' }}>
                    Arrastra la foto para encuadrar. Así se verá en el landing.
                  </p>
                  <Card theme={theme} style={{ padding: 0, overflow: 'hidden', maxWidth: 168, margin: '0 auto', cursor: 'pointer' }}>
                    <LandingFocusPhotoFrame
                      theme={theme}
                      imageUrl={coverPreview}
                      focusX={form.cover_focus_x}
                      focusY={form.cover_focus_y}
                      onFocusChange={(x, y) => { set('cover_focus_x', x); set('cover_focus_y', y); }}
                      aspectRatio="4/3"
                      maxWidth={168}
                      badge={(existingPhotos.length + extraFiles.length) > 1 ? (
                        <div style={{
                          position: 'absolute', top: 8, right: 8, padding: '3px 8px', borderRadius: 999,
                          background: 'rgba(0,0,0,0.55)', fontSize: 9, fontWeight: 700, color: '#fff',
                          fontFamily: 'Inter, sans-serif', pointerEvents: 'none',
                        }}>{(existingPhotos.length + extraFiles.length) || 1} fotos</div>
                      ) : null}
                    />
                    <div style={{ padding: '10px 12px 12px' }}>
                      <div style={{ fontSize: 10, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase', fontFamily: 'Inter, sans-serif' }}>
                        {categories.find(c => c.id === form.category_id)?.name || 'Categoría'}
                      </div>
                      <div style={{ fontWeight: 600, fontSize: 13, color: theme.text, fontFamily: 'Inter, sans-serif', marginTop: 2, lineHeight: 1.2 }}>
                        {form.title?.trim() || 'Título del álbum'}
                      </div>
                    </div>
                  </Card>
                </div>
              )}
            </div>

            <div>
              <label style={{ fontSize: 11, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase', fontFamily: 'Inter, sans-serif' }}>Más fotos del álbum</label>
              <input type="file" accept="image/jpeg,image/png,image/webp" multiple
                onChange={e => setExtraFiles(Array.from(e.target.files || []))}
                style={{ marginTop: 8, fontSize: 12, fontFamily: 'Inter, sans-serif', display: 'block' }} />
              {extraFiles.length > 0 && (
                <div style={{ fontSize: 11, color: theme.textDim, marginTop: 4, fontFamily: 'Inter, sans-serif' }}>
                  {extraFiles.length} archivo(s) por subir
                </div>
              )}
            </div>

            {existingPhotos.length > 0 && (
              <div>
                <label style={{ fontSize: 11, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase', fontFamily: 'Inter, sans-serif' }}>Fotos actuales</label>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(72px, 1fr))', gap: 8, marginTop: 8 }}>
                  {existingPhotos.map(p => {
                    const removed = removeIds.includes(p.id);
                    const isCover = coverItemId === p.id && !removed;
                    return (
                      <div key={p.id} style={{
                        position: 'relative', borderRadius: 8, overflow: 'hidden',
                        border: `2px solid ${isCover ? theme.primary : theme.border}`,
                        opacity: removed ? 0.35 : 1,
                      }}>
                        <img src={p.url} alt="" style={{ width: '100%', aspectRatio: '1', objectFit: 'cover', display: 'block' }} />
                        <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', justifyContent: 'flex-end', gap: 2, padding: 4, background: 'linear-gradient(transparent, rgba(0,0,0,.7))' }}>
                          {!removed && (
                            <button type="button" onClick={() => setCoverItemId(p.id)}
                              style={{ fontSize: 8, padding: '2px 4px', border: 'none', borderRadius: 4, background: isCover ? theme.primary : 'rgba(255,255,255,.25)', color: '#fff', cursor: 'pointer' }}>
                              {isCover ? 'Portada' : 'Usar portada'}
                            </button>
                          )}
                          <button type="button" onClick={() => toggleRemovePhoto(p.id)}
                            style={{ fontSize: 8, padding: '2px 4px', border: 'none', borderRadius: 4, background: theme.danger, color: '#fff', cursor: 'pointer' }}>
                            {removed ? 'Restaurar' : 'Quitar'}
                          </button>
                        </div>
                      </div>
                    );
                  })}
                </div>
              </div>
            )}

            {err && <div style={{ color: theme.danger, fontSize: 13, fontFamily: 'Inter, sans-serif' }}>{err}</div>}
          </>
        )}
      </div>
      <div style={{ padding: '16px 24px', borderTop: `1px solid ${theme.border}`, display: 'flex', justifyContent: 'flex-end', gap: 10 }}>
        <Btn theme={theme} kind="ghost" onClick={onClose}>Cancelar</Btn>
        <Btn theme={theme} icon="check" onClick={save} disabled={saving || loading}>{saving ? 'Guardando…' : 'Guardar álbum'}</Btn>
      </div>
    </Modal>
  );
};

const GaleriaAlbumsAdminModule = ({ theme }) => {
  const { rows, loading, error, needsAuth, reload } = useAdminList(() => fetchGalleryAlbumsAdmin(), []);
  const [modal, setModal] = React.useState(null);

  const openNew = () => setModal('new');
  const openEdit = (id) => setModal(id);

  return (
    <AdminEntityShell theme={theme} title="GALERÍA" sub="Álbumes con portada, varias fotos, categorías y enlace a eventos." icon="image"
      onAdd={openNew}>
      {needsAuth ? <AuthRequired theme={theme} onRetry={reload} /> : loading ? <LoadingBlock theme={theme} /> : error ? (
        <EmptyState theme={theme} title="Error" message={error} />
      ) : (
        <Card theme={theme} style={{ padding: 0 }}>
          {rows.length === 0 ? (
            <EmptyState theme={theme} title="Sin álbumes" message="Crea un álbum con foto principal y más imágenes." icon="image"
              action={<Btn theme={theme} onClick={openNew}>Nuevo álbum</Btn>} />
          ) : rows.map(r => {
            const thumb = r.cover_storage_path
              ? getStoragePublicUrl('gallery', r.cover_storage_path)
              : (r.photos?.[0]?.storage_path ? getStoragePublicUrl('gallery', r.photos[0].storage_path) : null);
            return (
              <div key={r.id} style={{ padding: 14, borderBottom: `1px solid ${theme.border}`, display: 'flex', gap: 12, alignItems: 'center' }}>
                {thumb ? (
                  <img src={thumb} alt="" style={{ width: 48, height: 48, borderRadius: 8, objectFit: 'cover', flexShrink: 0 }} />
                ) : (
                  <div style={{
                    width: 48, height: 48, borderRadius: 8, background: theme.bgInput,
                    display: 'grid', placeItems: 'center', flexShrink: 0,
                  }}><Icon name="image" size={20} style={{ color: theme.textMute }} /></div>
                )}
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontWeight: 700 }}>{r.title}</div>
                  <div style={{ fontSize: 12, color: theme.textDim }}>{albumMetaLine(r)}</div>
                  {!r.published && (
                    <span style={{ fontSize: 10, color: theme.warning, fontWeight: 700 }}>Borrador</span>
                  )}
                </div>
                <RowActions theme={theme} onEdit={() => openEdit(r.id)}
                  onDelete={async () => {
                    if (confirm(`¿Eliminar el álbum «${r.title}» y todas sus fotos?`)) {
                      await deleteGalleryAlbum(r.id);
                      notifyGalleryChanged();
                      reload();
                    }
                  }} />
              </div>
            );
          })}
        </Card>
      )}
      <AlbumFormModal
        open={!!modal}
        onClose={() => setModal(null)}
        theme={theme}
        albumId={modal === 'new' ? null : modal}
        onSaved={reload}
      />
    </AdminEntityShell>
  );
};

Object.assign(window, { GaleriaAlbumsAdminModule, AlbumFormModal });
