// Resources store — backed by the Cloudflare Workers API.
//
// Public consumers (confirm page, mobile) call useResources() and get the
// list of uploaded resources (rows with an r2_key). Admin uses the same
// hook plus mutators for upload / rename / remove.
//
// Each row maps the backend's contentType → type so the existing UI keeps
// working without changes.

const _resourcesCache = { list: null, loading: false };

function _publish(list) {
  _resourcesCache.list = list;
  window.dispatchEvent(new CustomEvent('resourceschange', { detail: list }));
}

function _normalize(r) {
  // Backend returns { id, name, filename, size, contentType, hasFile, position, addedAt }.
  // Existing UI reads `type` and `addedAt`; map to keep shape stable.
  return {
    id: r.id,
    name: r.name,
    filename: r.filename,
    size: r.size,
    type: r.contentType,
    hasFile: !!r.hasFile,
    addedAt: r.addedAt,
    position: r.position,
    downloadUrl: window.api.API_BASE_URL + `/api/resources/${encodeURIComponent(r.id)}/download`,
  };
}

function formatFileSize(bytes) {
  if (!Number.isFinite(bytes) || bytes <= 0) return '—';
  const KB = 1024, MB = KB * 1024;
  if (bytes >= MB) return (bytes / MB).toFixed(1) + ' MB';
  if (bytes >= KB) return Math.round(bytes / KB) + ' KB';
  return bytes + ' B';
}

function useResources() {
  const [resources, setResources] = React.useState(() => _resourcesCache.list || []);
  const [loading, setLoading] = React.useState(_resourcesCache.list === null);
  const [error, setError] = React.useState(null);
  const adminMode = window.api.hasAdminToken();

  React.useEffect(() => {
    const onChange = (e) => setResources(e.detail || []);
    window.addEventListener('resourceschange', onChange);

    if (_resourcesCache.list === null && !_resourcesCache.loading) {
      _resourcesCache.loading = true;
      const path = adminMode ? '/api/admin/resources' : '/api/resources';
      window.api.apiGet(path)
        .then(r => _publish((r?.resources || []).map(_normalize)))
        .catch(err => setError(err))
        .finally(() => { _resourcesCache.loading = false; setLoading(false); });
    } else {
      setLoading(false);
    }

    return () => window.removeEventListener('resourceschange', onChange);
  }, [adminMode]);

  // Admin mutators. All async; existing UI calls them as fire-and-forget,
  // which is fine because the cache update fires a 'resourceschange' event.

  const add = React.useCallback(async (file) => {
    const r = await window.api.apiUpload('/api/admin/resources', file);
    if (r?.resource) {
      const list = [...(_resourcesCache.list || []), _normalize(r.resource)];
      _publish(list);
    }
  }, []);

  const rename = React.useCallback(async (id, newName) => {
    const r = await window.api.apiPatch(`/api/admin/resources/${encodeURIComponent(id)}`, { name: newName });
    if (r?.resource) {
      const list = (_resourcesCache.list || []).map(x => x.id === id ? _normalize(r.resource) : x);
      _publish(list);
    }
  }, []);

  const remove = React.useCallback(async (id) => {
    await window.api.apiDelete(`/api/admin/resources/${encodeURIComponent(id)}`);
    const list = (_resourcesCache.list || []).filter(x => x.id !== id);
    _publish(list);
  }, []);

  // No-op (defaults are server-side); kept so existing UI doesn't NPE.
  const reset = React.useCallback(async () => {
    if (!window.confirm('Reset is now a server operation. Run `npm run db:reset:local` on the backend.')) return;
  }, []);

  return [resources, { add, rename, remove, reset }];
}

Object.assign(window, { useResources, formatFileSize });
